gfxGLCubemap.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "gfx/gl/gfxGLDevice.h"
  23. #include "gfx/gl/gfxGLTextureObject.h"
  24. #include "gfx/gl/gfxGLEnumTranslate.h"
  25. #include "gfx/gl/gfxGLUtils.h"
  26. #include "gfx/gl/gfxGLCubemap.h"
  27. #include "gfx/gfxTextureManager.h"
  28. #include "gfx/gfxCardProfile.h"
  29. #include "gfx/bitmap/DDSFile.h"
  30. GLenum GFXGLCubemap::faceList[6] =
  31. {
  32. GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
  33. GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
  34. GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
  35. };
  36. GFXGLCubemap::GFXGLCubemap() :
  37. mCubemap(0),
  38. mDynamicTexSize(0),
  39. mFaceFormat( GFXFormatR8G8B8A8 )
  40. {
  41. for(U32 i = 0; i < 6; i++)
  42. mTextures[i] = NULL;
  43. GFXTextureManager::addEventDelegate( this, &GFXGLCubemap::_onTextureEvent );
  44. }
  45. GFXGLCubemap::~GFXGLCubemap()
  46. {
  47. glDeleteTextures(1, &mCubemap);
  48. GFXTextureManager::removeEventDelegate( this, &GFXGLCubemap::_onTextureEvent );
  49. }
  50. void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces)
  51. {
  52. glActiveTexture(GL_TEXTURE0);
  53. glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
  54. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
  55. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  56. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  57. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  58. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  59. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  60. U32 reqWidth = faces[0]->getWidth();
  61. U32 reqHeight = faces[0]->getHeight();
  62. GFXFormat regFaceFormat = faces[0]->getFormat();
  63. mWidth = reqWidth;
  64. mHeight = reqHeight;
  65. mFaceFormat = regFaceFormat;
  66. mMipLevels = 1; // Lie for now
  67. AssertFatal(reqWidth == reqHeight, "GFXGLCubemap::fillCubeTextures - Width and height must be equal!");
  68. for(U32 i = 0; i < 6; i++)
  69. {
  70. AssertFatal(faces[i], avar("GFXGLCubemap::fillCubeFaces - texture %i is NULL!", i));
  71. AssertFatal((faces[i]->getWidth() == reqWidth) && (faces[i]->getHeight() == reqHeight), "GFXGLCubemap::fillCubeFaces - All textures must have identical dimensions!");
  72. AssertFatal(faces[i]->getFormat() == regFaceFormat, "GFXGLCubemap::fillCubeFaces - All textures must have identical formats!");
  73. mTextures[i] = faces[i];
  74. GFXFormat faceFormat = faces[i]->getFormat();
  75. GFXGLTextureObject* glTex = static_cast<GFXGLTextureObject*>(faces[i].getPointer());
  76. U8* buf = glTex->getTextureData();
  77. glTexImage2D(faceList[i], 0, GFXGLTextureInternalFormat[faceFormat], faces[i]->getWidth(), faces[i]->getHeight(),
  78. 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], buf);
  79. delete[] buf;
  80. }
  81. glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  82. glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
  83. }
  84. void GFXGLCubemap::initStatic(GFXTexHandle* faces)
  85. {
  86. if(mCubemap)
  87. return;
  88. if(faces)
  89. {
  90. AssertFatal(faces[0], "GFXGLCubemap::initStatic - empty texture passed");
  91. glGenTextures(1, &mCubemap);
  92. fillCubeTextures(faces);
  93. }
  94. }
  95. void GFXGLCubemap::initStatic( DDSFile *dds )
  96. {
  97. if(mCubemap)
  98. return;
  99. AssertFatal( dds, "GFXGLCubemap::initStatic - Got null DDS file!" );
  100. AssertFatal( dds->isCubemap(), "GFXGLCubemap::initStatic - Got non-cubemap DDS file!" );
  101. AssertFatal( dds->mSurfaces.size() == 6, "GFXGLCubemap::initStatic - DDS has less than 6 surfaces!" );
  102. // HACK: I cannot put the genie back in the bottle and assign a
  103. // DDSFile pointer back to a Resource<>.
  104. //
  105. // So we do a second lookup which works out ok for now, but shows
  106. // the weakness in the ResourceManager not having a common base
  107. // reference type.
  108. //
  109. mDDSFile = ResourceManager::get().load( dds->getSourcePath() );
  110. AssertFatal( mDDSFile == dds, "GFXGLCubemap::initStatic - Couldn't find DDSFile resource!" );
  111. glGenTextures(1, &mCubemap);
  112. glActiveTexture(GL_TEXTURE0);
  113. glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
  114. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
  115. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  116. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  117. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  118. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  119. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  120. mWidth = dds->getWidth();
  121. mHeight = dds->getHeight();
  122. mFaceFormat = dds->getFormat();
  123. mMipLevels = 1;
  124. // TODO: Support mipmaps here as well as decompressing the
  125. // DDS if the format is unsupported.
  126. AssertFatal(mWidth == mHeight, "GFXGLCubemap::initStatic - Width and height must be equal!");
  127. for(U32 i = 0; i < 6; i++)
  128. {
  129. if ( !dds->mSurfaces[i] )
  130. {
  131. // TODO: The DDS can skip surfaces, but i'm unsure what i should
  132. // do here when creating the cubemap. Ignore it for now.
  133. continue;
  134. }
  135. const U8 *buffer = dds->mSurfaces[i]->mMips[0];
  136. U32 surfaceSize = dds->getSurfaceSize( mHeight, mWidth, i );
  137. glCompressedTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[mFaceFormat],
  138. mWidth, mHeight, 0, surfaceSize, buffer );
  139. }
  140. glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  141. glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
  142. }
  143. void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
  144. {
  145. mDynamicTexSize = texSize;
  146. mFaceFormat = faceFormat;
  147. glGenTextures(1, &mCubemap);
  148. glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
  149. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  150. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  151. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  152. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  153. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  154. mWidth = texSize;
  155. mHeight = texSize;
  156. mMipLevels = 1;
  157. for(U32 i = 0; i < 6; i++)
  158. {
  159. glTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[faceFormat], texSize, texSize,
  160. 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], NULL);
  161. }
  162. glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  163. }
  164. void GFXGLCubemap::zombify()
  165. {
  166. glDeleteTextures(1, &mCubemap);
  167. mCubemap = 0;
  168. }
  169. void GFXGLCubemap::resurrect()
  170. {
  171. // Handled in tmResurrect
  172. }
  173. void GFXGLCubemap::tmResurrect()
  174. {
  175. if(mDynamicTexSize)
  176. initDynamic(mDynamicTexSize,mFaceFormat);
  177. else
  178. {
  179. if ( mDDSFile )
  180. initStatic( mDDSFile );
  181. else
  182. initStatic( mTextures );
  183. }
  184. }
  185. void GFXGLCubemap::setToTexUnit(U32 tuNum)
  186. {
  187. static_cast<GFXGLDevice*>(getOwningDevice())->setCubemapInternal(tuNum, this);
  188. }
  189. void GFXGLCubemap::bind(U32 textureUnit) const
  190. {
  191. glActiveTexture(GL_TEXTURE0 + textureUnit);
  192. glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
  193. GFXGLStateBlockRef sb = static_cast<GFXGLDevice*>(GFX)->getCurrentStateBlock();
  194. AssertFatal(sb, "GFXGLCubemap::bind - No active stateblock!");
  195. if (!sb)
  196. return;
  197. const GFXSamplerStateDesc& ssd = sb->getDesc().samplers[textureUnit];
  198. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, 0));
  199. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
  200. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
  201. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
  202. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
  203. glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, ssd.mipLODBias);
  204. }
  205. void GFXGLCubemap::_onTextureEvent( GFXTexCallbackCode code )
  206. {
  207. if ( code == GFXZombify )
  208. zombify();
  209. else
  210. tmResurrect();
  211. }