Texture.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "anki/resource/Texture.h"
  2. #include "anki/resource/Image.h"
  3. #include "anki/gl/GlException.h"
  4. #include "anki/util/Exception.h"
  5. #include <GL/glew.h>
  6. #include <boost/lexical_cast.hpp>
  7. namespace anki {
  8. #define LAST_TEX_UNIT (textureUnitsNum - 1)
  9. //==============================================================================
  10. // Statics =
  11. //==============================================================================
  12. int Texture::textureUnitsNum = -1;
  13. bool Texture::mipmappingEnabled = true;
  14. bool Texture::compressionEnabled = false;
  15. int Texture::anisotropyLevel = 8;
  16. //==============================================================================
  17. // Constructor =
  18. //==============================================================================
  19. Texture::Texture():
  20. glId(std::numeric_limits<uint>::max()),
  21. target(GL_TEXTURE_2D)
  22. {}
  23. //==============================================================================
  24. // Destructor =
  25. //==============================================================================
  26. Texture::~Texture()
  27. {
  28. if(isLoaded())
  29. {
  30. glDeleteTextures(1, &glId);
  31. }
  32. }
  33. //==============================================================================
  34. // load (const char*) =
  35. //==============================================================================
  36. void Texture::load(const char* filename)
  37. {
  38. try
  39. {
  40. load(Image(filename));
  41. }
  42. catch(std::exception& e)
  43. {
  44. throw ANKI_EXCEPTION("File \"" + filename + "\"") << e;
  45. }
  46. }
  47. //==============================================================================
  48. // load (const Image&) =
  49. //==============================================================================
  50. void Texture::load(const Image& img)
  51. {
  52. Initializer init;
  53. init.width = img.getWidth();
  54. init.height = img.getHeight();
  55. init.dataSize = img.getDataSize();
  56. switch(img.getColorType())
  57. {
  58. case Image::CT_R:
  59. init.internalFormat = (compressionEnabled) ?
  60. GL_COMPRESSED_RED : GL_RED;
  61. init.format = GL_RED;
  62. init.type = GL_UNSIGNED_BYTE;
  63. break;
  64. case Image::CT_RGB:
  65. init.internalFormat = (compressionEnabled) ?
  66. GL_COMPRESSED_RGB : GL_RGB;
  67. init.format = GL_RGB;
  68. init.type = GL_UNSIGNED_BYTE;
  69. break;
  70. case Image::CT_RGBA:
  71. init.internalFormat = (compressionEnabled) ?
  72. GL_COMPRESSED_RGBA : GL_RGBA;
  73. init.format = GL_RGBA;
  74. init.type = GL_UNSIGNED_BYTE;
  75. break;
  76. default:
  77. throw ANKI_EXCEPTION("See file: " +
  78. boost::lexical_cast<std::string>(img.getColorType()));
  79. }
  80. switch(img.getDataCompression())
  81. {
  82. case Image::DC_NONE:
  83. init.dataCompression = DC_NONE;
  84. break;
  85. case Image::DC_DXT1:
  86. init.dataCompression = DC_DXT1;
  87. init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
  88. break;
  89. case Image::DC_DXT3:
  90. init.dataCompression = DC_DXT3;
  91. init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  92. break;
  93. case Image::DC_DXT5:
  94. init.dataCompression = DC_DXT5;
  95. init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  96. break;
  97. }
  98. init.data = img.getData();
  99. init.mipmapping = mipmappingEnabled;
  100. init.filteringType = mipmappingEnabled ? TFT_TRILINEAR : TFT_LINEAR;
  101. init.repeat = true;
  102. init.anisotropyLevel = anisotropyLevel;
  103. create(init);
  104. }
  105. //==============================================================================
  106. // create =
  107. //==============================================================================
  108. void Texture::create(const Initializer& init_)
  109. {
  110. Initializer init = init_;
  111. //
  112. // Sanity checks
  113. //
  114. if(isLoaded())
  115. {
  116. throw ANKI_EXCEPTION("Already loaded");
  117. }
  118. if(init.internalFormat <= 4)
  119. {
  120. throw ANKI_EXCEPTION("Deprecated internal format");
  121. }
  122. //
  123. // Create
  124. //
  125. glGenTextures(1, &glId);
  126. bind(LAST_TEX_UNIT);
  127. target = GL_TEXTURE_2D;
  128. internalFormat = init.internalFormat;
  129. format = init.format;
  130. type = init.type;
  131. if(init.data == NULL)
  132. {
  133. init.dataCompression = DC_NONE;
  134. }
  135. switch(init.dataCompression)
  136. {
  137. case DC_NONE:
  138. glTexImage2D(target, 0, init.internalFormat, init.width,
  139. init.height, 0, init.format, init.type, init.data);
  140. break;
  141. case DC_DXT1:
  142. case DC_DXT3:
  143. case DC_DXT5:
  144. glCompressedTexImage2D(target, 0, init.internalFormat,
  145. init.width, init.height, 0, init.dataSize, init.data);
  146. break;
  147. default:
  148. throw ANKI_EXCEPTION("Incorrect data compression value");
  149. }
  150. setRepeat(init.repeat);
  151. if(init.mipmapping)
  152. {
  153. glGenerateMipmap(target);
  154. }
  155. // If not mipmapping then the filtering cannot be trilinear
  156. if(init.filteringType == TFT_TRILINEAR && !init.mipmapping)
  157. {
  158. setFiltering(TFT_LINEAR);
  159. }
  160. else
  161. {
  162. setFiltering(init.filteringType);
  163. }
  164. if(init.anisotropyLevel > 1)
  165. {
  166. setTexParameter(GL_TEXTURE_MAX_ANISOTROPY_EXT,
  167. float(init.anisotropyLevel));
  168. }
  169. ANKI_CHECK_GL_ERROR();
  170. }
  171. //==============================================================================
  172. // bind =
  173. //==============================================================================
  174. void Texture::bind(uint unit) const
  175. {
  176. if(unit >= static_cast<uint>(textureUnitsNum))
  177. {
  178. throw ANKI_EXCEPTION("Max tex units passed");
  179. }
  180. glActiveTexture(GL_TEXTURE0 + unit);
  181. glBindTexture(target, getGlId());
  182. }
  183. //==============================================================================
  184. // getWidth =
  185. //==============================================================================
  186. int Texture::getWidth(uint level) const
  187. {
  188. bind(LAST_TEX_UNIT);
  189. int i;
  190. glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &i);
  191. return i;
  192. }
  193. //==============================================================================
  194. // getHeight =
  195. //==============================================================================
  196. int Texture::getHeight(uint level) const
  197. {
  198. bind(LAST_TEX_UNIT);
  199. int i;
  200. glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &i);
  201. return i;
  202. }
  203. //==============================================================================
  204. // setTexParameter [int] =
  205. //==============================================================================
  206. void Texture::setTexParameter(uint paramName, int value) const
  207. {
  208. bind(LAST_TEX_UNIT);
  209. glTexParameteri(target, paramName, value);
  210. }
  211. //==============================================================================
  212. // setTexParameter [float] =
  213. //==============================================================================
  214. void Texture::setTexParameter(uint paramName, float value) const
  215. {
  216. bind(LAST_TEX_UNIT);
  217. glTexParameterf(target, paramName, value);
  218. }
  219. //==============================================================================
  220. // setRepeat =
  221. //==============================================================================
  222. void Texture::setRepeat(bool repeat) const
  223. {
  224. bind(LAST_TEX_UNIT);
  225. if(repeat)
  226. {
  227. setTexParameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
  228. setTexParameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
  229. }
  230. else
  231. {
  232. setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  233. setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  234. }
  235. }
  236. //==============================================================================
  237. // getBaseLevel =
  238. //==============================================================================
  239. int Texture::getBaseLevel() const
  240. {
  241. bind(LAST_TEX_UNIT);
  242. int level;
  243. glGetTexParameteriv(target, GL_TEXTURE_BASE_LEVEL, &level);
  244. return level;
  245. }
  246. //==============================================================================
  247. // getActiveTexUnit =
  248. //==============================================================================
  249. uint Texture::getActiveTexUnit()
  250. {
  251. int unit;
  252. glGetIntegerv(GL_ACTIVE_TEXTURE, &unit);
  253. return unit - GL_TEXTURE0;
  254. }
  255. //==============================================================================
  256. // getBindedTexId =
  257. //==============================================================================
  258. uint Texture::getBindedTexId(uint unit)
  259. {
  260. int id;
  261. glActiveTexture(GL_TEXTURE0 + unit);
  262. glGetIntegerv(GL_TEXTURE_BINDING_2D, &id);
  263. return id;
  264. }
  265. //==============================================================================
  266. // getMaxLevel =
  267. //==============================================================================
  268. int Texture::getMaxLevel() const
  269. {
  270. bind(LAST_TEX_UNIT);
  271. int level;
  272. glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &level);
  273. return level;
  274. }
  275. //==============================================================================
  276. // setAnisotropy =
  277. //==============================================================================
  278. void Texture::setAnisotropy(uint level)
  279. {
  280. bind(LAST_TEX_UNIT);
  281. setTexParameter(GL_TEXTURE_MAX_ANISOTROPY_EXT, int(level));
  282. }
  283. //==============================================================================
  284. // setMipmapLevel =
  285. //==============================================================================
  286. void Texture::setMipmapLevel(uint level)
  287. {
  288. bind(LAST_TEX_UNIT);
  289. setTexParameter(GL_TEXTURE_BASE_LEVEL, int(level));
  290. }
  291. //==============================================================================
  292. // genMipmap =
  293. //==============================================================================
  294. void Texture::genMipmap()
  295. {
  296. bind(LAST_TEX_UNIT);
  297. glGenerateMipmap(target);
  298. }
  299. //==============================================================================
  300. // setFiltering =
  301. //==============================================================================
  302. void Texture::setFiltering(TextureFilteringType filterType)
  303. {
  304. switch(filterType)
  305. {
  306. case TFT_NEAREST:
  307. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  308. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  309. break;
  310. case TFT_LINEAR:
  311. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  312. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  313. break;
  314. case TFT_TRILINEAR:
  315. glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
  316. GL_LINEAR_MIPMAP_LINEAR);
  317. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  318. }
  319. }
  320. } // end namespace