diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index f6eae07f1..5a0aaf4fb 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -247,182 +247,6 @@ GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsi return Program; } -GLuint getTextureGLuint(irr::video::ITexture *tex) -{ - return static_cast(tex)->getOpenGLTextureName(); -} - -GLuint getDepthTexture(irr::video::ITexture *tex) -{ - assert(tex->isRenderTarget()); - return static_cast(tex)->DepthBufferTexture; -} - -std::set AlreadyTransformedTexture; -void resetTextureTable() -{ - AlreadyTransformedTexture.clear(); -} - -void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha) -{ - if (AlreadyTransformedTexture.find(tex) != AlreadyTransformedTexture.end()) - return; - AlreadyTransformedTexture.insert(tex); - - glBindTexture(GL_TEXTURE_2D, getTextureGLuint(tex)); - - std::string cached_file; - if (UserConfigParams::m_texture_compression) - { - // Try to retrieve the compressed texture in cache - std::string tex_name = irr_driver->getTextureName(tex); - if (!tex_name.empty()) { - cached_file = file_manager->getTextureCacheLocation(tex_name) + ".gltz"; - if (!file_manager->fileIsNewer(tex_name, cached_file)) { - if (loadCompressedTexture(cached_file)) - return; - } - } - } - - size_t w = tex->getSize().Width, h = tex->getSize().Height; - unsigned char *data = new unsigned char[w * h * 4]; - memcpy(data, tex->lock(), w * h * 4); - tex->unlock(); - unsigned internalFormat, Format; - if (tex->hasAlpha()) - Format = GL_BGRA; - else - Format = GL_BGR; - - if (premul_alpha) - { - for (unsigned i = 0; i < w * h; i++) - { - float alpha = data[4 * i + 3]; - if (alpha > 0.) - alpha = pow(alpha / 255.f, 1.f / 2.2f); - data[4 * i ] = (unsigned char)(data[4 * i ] * alpha); - data[4 * i + 1] = (unsigned char)(data[4 * i + 1] * alpha); - data[4 * i + 2] = (unsigned char)(data[4 * i + 2] * alpha); - } - } - - if (!UserConfigParams::m_texture_compression) - { - if (srgb) - internalFormat = (tex->hasAlpha()) ? GL_SRGB_ALPHA : GL_SRGB; - else - internalFormat = (tex->hasAlpha()) ? GL_RGBA : GL_RGB; - } - else - { - if (srgb) - internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; - else - internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - } - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, Format, GL_UNSIGNED_BYTE, (GLvoid *)data); - glGenerateMipmap(GL_TEXTURE_2D); - delete[] data; - - if (UserConfigParams::m_texture_compression && !cached_file.empty()) - { - // Save the compressed texture in the cache for later use. - saveCompressedTexture(cached_file); - } -} - -//----------------------------------------------------------------------------- -/** Try to load a compressed texture from the given file name. - * Data in the specified file need to have a specific format. See the - * saveCompressedTexture() function for a description of the format. - * \return true if the loading succeeded, false otherwise. - * \see saveCompressedTexture - */ -bool loadCompressedTexture(const std::string& compressed_tex) -{ - std::ifstream ifs(compressed_tex.c_str(), std::ios::in | std::ios::binary); - if (!ifs.is_open()) - return false; - - int internal_format; - int w, h; - int size = -1; - ifs.read((char*)&internal_format, sizeof(int)); - ifs.read((char*)&w, sizeof(int)); - ifs.read((char*)&h, sizeof(int)); - ifs.read((char*)&size, sizeof(int)); - - if (ifs.fail() || size == -1) - return false; - - char *data = new char[size]; - ifs.read(data, size); - if (!ifs.fail()) - { - glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format, - w, h, 0, size, (GLvoid*)data); - glGenerateMipmap(GL_TEXTURE_2D); - delete[] data; - ifs.close(); - return true; - } - delete[] data; - return false; -} - -//----------------------------------------------------------------------------- -/** Try to save the last texture sent to glTexImage2D in a file of the given - * file name. This function should only be used for textures sent to - * glTexImage2D with a compressed internal format as argument.
- * \note The following format is used to save the compressed texture:
- *
- * The first four elements are integers and the last one is stored - * on \c size bytes. - * \see loadCompressedTexture - */ -void saveCompressedTexture(const std::string& compressed_tex) -{ - int internal_format, width, height, size, compressionSuccessful; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&internal_format); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint *)&width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint *)&height); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, (GLint *)&compressionSuccessful); - if (!compressionSuccessful) - return; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&size); - - char *data = new char[size]; - glGetCompressedTexImage(GL_TEXTURE_2D, 0, (GLvoid*)data); - std::ofstream ofs(compressed_tex.c_str(), std::ios::out | std::ios::binary); - if (ofs.is_open()) - { - ofs.write((char*)&internal_format, sizeof(int)); - ofs.write((char*)&width, sizeof(int)); - ofs.write((char*)&height, sizeof(int)); - ofs.write((char*)&size, sizeof(int)); - ofs.write(data, size); - ofs.close(); - } - delete[] data; -} - -static unsigned colorcount = 0; - -video::ITexture* getUnicolorTexture(video::SColor c) -{ - video::SColor tmp[4] = { - c, c, c, c - }; - video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d(2, 2), tmp); - img->grab(); - std::string name("color"); - name += colorcount++; - return irr_driver->getVideoDriver()->addTexture(name.c_str(), img); -} - void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF) { glActiveTexture(GL_TEXTURE0 + TextureUnit); diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index 8fa49c6c4..672a4d61e 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -129,13 +129,7 @@ public: // core::rect needs these includes #include #include "utils/vec3.hpp" - -GLuint getTextureGLuint(irr::video::ITexture *tex); -GLuint getDepthTexture(irr::video::ITexture *tex); -void resetTextureTable(); -void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false); -bool loadCompressedTexture(const std::string& compressed_tex); -void saveCompressedTexture(const std::string& compressed_tex); +#include "texturemanager.hpp" void draw3DLine(const core::vector3df& start, const core::vector3df& end, irr::video::SColor color); diff --git a/src/graphics/texturemanager.cpp b/src/graphics/texturemanager.cpp new file mode 100644 index 000000000..74d9c548b --- /dev/null +++ b/src/graphics/texturemanager.cpp @@ -0,0 +1,182 @@ +#include "texturemanager.hpp" +#include +#include +#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h" +#include "irr_driver.hpp" + + +GLuint getTextureGLuint(irr::video::ITexture *tex) +{ + return static_cast(tex)->getOpenGLTextureName(); +} + +GLuint getDepthTexture(irr::video::ITexture *tex) +{ + assert(tex->isRenderTarget()); + return static_cast(tex)->DepthBufferTexture; +} + +std::set AlreadyTransformedTexture; +void resetTextureTable() +{ + AlreadyTransformedTexture.clear(); +} + +void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha) +{ + if (AlreadyTransformedTexture.find(tex) != AlreadyTransformedTexture.end()) + return; + AlreadyTransformedTexture.insert(tex); + + glBindTexture(GL_TEXTURE_2D, getTextureGLuint(tex)); + + std::string cached_file; + if (UserConfigParams::m_texture_compression) + { + // Try to retrieve the compressed texture in cache + std::string tex_name = irr_driver->getTextureName(tex); + if (!tex_name.empty()) { + cached_file = file_manager->getTextureCacheLocation(tex_name) + ".gltz"; + if (!file_manager->fileIsNewer(tex_name, cached_file)) { + if (loadCompressedTexture(cached_file)) + return; + } + } + } + + size_t w = tex->getSize().Width, h = tex->getSize().Height; + unsigned char *data = new unsigned char[w * h * 4]; + memcpy(data, tex->lock(), w * h * 4); + tex->unlock(); + unsigned internalFormat, Format; + if (tex->hasAlpha()) + Format = GL_BGRA; + else + Format = GL_BGR; + + if (premul_alpha) + { + for (unsigned i = 0; i < w * h; i++) + { + float alpha = data[4 * i + 3]; + if (alpha > 0.) + alpha = pow(alpha / 255.f, 1.f / 2.2f); + data[4 * i] = (unsigned char)(data[4 * i] * alpha); + data[4 * i + 1] = (unsigned char)(data[4 * i + 1] * alpha); + data[4 * i + 2] = (unsigned char)(data[4 * i + 2] * alpha); + } + } + + if (!UserConfigParams::m_texture_compression) + { + if (srgb) + internalFormat = (tex->hasAlpha()) ? GL_SRGB_ALPHA : GL_SRGB; + else + internalFormat = (tex->hasAlpha()) ? GL_RGBA : GL_RGB; + } + else + { + if (srgb) + internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + else + internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + } + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, Format, GL_UNSIGNED_BYTE, (GLvoid *)data); + glGenerateMipmap(GL_TEXTURE_2D); + delete[] data; + + if (UserConfigParams::m_texture_compression && !cached_file.empty()) + { + // Save the compressed texture in the cache for later use. + saveCompressedTexture(cached_file); + } +} + +//----------------------------------------------------------------------------- +/** Try to load a compressed texture from the given file name. +* Data in the specified file need to have a specific format. See the +* saveCompressedTexture() function for a description of the format. +* \return true if the loading succeeded, false otherwise. +* \see saveCompressedTexture +*/ +bool loadCompressedTexture(const std::string& compressed_tex) +{ + std::ifstream ifs(compressed_tex.c_str(), std::ios::in | std::ios::binary); + if (!ifs.is_open()) + return false; + + int internal_format; + int w, h; + int size = -1; + ifs.read((char*)&internal_format, sizeof(int)); + ifs.read((char*)&w, sizeof(int)); + ifs.read((char*)&h, sizeof(int)); + ifs.read((char*)&size, sizeof(int)); + + if (ifs.fail() || size == -1) + return false; + + char *data = new char[size]; + ifs.read(data, size); + if (!ifs.fail()) + { + glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format, + w, h, 0, size, (GLvoid*)data); + glGenerateMipmap(GL_TEXTURE_2D); + delete[] data; + ifs.close(); + return true; + } + delete[] data; + return false; +} + +//----------------------------------------------------------------------------- +/** Try to save the last texture sent to glTexImage2D in a file of the given +* file name. This function should only be used for textures sent to +* glTexImage2D with a compressed internal format as argument.
+* \note The following format is used to save the compressed texture:
+*
+* The first four elements are integers and the last one is stored +* on \c size bytes. +* \see loadCompressedTexture +*/ +void saveCompressedTexture(const std::string& compressed_tex) +{ + int internal_format, width, height, size, compressionSuccessful; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&internal_format); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint *)&width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint *)&height); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, (GLint *)&compressionSuccessful); + if (!compressionSuccessful) + return; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&size); + + char *data = new char[size]; + glGetCompressedTexImage(GL_TEXTURE_2D, 0, (GLvoid*)data); + std::ofstream ofs(compressed_tex.c_str(), std::ios::out | std::ios::binary); + if (ofs.is_open()) + { + ofs.write((char*)&internal_format, sizeof(int)); + ofs.write((char*)&width, sizeof(int)); + ofs.write((char*)&height, sizeof(int)); + ofs.write((char*)&size, sizeof(int)); + ofs.write(data, size); + ofs.close(); + } + delete[] data; +} + +static unsigned colorcount = 0; + +video::ITexture* getUnicolorTexture(video::SColor c) +{ + video::SColor tmp[4] = { + c, c, c, c + }; + video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d(2, 2), tmp); + img->grab(); + std::string name("color"); + name += colorcount++; + return irr_driver->getVideoDriver()->addTexture(name.c_str(), img); +} \ No newline at end of file diff --git a/src/graphics/texturemanager.hpp b/src/graphics/texturemanager.hpp new file mode 100644 index 000000000..89489d8c1 --- /dev/null +++ b/src/graphics/texturemanager.hpp @@ -0,0 +1,15 @@ +#ifndef MEMORYMANAGER_HPP +#define MEMORYMANAGER_HPP + +#include "gl_headers.hpp" +#include +#include + +GLuint getTextureGLuint(irr::video::ITexture *tex); +GLuint getDepthTexture(irr::video::ITexture *tex); +void resetTextureTable(); +void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false); +bool loadCompressedTexture(const std::string& compressed_tex); +void saveCompressedTexture(const std::string& compressed_tex); + +#endif \ No newline at end of file