Texture.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include "Base.h"
  2. #include "Image.h"
  3. #include "Texture.h"
  4. namespace gameplay
  5. {
  6. static std::vector<Texture*> __textureCache;
  7. Texture::Texture() : _handle(0), _mipmapped(false), _cached(false)
  8. {
  9. }
  10. Texture::Texture(const Texture& copy)
  11. {
  12. }
  13. Texture::~Texture()
  14. {
  15. if (_handle)
  16. {
  17. glDeleteTextures(1, &_handle);
  18. _handle = 0;
  19. }
  20. // Remove ourself from the texture cache.
  21. if (_cached)
  22. {
  23. std::vector<Texture*>::iterator itr = std::find(__textureCache.begin(), __textureCache.end(), this);
  24. if (itr != __textureCache.end())
  25. {
  26. __textureCache.erase(itr);
  27. }
  28. }
  29. }
  30. Texture* Texture::create(const char* path, bool generateMipmaps)
  31. {
  32. // Search texture cache first.
  33. for (unsigned int i = 0, count = __textureCache.size(); i < count; ++i)
  34. {
  35. Texture* t = __textureCache[i];
  36. if (t->_path == path)
  37. {
  38. // If 'generateMipmaps' is true, call Texture::generateMipamps() to force the
  39. // texture to generate its mipmap chain if it hasn't already done so.
  40. if (generateMipmaps)
  41. {
  42. t->generateMipmaps();
  43. }
  44. // Found a match.
  45. t->addRef();
  46. return t;
  47. }
  48. }
  49. Texture* texture = NULL;
  50. // Filter loading based on file extension.
  51. const char* ext = strrchr(path, '.');
  52. if (ext)
  53. {
  54. switch (strlen(ext))
  55. {
  56. case 4:
  57. if (tolower(ext[1]) == 'p' && tolower(ext[2]) == 'n' && tolower(ext[3]) == 'g')
  58. {
  59. Image* image = Image::create(path);
  60. if (image)
  61. texture = create(image, generateMipmaps);
  62. SAFE_RELEASE(image);
  63. }
  64. break;
  65. }
  66. }
  67. if (texture)
  68. {
  69. texture->_path = path;
  70. texture->_cached = true;
  71. // Add to texture cache.
  72. __textureCache.push_back(texture);
  73. return texture;
  74. }
  75. LOG_ERROR_VARG("Failed to load texture: %s", path);
  76. return NULL;
  77. }
  78. Texture* Texture::create(Image* image, bool generateMipmaps)
  79. {
  80. switch (image->getFormat())
  81. {
  82. case Image::RGB:
  83. return create(Texture::RGB, image->getWidth(), image->getHeight(), image->getData(), generateMipmaps);
  84. case Image::RGBA:
  85. return create(Texture::RGBA, image->getWidth(), image->getHeight(), image->getData(), generateMipmaps);
  86. }
  87. return NULL;
  88. }
  89. Texture* Texture::create(Format format, unsigned int width, unsigned int height, unsigned char* data, bool generateMipmaps)
  90. {
  91. // Load our texture.
  92. GLuint textureId;
  93. GL_ASSERT( glGenTextures(1, &textureId) );
  94. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, textureId) );
  95. if (format == DEPTH)
  96. {
  97. // <type> must be UNSIGNED_SHORT or UNSIGNED_INT for a format of DEPTH_COMPONENT.
  98. GL_ASSERT( glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)format, width, height, 0, (GLenum)format, GL_UNSIGNED_INT, data) );
  99. }
  100. else
  101. {
  102. GL_ASSERT( glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)format, width, height, 0, (GLenum)format, GL_UNSIGNED_BYTE, data) );
  103. }
  104. // Set initial minification filter based on whether or not mipmaping was enabled
  105. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, generateMipmaps ? GL_NEAREST_MIPMAP_LINEAR : GL_LINEAR) );
  106. Texture* texture = new Texture();
  107. texture->_handle = textureId;
  108. texture->_width = width;
  109. texture->_height = height;
  110. if (generateMipmaps)
  111. {
  112. texture->generateMipmaps();
  113. }
  114. return texture;
  115. }
  116. unsigned int Texture::getWidth() const
  117. {
  118. return _width;
  119. }
  120. unsigned int Texture::getHeight() const
  121. {
  122. return _height;
  123. }
  124. TextureHandle Texture::getHandle() const
  125. {
  126. return _handle;
  127. }
  128. void Texture::setWrapMode(Wrap wrapS, Wrap wrapT)
  129. {
  130. GLint currentTextureId;
  131. GL_ASSERT( glGetIntegerv(GL_TEXTURE_BINDING_2D, &currentTextureId) );
  132. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, _handle) );
  133. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLenum)wrapS) );
  134. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLenum)wrapT) );
  135. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, (GLuint)currentTextureId) );
  136. }
  137. void Texture::setFilterMode(Filter minificationFilter, Filter magnificationFilter)
  138. {
  139. GLint currentTextureId;
  140. GL_ASSERT( glGetIntegerv(GL_TEXTURE_BINDING_2D, &currentTextureId) );
  141. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, _handle) );
  142. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLenum)minificationFilter) );
  143. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLenum)magnificationFilter) );
  144. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, (GLuint)currentTextureId) );
  145. }
  146. void Texture::generateMipmaps()
  147. {
  148. if (!_mipmapped)
  149. {
  150. GLint currentTextureId;
  151. GL_ASSERT( glGetIntegerv(GL_TEXTURE_BINDING_2D, &currentTextureId) );
  152. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, _handle) );
  153. GL_ASSERT( glGenerateMipmap(GL_TEXTURE_2D) );
  154. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, (GLuint)currentTextureId) );
  155. _mipmapped = true;
  156. }
  157. }
  158. bool Texture::isMipmapped() const
  159. {
  160. return _mipmapped;
  161. }
  162. Texture::Sampler::Sampler(Texture* texture)
  163. : _texture(texture), _wrapS(Texture::REPEAT), _wrapT(Texture::REPEAT), _magFilter(Texture::LINEAR)
  164. {
  165. _minFilter = texture->isMipmapped() ? Texture::NEAREST_MIPMAP_LINEAR : Texture::LINEAR;
  166. }
  167. Texture::Sampler::~Sampler()
  168. {
  169. SAFE_RELEASE(_texture);
  170. }
  171. Texture::Sampler* Texture::Sampler::create(Texture* texture)
  172. {
  173. assert(texture != NULL);
  174. texture->addRef();
  175. return new Sampler(texture);
  176. }
  177. Texture::Sampler* Texture::Sampler::create(const char* path, bool generateMipmaps)
  178. {
  179. Texture* texture = Texture::create(path, generateMipmaps);
  180. return texture ? new Sampler(texture) : NULL;
  181. }
  182. void Texture::Sampler::setWrapMode(Wrap wrapS, Wrap wrapT)
  183. {
  184. _wrapS = wrapS;
  185. _wrapT = wrapT;
  186. }
  187. void Texture::Sampler::setFilterMode(Filter minificationFilter, Filter magnificationFilter)
  188. {
  189. _minFilter = minificationFilter;
  190. _magFilter = magnificationFilter;
  191. }
  192. Texture* Texture::Sampler::getTexture() const
  193. {
  194. return _texture;
  195. }
  196. void Texture::Sampler::bind()
  197. {
  198. GL_ASSERT( glBindTexture(GL_TEXTURE_2D, _texture->_handle) );
  199. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLenum)_wrapS) );
  200. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLenum)_wrapT) );
  201. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLenum)_minFilter) );
  202. GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLenum)_magFilter) );
  203. }
  204. }