BsSkybox.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Renderer/BsSkybox.h"
  4. #include "RTTI/BsSkyboxRTTI.h"
  5. #include "Scene/BsSceneObject.h"
  6. #include "Allocators/BsFrameAlloc.h"
  7. #include "Image/BsTexture.h"
  8. #include "Renderer/BsRenderer.h"
  9. #include "Utility/BsUUID.h"
  10. #include "Renderer/BsIBLUtility.h"
  11. namespace bs
  12. {
  13. SkyboxBase::SkyboxBase()
  14. : mIsActive(true), mBrightness(1.0f)
  15. { }
  16. template <bool Core>
  17. TSkybox<Core>::TSkybox()
  18. : SkyboxBase()
  19. { }
  20. template class TSkybox<true>;
  21. template class TSkybox<false>;
  22. Skybox::Skybox()
  23. {
  24. // This shouldn't normally happen, as filtered textures are generated when a radiance texture is assigned, but
  25. // we check for it anyway (something could have gone wrong).
  26. if(mTexture.isLoaded())
  27. {
  28. if (mFilteredRadiance == nullptr || mIrradiance == nullptr)
  29. filterTexture();
  30. }
  31. }
  32. Skybox::~Skybox()
  33. {
  34. if (mRendererTask != nullptr)
  35. mRendererTask->cancel();
  36. }
  37. void Skybox::filterTexture()
  38. {
  39. // If previous rendering task exists, cancel it
  40. if (mRendererTask != nullptr)
  41. mRendererTask->cancel();
  42. {
  43. TEXTURE_DESC cubemapDesc;
  44. cubemapDesc.type = TEX_TYPE_CUBE_MAP;
  45. cubemapDesc.format = PF_RG11B10F;
  46. cubemapDesc.width = ct::IBLUtility::REFLECTION_CUBEMAP_SIZE;
  47. cubemapDesc.height = ct::IBLUtility::REFLECTION_CUBEMAP_SIZE;
  48. cubemapDesc.numMips = PixelUtil::getMaxMipmaps(cubemapDesc.width, cubemapDesc.height, 1, cubemapDesc.format);
  49. cubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
  50. mFilteredRadiance = Texture::_createPtr(cubemapDesc);
  51. }
  52. {
  53. TEXTURE_DESC irradianceCubemapDesc;
  54. irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
  55. irradianceCubemapDesc.format = PF_RG11B10F;
  56. irradianceCubemapDesc.width = ct::IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
  57. irradianceCubemapDesc.height = ct::IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
  58. irradianceCubemapDesc.numMips = 0;
  59. irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
  60. mIrradiance = Texture::_createPtr(irradianceCubemapDesc);
  61. }
  62. auto renderComplete = [this]()
  63. {
  64. mRendererTask = nullptr;
  65. };
  66. SPtr<ct::Skybox> coreSkybox = getCore();
  67. SPtr<ct::Texture> coreFilteredRadiance = mFilteredRadiance->getCore();
  68. SPtr<ct::Texture> coreIrradiance = mIrradiance->getCore();
  69. auto filterSkybox = [coreFilteredRadiance, coreIrradiance, coreSkybox]()
  70. {
  71. // Filter radiance
  72. ct::gIBLUtility().scaleCubemap(coreSkybox->getTexture(), 0, coreFilteredRadiance, 0);
  73. ct::gIBLUtility().filterCubemapForSpecular(coreFilteredRadiance, nullptr);
  74. coreSkybox->mFilteredRadiance = coreFilteredRadiance;
  75. // Generate irradiance
  76. ct::gIBLUtility().filterCubemapForIrradiance(coreFilteredRadiance, coreIrradiance);
  77. coreSkybox->mIrradiance = coreIrradiance;
  78. return true;
  79. };
  80. mRendererTask = ct::RendererTask::create("SkyboxFilter", filterSkybox);
  81. mRendererTask->onComplete.connect(renderComplete);
  82. ct::gRenderer()->addTask(mRendererTask);
  83. }
  84. SPtr<ct::Skybox> Skybox::getCore() const
  85. {
  86. return std::static_pointer_cast<ct::Skybox>(mCoreSpecific);
  87. }
  88. SPtr<Skybox> Skybox::create()
  89. {
  90. Skybox* skybox = new (bs_alloc<Skybox>()) Skybox();
  91. SPtr<Skybox> skyboxPtr = bs_core_ptr<Skybox>(skybox);
  92. skyboxPtr->_setThisPtr(skyboxPtr);
  93. skyboxPtr->mUUID = UUIDGenerator::generateRandom();
  94. skyboxPtr->initialize();
  95. return skyboxPtr;
  96. }
  97. SPtr<ct::CoreObject> Skybox::createCore() const
  98. {
  99. SPtr<ct::Texture> filteredRadiance;
  100. if (mFilteredRadiance)
  101. filteredRadiance = mFilteredRadiance->getCore();
  102. SPtr<ct::Texture> irradiance;
  103. if (mIrradiance)
  104. irradiance = mIrradiance->getCore();
  105. ct::Skybox* skybox = new (bs_alloc<ct::Skybox>()) ct::Skybox(filteredRadiance, irradiance);
  106. SPtr<ct::Skybox> skyboxPtr = bs_shared_ptr<ct::Skybox>(skybox);
  107. skyboxPtr->mUUID = mUUID;
  108. skyboxPtr->_setThisPtr(skyboxPtr);
  109. return skyboxPtr;
  110. }
  111. CoreSyncData Skybox::syncToCore(FrameAlloc* allocator)
  112. {
  113. UINT32 size = 0;
  114. size += rttiGetElemSize(mIsActive);
  115. size += rttiGetElemSize(mBrightness);
  116. size += sizeof(SPtr<ct::Texture>);
  117. size += rttiGetElemSize(mUUID);
  118. size += rttiGetElemSize(getCoreDirtyFlags());
  119. UINT8* buffer = allocator->alloc(size);
  120. char* dataPtr = (char*)buffer;
  121. dataPtr = rttiWriteElem(mIsActive, dataPtr);
  122. dataPtr = rttiWriteElem(mBrightness, dataPtr);
  123. dataPtr = rttiWriteElem(mUUID, dataPtr);
  124. dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
  125. SPtr<ct::Texture>* texture = new (dataPtr) SPtr<ct::Texture>();
  126. if (mTexture.isLoaded(false))
  127. *texture = mTexture->getCore();
  128. else
  129. *texture = nullptr;
  130. dataPtr += sizeof(SPtr<ct::Texture>);
  131. return CoreSyncData(buffer, size);
  132. }
  133. void Skybox::_markCoreDirty(SkyboxDirtyFlag flags)
  134. {
  135. if(flags == SkyboxDirtyFlag::Texture)
  136. filterTexture();
  137. markCoreDirty((UINT32)flags);
  138. }
  139. RTTITypeBase* Skybox::getRTTIStatic()
  140. {
  141. return SkyboxRTTI::instance();
  142. }
  143. RTTITypeBase* Skybox::getRTTI() const
  144. {
  145. return Skybox::getRTTIStatic();
  146. }
  147. namespace ct
  148. {
  149. Skybox::Skybox(const SPtr<Texture>& filteredRadiance, const SPtr<Texture>& irradiance)
  150. :mFilteredRadiance(filteredRadiance), mIrradiance(irradiance)
  151. { }
  152. Skybox::~Skybox()
  153. {
  154. gRenderer()->notifySkyboxRemoved(this);
  155. }
  156. void Skybox::initialize()
  157. {
  158. gRenderer()->notifySkyboxAdded(this);
  159. CoreObject::initialize();
  160. }
  161. void Skybox::syncToCore(const CoreSyncData& data)
  162. {
  163. char* dataPtr = (char*)data.getBuffer();
  164. SkyboxDirtyFlag dirtyFlags;
  165. bool oldIsActive = mIsActive;
  166. dataPtr = rttiReadElem(mIsActive, dataPtr);
  167. dataPtr = rttiReadElem(mBrightness, dataPtr);
  168. dataPtr = rttiReadElem(mUUID, dataPtr);
  169. dataPtr = rttiReadElem(dirtyFlags, dataPtr);
  170. SPtr<Texture>* texture = (SPtr<Texture>*)dataPtr;
  171. mTexture = *texture;
  172. texture->~SPtr<Texture>();
  173. dataPtr += sizeof(SPtr<Texture>);
  174. if (oldIsActive != mIsActive)
  175. {
  176. if (mIsActive)
  177. gRenderer()->notifySkyboxAdded(this);
  178. else
  179. gRenderer()->notifySkyboxRemoved(this);
  180. }
  181. else
  182. {
  183. if (dirtyFlags != SkyboxDirtyFlag::Texture)
  184. {
  185. gRenderer()->notifySkyboxRemoved(this);
  186. gRenderer()->notifySkyboxAdded(this);
  187. }
  188. }
  189. }
  190. }
  191. }