void TextureFactory::reloadObject(LoadableObject::Pointer object, ObjectsCache&) { TextureDescription::Pointer newData = et::loadTexture(object->origin()); if (newData.valid()) Texture::Pointer(object)->updateData(renderContext(), newData); }
Texture TextureFactory::loadTexture(const std::string& fileName, ObjectsCache& cache, bool async, TextureLoaderDelegate* delegate) { if (fileName.length() == 0) return Texture(); CriticalSectionScope lock(_csTextureLoading); std::string file = application().environment().resolveScalableFileName(fileName, renderContext()->screenScaleFactor()); if (!fileExists(file)) { log::error("Unable to find texture file: %s", file.c_str()); return Texture(); } uint64_t cachedFileProperty = 0; Texture texture = cache.findAnyObject(file, &cachedFileProperty); if (texture.invalid()) { TextureDescription::Pointer desc = async ? et::loadTextureDescription(file, false) : et::loadTexture(file); if (desc.valid()) { bool calledFromAnotherThread = Threading::currentThread() != threading().renderingThread(); texture = Texture(new TextureData(renderContext(), desc, desc->origin(), async || calledFromAnotherThread)); cache.manage(texture, ObjectLoader::Pointer(this)); if (async) _loadingThread->addRequest(desc->origin(), texture, delegate); else if (calledFromAnotherThread) assert(false && "ERROR: Unable to load texture synchronously from non-rendering thread."); } } else { auto newProperty = cache.getFileProperty(file); if (cachedFileProperty != newProperty) reloadObject(texture, cache); if (async && (delegate != nullptr)) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidStartLoading, texture); i.invokeInMainRunLoop(); i.setTarget(delegate, &TextureLoaderDelegate::textureDidLoad, texture); i.invokeInMainRunLoop(); } } return texture; }
void Framebuffer::resize(const vec2i& sz) { if (_description.size.xy() == sz) return; forceSize(sz); bool hasColor = (_description.colorInternalformat != TextureFormat::Invalid) && (_description.colorIsRenderbuffer || (_description.colorFormat != TextureFormat::Invalid)); bool hasDepth = (_description.depthInternalformat != TextureFormat::Invalid) && (_description.depthIsRenderbuffer || (_description.depthFormat != TextureFormat::Invalid)); if (hasColor) { if (_description.colorIsRenderbuffer) { for (uint32_t& renderBuffer : _colorRenderBuffers) renderBuffer = buildColorRenderbuffer(renderBuffer); } else { for (auto rt : _renderTargets) { TextureDescription::Pointer desc = rt->description(); desc->size = sz; desc->data.resize(desc->layersCount * desc->dataSizeForAllMipLevels()); desc->data.fill(0); rt->updateData(_rc, desc); setCurrentRenderTarget(rt); } } } if (hasDepth) { if (_description.depthIsRenderbuffer) { createOrUpdateDepthRenderbuffer(); } else if (_depthBuffer.valid()) { auto desc = _depthBuffer->description(); desc->size = sz; desc->data.resize(desc->layersCount * desc->dataSizeForAllMipLevels()); desc->data.fill(0); _depthBuffer->updateData(_rc, desc); setDepthTarget(_depthBuffer); } } if (hasColor || hasDepth) checkStatus(); }
Texture::Pointer TextureFactory::genCubeTexture(TextureFormat internalformat, uint32_t size, TextureFormat format, DataType type, const std::string& aName) { TextureDescription::Pointer desc = TextureDescription::Pointer::create(); desc->target = TextureTarget::Texture_Cube; desc->format = format; desc->internalformat = internalformat; desc->type = type; desc->size = vec2i(size); desc->mipMapCount = 1; desc->layersCount = 6; desc->bitsPerPixel = bitsPerPixelForTextureFormat(internalformat, type); desc->data = BinaryDataStorage(desc->layersCount * desc->dataSizeForAllMipLevels(), 0); return Texture::Pointer::create(renderContext(), desc, aName, false); }
Texture::Texture(RenderContext* rc, const TextureDescription::Pointer& desc, const std::string& id, bool deferred) : APIObject(id, desc->origin()), _desc(desc), _own(true) { #if (ET_OPENGLES) if (!(isPowerOfTwo(desc->size.x) && isPowerOfTwo(desc->size.y))) _wrap = vector3<TextureWrap>(TextureWrap::ClampToEdge); const auto& caps = OpenGLCapabilities::instance(); if ((_desc->internalformat == TextureFormat::R) && (caps.version() > OpenGLVersion::Version_2x)) _desc->internalformat = TextureFormat::R8; #endif if (deferred) { buildProperies(); } else { generateTexture(rc); build(rc); } }
int main(int argc, char* argv[]) { log::addOutput(log::ConsoleOutput::Pointer::create()); bool hasPattern = false; bool hasRoot = false; bool hasOutput = false; bool addSpace = true; std::string rootFolder; std::string outFile; std::string pattern = "texture_%d.png"; int outputSize = 1024; for (int i = 1; i < argc; ++i) { if ((strcmp(argv[i], "-root") == 0) && (i + 1 < argc)) { rootFolder = addTrailingSlash(std::string(argv[i+1])); if (folderExists(rootFolder)) { hasRoot = true; ++i; } else { log::error("Root folder not found: %s", rootFolder.c_str()); return 0; } } else if ((strcmp(argv[i], "-out") == 0) && (i + 1 < argc)) { outFile = std::string(argv[i+1]); hasOutput = true; ++i; } else if ((strcmp(argv[i], "-pattern") == 0) && (i + 1 < argc)) { pattern = std::string(argv[i+1]); hasPattern = true; ++i; } else if (strcmp(argv[i], "-nospace") == 0) { addSpace = false; } else if ((strcmp(argv[i], "-size") == 0) && (i + 1 < argc)) { outputSize = strToInt(std::string(argv[i+1])); ++i; } } if (!hasRoot || !hasOutput) { printHelp(); return 0; } StringList fileList; TextureDescription::List textureDescriptors; findFiles(rootFolder, "*.png", true, fileList); for (auto i : fileList) { TextureDescription::Pointer desc = TextureDescription::Pointer::create(); png::loadInfoFromFile(i, desc.reference()); if ((desc->size.x > outputSize) || (desc->size.y > outputSize)) { log::error("Image %s is larger (%d x %d) than ouput size (%d x %d), use -size option", i.c_str(), desc->size.x, desc->size.y, outputSize, outputSize); return 0; } textureDescriptors.push_back(desc); } std::sort(textureDescriptors.begin(), textureDescriptors.end(), [](const TextureDescription::Pointer& d1, const TextureDescription::Pointer& d2) { return d1->size.square() > d2->size.square(); }); TextureAtlasWriter placer(addSpace); while (textureDescriptors.size()) { TextureAtlasWriter::TextureAtlasItem& texture = placer.addItem(vec2i(outputSize)); TextureDescription::List::iterator i = textureDescriptors.begin(); int placedItems = 0; while (i != textureDescriptors.end()) { if (placer.placeImage(*i, texture)) { ++placedItems; i = textureDescriptors.erase(i); } else { ++i; } } texture.texture->size.x = static_cast<int>(roundToHighestPowerOfTwo(texture.maxWidth)); texture.texture->size.y = static_cast<int>(roundToHighestPowerOfTwo(texture.maxHeight)); } for (const auto i : placer.items()) { log::info("Texture: %d x %d", i.texture->size.x, i.texture->size.y); for (const auto& ii : i.images) { log::info("(% 5d, % 5d) | (% 5d % 5d) | %s", static_cast<int>(ii.place.origin.x), static_cast<int>(ii.place.origin.y), static_cast<int>(ii.place.size.x), static_cast<int>(ii.place.size.y), getFileName(ii.image->origin()).c_str()); } } placer.writeToFile(outFile, pattern.c_str()); return 0; }
Texture::Pointer TextureFactory::loadTexture(const std::string& fileName, ObjectsCache& cache, bool async, TextureLoaderDelegate* delegate) { if (fileName.length() == 0) return Texture::Pointer(); CriticalSectionScope lock(_csTextureLoading); auto file = resolveTextureName(fileName); if (!fileExists(file)) return Texture::Pointer(); uint64_t cachedFileProperty = 0; Texture::Pointer texture = cache.findAnyObject(file, &cachedFileProperty); if (texture.invalid()) { TextureDescription::Pointer desc = async ? et::loadTextureDescription(file, false) : et::loadTexture(file); int maxTextureSize = static_cast<int>(RenderingCapabilities::instance().maxTextureSize()); if ((desc->size.x > maxTextureSize) || (desc->size.y > maxTextureSize)) { log::warning("Attempt to load texture with dimensions (%d x %d) larger than max allowed (%d)", desc->size.x, desc->size.y, maxTextureSize); } if (desc.valid()) { bool calledFromAnotherThread = !threading::inMainThread(); texture = Texture::Pointer::create(renderContext(), desc, desc->origin(), async || calledFromAnotherThread); cache.manage(texture, _private->loader); if (async) { _loadingThread->addRequest(desc->origin(), texture, delegate); } else if (calledFromAnotherThread) { ET_FAIL("ERROR: Unable to load texture synchronously from non-rendering thread."); } } } else { auto newProperty = cache.getFileProperty(file); if (cachedFileProperty != newProperty) reloadObject(texture, cache); if (async) { textureDidStartLoading.invokeInMainRunLoop(texture); if (delegate != nullptr) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidStartLoading, texture); i.invokeInMainRunLoop(); } textureDidLoad.invokeInMainRunLoop(texture); if (delegate != nullptr) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidLoad, texture); i.invokeInMainRunLoop(); } } } return texture; }
Texture::Pointer TextureFactory::genTexture(TextureDescription::Pointer desc) { return Texture::Pointer::create(renderContext(), desc, desc->origin(), false); }
Texture TextureFactory::genTexture(TextureDescription::Pointer desc) { return Texture(new TextureData(renderContext(), desc, desc->origin(), false)); }