cubemapSaver.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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/bitmap/cubemapSaver.h"
  23. #include "platform/platform.h"
  24. #include "gfx/bitmap/ddsFile.h"
  25. #include "gfx/bitmap/imageUtils.h"
  26. #include "gfx/gfxDevice.h"
  27. #include "gfx/gfxTransformSaver.h"
  28. #include "gfx/gfxTextureManager.h"
  29. #include "materials/shaderData.h"
  30. #include "core/stream/fileStream.h"
  31. #include "math/mathUtils.h"
  32. #include "math/mTransform.h"
  33. namespace CubemapSaver
  34. {
  35. const U32 CubeFaces = 6;
  36. void _setConstBuffer(GFXShaderConstHandle* handle, GFXShaderConstBuffer *cbuf, const VectorF &vLookatPt, const VectorF &vUpVec)
  37. {
  38. VectorF cross = mCross(vUpVec, vLookatPt);
  39. cross.normalizeSafe();
  40. MatrixF matView(true);
  41. matView.setColumn(0, cross);
  42. matView.setColumn(1, vLookatPt);
  43. matView.setColumn(2, vUpVec);
  44. matView.setPosition(VectorF(0.0f, 0.0f, 1.0f));
  45. matView.inverse();
  46. if (handle->isValid())
  47. cbuf->set(handle, matView);
  48. else
  49. Con::errorf("CubemapSaver: Failed to set a shader constant handle.");
  50. }
  51. bool save(GFXCubemapHandle cubemap, const Torque::Path &path, GFXFormat compressionFormat)
  52. {
  53. if (!cubemap.isValid())
  54. {
  55. Con::errorf("CubemapSaver: cubemap handle is not valid");
  56. return false;
  57. }
  58. // This can sometimes occur outside a begin/end scene.
  59. const bool sceneBegun = GFX->canCurrentlyRender();
  60. if (!sceneBegun)
  61. GFX->beginScene();
  62. GFXCubemap *pCubemap = cubemap.getPointer();
  63. U32 faceSize = pCubemap->getSize();
  64. ShaderData *shaderData = nullptr;
  65. GFXShaderRef shader = Sim::findObject("CubemapSaveShader", shaderData) ? shaderData->getShader() : nullptr;
  66. if (!shader)
  67. {
  68. Con::errorf("CubemapSaver::save - could not find CubemapSaveShader");
  69. return false;
  70. }
  71. GFXShaderConstHandle *matHandles[CubeFaces];
  72. matHandles[0] = shader->getShaderConstHandle("$matrix0");
  73. matHandles[1] = shader->getShaderConstHandle("$matrix1");
  74. matHandles[2] = shader->getShaderConstHandle("$matrix2");
  75. matHandles[3] = shader->getShaderConstHandle("$matrix3");
  76. matHandles[4] = shader->getShaderConstHandle("$matrix4");
  77. matHandles[5] = shader->getShaderConstHandle("$matrix5");
  78. GFXShaderConstBufferRef cbuffer = shader->allocConstBuffer();
  79. GFXTextureTarget *pTarget = GFX->allocRenderToTextureTarget();
  80. GFX->pushActiveRenderTarget();
  81. GFXFormat renderTargetFmt = GFXFormatR8G8B8A8;
  82. //setup render targets
  83. GFXTexHandle pTextures[CubeFaces];
  84. for (U32 i = 0; i < CubeFaces; i++)
  85. {
  86. pTextures[i].set(faceSize, faceSize, renderTargetFmt,
  87. &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
  88. 1, GFXTextureManager::AA_MATCH_BACKBUFFER);
  89. pTarget->attachTexture(GFXTextureTarget::RenderSlot(GFXTextureTarget::Color0 + i), pTextures[i]);
  90. }
  91. //create stateblock
  92. GFXStateBlockDesc desc;
  93. desc.setZReadWrite(false, false);
  94. desc.samplersDefined = true;
  95. desc.samplers[0].addressModeU = GFXAddressClamp;
  96. desc.samplers[0].addressModeV = GFXAddressClamp;
  97. desc.samplers[0].addressModeW = GFXAddressClamp;
  98. desc.samplers[0].magFilter = GFXTextureFilterLinear;
  99. desc.samplers[0].minFilter = GFXTextureFilterLinear;
  100. desc.samplers[0].mipFilter = GFXTextureFilterLinear;
  101. //yep funky order and rotations with t3d z up
  102. _setConstBuffer(matHandles[0], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(-1.0f, 0.0f, 0.0f));
  103. _setConstBuffer(matHandles[1], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(1.0f, 0.0f, 0.0f));
  104. _setConstBuffer(matHandles[2], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, -1.0f));
  105. _setConstBuffer(matHandles[3], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, 1.0f));
  106. _setConstBuffer(matHandles[4], cbuffer, VectorF(0.0f, 0.0f, -1.0f), VectorF(0.0f, -1.0f, 0.0f));
  107. _setConstBuffer(matHandles[5], cbuffer, VectorF(0.0f, 0.0f, 1.0f), VectorF(0.0f, 1.0f, 0.0f));
  108. GFXTransformSaver saver;
  109. GFX->setActiveRenderTarget(pTarget);
  110. GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
  111. GFX->setStateBlockByDesc(desc);
  112. GFX->setWorldMatrix(MatrixF::Identity);
  113. GFX->setProjectionMatrix(MatrixF::Identity);
  114. GFX->setCubeTexture(0, pCubemap);
  115. GFX->setShaderConstBuffer(cbuffer);
  116. GFX->setShader(shader);
  117. GFX->drawPrimitive(GFXTriangleList, 0, 3);
  118. pTarget->resolve();
  119. GBitmap *pBitmaps[CubeFaces];
  120. bool error = false;
  121. const bool compressedFormat = ImageUtil::isCompressedFormat(compressionFormat);
  122. for (U32 i = 0; i < CubeFaces; i++)
  123. {
  124. pBitmaps[i] = new GBitmap(faceSize, faceSize, false, renderTargetFmt);
  125. bool result = pTextures[i].copyToBmp(pBitmaps[i]);
  126. if (!result)
  127. {
  128. Con::errorf("CubemapSaver: cubemap number %u failed to copy", i);
  129. error = true;
  130. }
  131. //gen mip maps
  132. pBitmaps[i]->extrudeMipLevels();
  133. }
  134. if (!error)
  135. {
  136. DDSFile *pDds = DDSFile::createDDSCubemapFileFromGBitmaps(pBitmaps);
  137. if (pDds)
  138. {
  139. // non compressed format needs swizzling
  140. if (!compressedFormat)
  141. ImageUtil::swizzleDDS(pDds, Swizzles::bgra);
  142. if(compressedFormat)
  143. ImageUtil::ddsCompress(pDds, compressionFormat);
  144. FileStream stream;
  145. stream.open(path, Torque::FS::File::Write);
  146. if (stream.getStatus() == Stream::Ok)
  147. pDds->write(stream);
  148. else
  149. Con::errorf("CubemapSaver: failed to open file stream for file %s", path.getFullPath().c_str());
  150. SAFE_DELETE(pDds);
  151. }
  152. }
  153. for (U32 i = 0; i < CubeFaces; i++)
  154. SAFE_DELETE(pBitmaps[i]);
  155. //cleaup
  156. GFX->popActiveRenderTarget();
  157. GFX->setTexture(0, NULL);
  158. GFX->setShader(NULL);
  159. GFX->setShaderConstBuffer(NULL);
  160. GFX->setVertexBuffer(NULL);
  161. // End it if we begun it.
  162. if (!sceneBegun)
  163. GFX->endScene();
  164. return true;
  165. }
  166. bool getBitmaps(GFXCubemapHandle cubemap, GFXFormat compressionFormat, GBitmap* faceBitmaps[6])
  167. {
  168. if (!cubemap.isValid())
  169. {
  170. Con::errorf("CubemapSaver: cubemap handle is not valid");
  171. return false;
  172. }
  173. // This can sometimes occur outside a begin/end scene.
  174. const bool sceneBegun = GFX->canCurrentlyRender();
  175. if (!sceneBegun)
  176. GFX->beginScene();
  177. GFXCubemap *pCubemap = cubemap.getPointer();
  178. U32 faceSize = pCubemap->getSize();
  179. ShaderData *shaderData = nullptr;
  180. GFXShaderRef shader = Sim::findObject("CubemapSaveShader", shaderData) ? shaderData->getShader() : nullptr;
  181. if (!shader)
  182. {
  183. Con::errorf("CubemapSaver::save - could not find CubemapSaveShader");
  184. return false;
  185. }
  186. GFXShaderConstHandle *matHandles[CubeFaces];
  187. matHandles[0] = shader->getShaderConstHandle("$matrix0");
  188. matHandles[1] = shader->getShaderConstHandle("$matrix1");
  189. matHandles[2] = shader->getShaderConstHandle("$matrix2");
  190. matHandles[3] = shader->getShaderConstHandle("$matrix3");
  191. matHandles[4] = shader->getShaderConstHandle("$matrix4");
  192. matHandles[5] = shader->getShaderConstHandle("$matrix5");
  193. GFXShaderConstBufferRef cbuffer = shader->allocConstBuffer();
  194. GFXTextureTarget *pTarget = GFX->allocRenderToTextureTarget();
  195. GFX->pushActiveRenderTarget();
  196. GFXFormat renderTargetFmt = GFXFormatR8G8B8A8;
  197. //setup render targets
  198. GFXTexHandle pTextures[CubeFaces];
  199. for (U32 i = 0; i < CubeFaces; i++)
  200. {
  201. pTextures[i].set(faceSize, faceSize, renderTargetFmt,
  202. &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
  203. 1, GFXTextureManager::AA_MATCH_BACKBUFFER);
  204. pTarget->attachTexture(GFXTextureTarget::RenderSlot(GFXTextureTarget::Color0 + i), pTextures[i]);
  205. }
  206. //create stateblock
  207. GFXStateBlockDesc desc;
  208. desc.setZReadWrite(false, false);
  209. desc.samplersDefined = true;
  210. desc.samplers[0].addressModeU = GFXAddressClamp;
  211. desc.samplers[0].addressModeV = GFXAddressClamp;
  212. desc.samplers[0].addressModeW = GFXAddressClamp;
  213. desc.samplers[0].magFilter = GFXTextureFilterLinear;
  214. desc.samplers[0].minFilter = GFXTextureFilterLinear;
  215. desc.samplers[0].mipFilter = GFXTextureFilterLinear;
  216. //yep funky order and rotations with t3d z up
  217. _setConstBuffer(matHandles[0], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(-1.0f, 0.0f, 0.0f));
  218. _setConstBuffer(matHandles[1], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(1.0f, 0.0f, 0.0f));
  219. _setConstBuffer(matHandles[2], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, -1.0f));
  220. _setConstBuffer(matHandles[3], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, 1.0f));
  221. _setConstBuffer(matHandles[4], cbuffer, VectorF(0.0f, 0.0f, -1.0f), VectorF(0.0f, -1.0f, 0.0f));
  222. _setConstBuffer(matHandles[5], cbuffer, VectorF(0.0f, 0.0f, 1.0f), VectorF(0.0f, 1.0f, 0.0f));
  223. GFXTransformSaver saver;
  224. GFX->setActiveRenderTarget(pTarget);
  225. GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
  226. GFX->setStateBlockByDesc(desc);
  227. GFX->setWorldMatrix(MatrixF::Identity);
  228. GFX->setProjectionMatrix(MatrixF::Identity);
  229. GFX->setCubeTexture(0, pCubemap);
  230. GFX->setShaderConstBuffer(cbuffer);
  231. GFX->setShader(shader);
  232. GFX->drawPrimitive(GFXTriangleList, 0, 3);
  233. pTarget->resolve();
  234. bool error = false;
  235. const bool compressedFormat = ImageUtil::isCompressedFormat(compressionFormat);
  236. for (U32 i = 0; i < CubeFaces; i++)
  237. {
  238. //faceBitmaps[i] = new GBitmap(faceSize, faceSize, false, renderTargetFmt);
  239. bool result = pTextures[i].copyToBmp(faceBitmaps[i]);
  240. if (!result)
  241. {
  242. Con::errorf("CubemapSaver: cubemap number %u failed to copy", i);
  243. error = true;
  244. }
  245. //gen mip maps
  246. faceBitmaps[i]->extrudeMipLevels();
  247. }
  248. /*if (!error)
  249. {
  250. DDSFile *pDds = DDSFile::createDDSCubemapFileFromGBitmaps(pBitmaps);
  251. if (pDds)
  252. {
  253. // non compressed format needs swizzling
  254. if (!compressedFormat)
  255. ImageUtil::swizzleDDS(pDds, Swizzles::bgra);
  256. if (compressedFormat)
  257. ImageUtil::ddsCompress(pDds, compressionFormat);
  258. FileStream stream;
  259. stream.open(path, Torque::FS::File::Write);
  260. if (stream.getStatus() == Stream::Ok)
  261. pDds->write(stream);
  262. else
  263. Con::errorf("CubemapSaver: failed to open file stream for file %s", path.getFullPath().c_str());
  264. SAFE_DELETE(pDds);
  265. }
  266. }
  267. for (U32 i = 0; i < CubeFaces; i++)
  268. SAFE_DELETE(pBitmaps[i]);*/
  269. //cleaup
  270. GFX->popActiveRenderTarget();
  271. GFX->setTexture(0, NULL);
  272. GFX->setShader(NULL);
  273. GFX->setShaderConstBuffer(NULL);
  274. GFX->setVertexBuffer(NULL);
  275. // End it if we begun it.
  276. if (!sceneBegun)
  277. GFX->endScene();
  278. if (error)
  279. return false;
  280. return true;
  281. }
  282. }