| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- #include "anki/resource/Texture.h"
- #include "anki/resource/Image.h"
- #include "anki/gl/GlException.h"
- #include "anki/util/Exception.h"
- #include <GL/glew.h>
- #include <boost/lexical_cast.hpp>
- namespace anki {
- #define LAST_TEX_UNIT (textureUnitsNum - 1)
- //==============================================================================
- // Statics =
- //==============================================================================
- int Texture::textureUnitsNum = -1;
- bool Texture::mipmappingEnabled = true;
- bool Texture::compressionEnabled = false;
- int Texture::anisotropyLevel = 8;
- //==============================================================================
- // Constructor =
- //==============================================================================
- Texture::Texture():
- glId(std::numeric_limits<uint>::max()),
- target(GL_TEXTURE_2D)
- {}
- //==============================================================================
- // Destructor =
- //==============================================================================
- Texture::~Texture()
- {
- if(isLoaded())
- {
- glDeleteTextures(1, &glId);
- }
- }
- //==============================================================================
- // load (const char*) =
- //==============================================================================
- void Texture::load(const char* filename)
- {
- try
- {
- load(Image(filename));
- }
- catch(std::exception& e)
- {
- throw ANKI_EXCEPTION("File \"" + filename + "\"") << e;
- }
- }
- //==============================================================================
- // load (const Image&) =
- //==============================================================================
- void Texture::load(const Image& img)
- {
- Initializer init;
- init.width = img.getWidth();
- init.height = img.getHeight();
- init.dataSize = img.getDataSize();
- switch(img.getColorType())
- {
- case Image::CT_R:
- init.internalFormat = (compressionEnabled) ?
- GL_COMPRESSED_RED : GL_RED;
- init.format = GL_RED;
- init.type = GL_UNSIGNED_BYTE;
- break;
- case Image::CT_RGB:
- init.internalFormat = (compressionEnabled) ?
- GL_COMPRESSED_RGB : GL_RGB;
- init.format = GL_RGB;
- init.type = GL_UNSIGNED_BYTE;
- break;
- case Image::CT_RGBA:
- init.internalFormat = (compressionEnabled) ?
- GL_COMPRESSED_RGBA : GL_RGBA;
- init.format = GL_RGBA;
- init.type = GL_UNSIGNED_BYTE;
- break;
- default:
- throw ANKI_EXCEPTION("See file: " +
- boost::lexical_cast<std::string>(img.getColorType()));
- }
- switch(img.getDataCompression())
- {
- case Image::DC_NONE:
- init.dataCompression = DC_NONE;
- break;
- case Image::DC_DXT1:
- init.dataCompression = DC_DXT1;
- init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- break;
- case Image::DC_DXT3:
- init.dataCompression = DC_DXT3;
- init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
- break;
- case Image::DC_DXT5:
- init.dataCompression = DC_DXT5;
- init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- break;
- }
- init.data = img.getData();
- init.mipmapping = mipmappingEnabled;
- init.filteringType = mipmappingEnabled ? TFT_TRILINEAR : TFT_LINEAR;
- init.repeat = true;
- init.anisotropyLevel = anisotropyLevel;
- create(init);
- }
- //==============================================================================
- // create =
- //==============================================================================
- void Texture::create(const Initializer& init_)
- {
- Initializer init = init_;
- //
- // Sanity checks
- //
- if(isLoaded())
- {
- throw ANKI_EXCEPTION("Already loaded");
- }
- if(init.internalFormat <= 4)
- {
- throw ANKI_EXCEPTION("Deprecated internal format");
- }
- //
- // Create
- //
- glGenTextures(1, &glId);
- bind(LAST_TEX_UNIT);
- target = GL_TEXTURE_2D;
- internalFormat = init.internalFormat;
- format = init.format;
- type = init.type;
- if(init.data == NULL)
- {
- init.dataCompression = DC_NONE;
- }
- switch(init.dataCompression)
- {
- case DC_NONE:
- glTexImage2D(target, 0, init.internalFormat, init.width,
- init.height, 0, init.format, init.type, init.data);
- break;
- case DC_DXT1:
- case DC_DXT3:
- case DC_DXT5:
- glCompressedTexImage2D(target, 0, init.internalFormat,
- init.width, init.height, 0, init.dataSize, init.data);
- break;
- default:
- throw ANKI_EXCEPTION("Incorrect data compression value");
- }
- setRepeat(init.repeat);
- if(init.mipmapping)
- {
- glGenerateMipmap(target);
- }
- // If not mipmapping then the filtering cannot be trilinear
- if(init.filteringType == TFT_TRILINEAR && !init.mipmapping)
- {
- setFiltering(TFT_LINEAR);
- }
- else
- {
- setFiltering(init.filteringType);
- }
- if(init.anisotropyLevel > 1)
- {
- setTexParameter(GL_TEXTURE_MAX_ANISOTROPY_EXT,
- float(init.anisotropyLevel));
- }
- ANKI_CHECK_GL_ERROR();
- }
- //==============================================================================
- // bind =
- //==============================================================================
- void Texture::bind(uint unit) const
- {
- if(unit >= static_cast<uint>(textureUnitsNum))
- {
- throw ANKI_EXCEPTION("Max tex units passed");
- }
- glActiveTexture(GL_TEXTURE0 + unit);
- glBindTexture(target, getGlId());
- }
- //==============================================================================
- // getWidth =
- //==============================================================================
- int Texture::getWidth(uint level) const
- {
- bind(LAST_TEX_UNIT);
- int i;
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &i);
- return i;
- }
- //==============================================================================
- // getHeight =
- //==============================================================================
- int Texture::getHeight(uint level) const
- {
- bind(LAST_TEX_UNIT);
- int i;
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &i);
- return i;
- }
- //==============================================================================
- // setTexParameter [int] =
- //==============================================================================
- void Texture::setTexParameter(uint paramName, int value) const
- {
- bind(LAST_TEX_UNIT);
- glTexParameteri(target, paramName, value);
- }
- //==============================================================================
- // setTexParameter [float] =
- //==============================================================================
- void Texture::setTexParameter(uint paramName, float value) const
- {
- bind(LAST_TEX_UNIT);
- glTexParameterf(target, paramName, value);
- }
- //==============================================================================
- // setRepeat =
- //==============================================================================
- void Texture::setRepeat(bool repeat) const
- {
- bind(LAST_TEX_UNIT);
- if(repeat)
- {
- setTexParameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
- setTexParameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- else
- {
- setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- }
- //==============================================================================
- // getBaseLevel =
- //==============================================================================
- int Texture::getBaseLevel() const
- {
- bind(LAST_TEX_UNIT);
- int level;
- glGetTexParameteriv(target, GL_TEXTURE_BASE_LEVEL, &level);
- return level;
- }
- //==============================================================================
- // getActiveTexUnit =
- //==============================================================================
- uint Texture::getActiveTexUnit()
- {
- int unit;
- glGetIntegerv(GL_ACTIVE_TEXTURE, &unit);
- return unit - GL_TEXTURE0;
- }
- //==============================================================================
- // getBindedTexId =
- //==============================================================================
- uint Texture::getBindedTexId(uint unit)
- {
- int id;
- glActiveTexture(GL_TEXTURE0 + unit);
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &id);
- return id;
- }
- //==============================================================================
- // getMaxLevel =
- //==============================================================================
- int Texture::getMaxLevel() const
- {
- bind(LAST_TEX_UNIT);
- int level;
- glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &level);
- return level;
- }
- //==============================================================================
- // setAnisotropy =
- //==============================================================================
- void Texture::setAnisotropy(uint level)
- {
- bind(LAST_TEX_UNIT);
- setTexParameter(GL_TEXTURE_MAX_ANISOTROPY_EXT, int(level));
- }
- //==============================================================================
- // setMipmapLevel =
- //==============================================================================
- void Texture::setMipmapLevel(uint level)
- {
- bind(LAST_TEX_UNIT);
- setTexParameter(GL_TEXTURE_BASE_LEVEL, int(level));
- }
- //==============================================================================
- // genMipmap =
- //==============================================================================
- void Texture::genMipmap()
- {
- bind(LAST_TEX_UNIT);
- glGenerateMipmap(target);
- }
- //==============================================================================
- // setFiltering =
- //==============================================================================
- void Texture::setFiltering(TextureFilteringType filterType)
- {
- switch(filterType)
- {
- case TFT_NEAREST:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- case TFT_LINEAR:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- break;
- case TFT_TRILINEAR:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
- }
- } // end namespace
|