cubemapData.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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 "platform/platform.h"
  23. #include "gfx/sim/cubemapData.h"
  24. #include "core/stream/bitStream.h"
  25. #include "console/consoleTypes.h"
  26. #include "gfx/gfxCubemap.h"
  27. #include "gfx/gfxDevice.h"
  28. #include "gfx/gfxTransformSaver.h"
  29. #include "gfx/gfxDebugEvent.h"
  30. #include "scene/sceneManager.h"
  31. #include "console/engineAPI.h"
  32. #include "math/mathUtils.h"
  33. IMPLEMENT_CONOBJECT( CubemapData );
  34. CubemapData::CubemapData()
  35. {
  36. mCubemap = NULL;
  37. mDynamic = false;
  38. mDynamicSize = 512;
  39. mDynamicNearDist = 0.1f;
  40. mDynamicFarDist = 100.0f;
  41. mDynamicObjectTypeMask = 0;
  42. #ifdef INIT_HACK
  43. mInit = false;
  44. #endif
  45. }
  46. CubemapData::~CubemapData()
  47. {
  48. mCubemap = NULL;
  49. }
  50. ConsoleDocClass( CubemapData,
  51. "@brief Used to create static or dynamic cubemaps.\n\n"
  52. "This object is used with Material, WaterObject, and other objects for cubemap reflections.\n\n"
  53. "A simple declaration of a static cubemap:\n"
  54. "@tsexample\n"
  55. "singleton CubemapData( SkyboxCubemap )\n"
  56. "{\n"
  57. " cubeFace[0] = \"./skybox_1\";\n"
  58. " cubeFace[1] = \"./skybox_2\";\n"
  59. " cubeFace[2] = \"./skybox_3\";\n"
  60. " cubeFace[3] = \"./skybox_4\";\n"
  61. " cubeFace[4] = \"./skybox_5\";\n"
  62. " cubeFace[5] = \"./skybox_6\";\n"
  63. "};\n"
  64. "@endtsexample\n"
  65. "@note The dynamic cubemap functionality in CubemapData has been depreciated in favor of ReflectorDesc.\n"
  66. "@see ReflectorDesc\n"
  67. "@ingroup GFX\n" );
  68. void CubemapData::initPersistFields()
  69. {
  70. addField( "cubeFace", TypeStringFilename, Offset(mCubeFaceFile, CubemapData), 6,
  71. "@brief The 6 cubemap face textures for a static cubemap.\n\n"
  72. "They are in the following order:\n"
  73. " - cubeFace[0] is -X\n"
  74. " - cubeFace[1] is +X\n"
  75. " - cubeFace[2] is -Z\n"
  76. " - cubeFace[3] is +Z\n"
  77. " - cubeFace[4] is -Y\n"
  78. " - cubeFace[5] is +Y\n" );
  79. addField("dynamic", TypeBool, Offset(mDynamic, CubemapData),
  80. "Set to true if this is a dynamic cubemap. The default is false." );
  81. addField("dynamicSize", TypeS32, Offset(mDynamicSize, CubemapData),
  82. "The size of each dynamic cubemap face in pixels." );
  83. addField("dynamicNearDist", TypeF32, Offset(mDynamicNearDist, CubemapData),
  84. "The near clip distance used when rendering to the dynamic cubemap." );
  85. addField("dynamicFarDist", TypeF32, Offset(mDynamicFarDist, CubemapData),
  86. "The far clip distance used when rendering to the dynamic cubemap." );
  87. addField("dynamicObjectTypeMask", TypeS32, Offset(mDynamicObjectTypeMask, CubemapData),
  88. "The typemask used to filter the objects rendered to the dynamic cubemap." );
  89. Parent::initPersistFields();
  90. }
  91. bool CubemapData::onAdd()
  92. {
  93. if( !Parent::onAdd() )
  94. return false;
  95. // Do NOT call this here as it forces every single cubemap defined to load its images, immediately, without mercy
  96. // createMap();
  97. return true;
  98. }
  99. void CubemapData::createMap()
  100. {
  101. if( !mCubemap )
  102. {
  103. if( mDynamic )
  104. {
  105. mCubemap = GFX->createCubemap();
  106. mCubemap->initDynamic( mDynamicSize );
  107. mDepthBuff = GFXTexHandle( mDynamicSize, mDynamicSize, GFXFormatD24S8,
  108. &GFXDefaultZTargetProfile, avar("%s() - mDepthBuff (line %d)", __FUNCTION__, __LINE__));
  109. mRenderTarget = GFX->allocRenderToTextureTarget();
  110. }
  111. else
  112. {
  113. bool initSuccess = true;
  114. for( U32 i=0; i<6; i++ )
  115. {
  116. if( !mCubeFaceFile[i].isEmpty() )
  117. {
  118. if(!mCubeFace[i].set(mCubeFaceFile[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - mCubeFace[%d] (line %d)", __FUNCTION__, i, __LINE__) ))
  119. {
  120. Con::errorf("CubemapData::createMap - Failed to load texture '%s'", mCubeFaceFile[i].c_str());
  121. initSuccess = false;
  122. }
  123. }
  124. }
  125. if( initSuccess )
  126. {
  127. mCubemap = GFX->createCubemap();
  128. mCubemap->initStatic( mCubeFace );
  129. }
  130. }
  131. }
  132. }
  133. void CubemapData::updateDynamic(SceneManager* sm, const Point3F& pos)
  134. {
  135. AssertFatal(mDynamic, "This is not a dynamic cubemap!");
  136. GFXDEBUGEVENT_SCOPE( CubemapData_updateDynamic, ColorI::WHITE );
  137. #ifdef INIT_HACK
  138. if( mInit ) return;
  139. mInit = true;
  140. #endif
  141. GFX->pushActiveRenderTarget();
  142. mRenderTarget->attachTexture(GFXTextureTarget::DepthStencil, mDepthBuff );
  143. // store current matrices
  144. GFXTransformSaver saver;
  145. F32 oldVisibleDist = sm->getVisibleDistance();
  146. // set projection to 90 degrees vertical and horizontal
  147. {
  148. F32 left, right, top, bottom;
  149. MathUtils::makeFrustum( &left, &right, &top, &bottom, M_HALFPI_F, 1.0f, mDynamicNearDist );
  150. GFX->setFrustum( left, right, bottom, top, mDynamicNearDist, mDynamicFarDist );
  151. }
  152. sm->setVisibleDistance(mDynamicFarDist);
  153. // We don't use a special clipping projection, but still need to initialize
  154. // this for objects like SkyBox which will use it during a reflect pass.
  155. gClientSceneGraph->setNonClipProjection( (MatrixF&) GFX->getProjectionMatrix() );
  156. // Loop through the six faces of the cube map.
  157. for(U32 i=0; i<6; i++)
  158. {
  159. // Standard view that will be overridden below.
  160. VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f);
  161. switch( i )
  162. {
  163. case 0 : // D3DCUBEMAP_FACE_POSITIVE_X:
  164. vLookatPt = VectorF( 1.0f, 0.0f, 0.0f );
  165. vUpVec = VectorF( 0.0f, 1.0f, 0.0f );
  166. break;
  167. case 1 : // D3DCUBEMAP_FACE_NEGATIVE_X:
  168. vLookatPt = VectorF( -1.0f, 0.0f, 0.0f );
  169. vUpVec = VectorF( 0.0f, 1.0f, 0.0f );
  170. break;
  171. case 2 : // D3DCUBEMAP_FACE_POSITIVE_Y:
  172. vLookatPt = VectorF( 0.0f, 1.0f, 0.0f );
  173. vUpVec = VectorF( 0.0f, 0.0f,-1.0f );
  174. break;
  175. case 3 : // D3DCUBEMAP_FACE_NEGATIVE_Y:
  176. vLookatPt = VectorF( 0.0f, -1.0f, 0.0f );
  177. vUpVec = VectorF( 0.0f, 0.0f, 1.0f );
  178. break;
  179. case 4 : // D3DCUBEMAP_FACE_POSITIVE_Z:
  180. vLookatPt = VectorF( 0.0f, 0.0f, 1.0f );
  181. vUpVec = VectorF( 0.0f, 1.0f, 0.0f );
  182. break;
  183. case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z:
  184. vLookatPt = VectorF( 0.0f, 0.0f, -1.0f );
  185. vUpVec = VectorF( 0.0f, 1.0f, 0.0f );
  186. break;
  187. }
  188. // create camera matrix
  189. VectorF cross = mCross( vUpVec, vLookatPt );
  190. cross.normalizeSafe();
  191. MatrixF matView(true);
  192. matView.setColumn( 0, cross );
  193. matView.setColumn( 1, vLookatPt );
  194. matView.setColumn( 2, vUpVec );
  195. matView.setPosition( pos );
  196. matView.inverse();
  197. GFX->pushWorldMatrix();
  198. GFX->setWorldMatrix(matView);
  199. mRenderTarget->attachTexture( GFXTextureTarget::Color0, mCubemap, i );
  200. GFX->setActiveRenderTarget( mRenderTarget );
  201. GFX->clear( GFXClearStencil | GFXClearTarget | GFXClearZBuffer, ColorI( 64, 64, 64 ), 1.f, 0 );
  202. // render scene
  203. sm->renderScene( SPT_Reflect, mDynamicObjectTypeMask );
  204. // Resolve render target for each face
  205. mRenderTarget->resolve();
  206. GFX->popWorldMatrix();
  207. }
  208. // restore render surface and depth buffer
  209. GFX->popActiveRenderTarget();
  210. mRenderTarget->attachTexture(GFXTextureTarget::Color0, NULL);
  211. sm->setVisibleDistance(oldVisibleDist);
  212. }
  213. void CubemapData::updateFaces()
  214. {
  215. bool initSuccess = true;
  216. for( U32 i=0; i<6; i++ )
  217. {
  218. if( !mCubeFaceFile[i].isEmpty() )
  219. {
  220. if(!mCubeFace[i].set(mCubeFaceFile[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - mCubeFace[%d] (line %d)", __FUNCTION__, i, __LINE__) ))
  221. {
  222. initSuccess = false;
  223. Con::errorf("CubemapData::createMap - Failed to load texture '%s'", mCubeFaceFile[i].c_str());
  224. }
  225. }
  226. }
  227. if( initSuccess )
  228. {
  229. mCubemap = NULL;
  230. mCubemap = GFX->createCubemap();
  231. mCubemap->initStatic( mCubeFace );
  232. }
  233. }
  234. DefineEngineMethod( CubemapData, updateFaces, void, (),,
  235. "Update the assigned cubemaps faces." )
  236. {
  237. object->updateFaces();
  238. }
  239. DefineEngineMethod( CubemapData, getFilename, const char*, (),,
  240. "Returns the script filename of where the CubemapData object was "
  241. "defined. This is used by the material editor." )
  242. {
  243. return object->getFilename();
  244. }