BsSkybox.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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->initialize();
  94. return skyboxPtr;
  95. }
  96. SPtr<ct::CoreObject> Skybox::createCore() const
  97. {
  98. SPtr<ct::Texture> filteredRadiance;
  99. if (mFilteredRadiance)
  100. filteredRadiance = mFilteredRadiance->getCore();
  101. SPtr<ct::Texture> irradiance;
  102. if (mIrradiance)
  103. irradiance = mIrradiance->getCore();
  104. ct::Skybox* skybox = new (bs_alloc<ct::Skybox>()) ct::Skybox(filteredRadiance, irradiance);
  105. SPtr<ct::Skybox> skyboxPtr = bs_shared_ptr<ct::Skybox>(skybox);
  106. skyboxPtr->_setThisPtr(skyboxPtr);
  107. return skyboxPtr;
  108. }
  109. CoreSyncData Skybox::syncToCore(FrameAlloc* allocator)
  110. {
  111. UINT32 size = 0;
  112. size += rttiGetElemSize(mIsActive);
  113. size += rttiGetElemSize(mBrightness);
  114. size += sizeof(SPtr<ct::Texture>);
  115. size += rttiGetElemSize(getCoreDirtyFlags());
  116. UINT8* buffer = allocator->alloc(size);
  117. char* dataPtr = (char*)buffer;
  118. dataPtr = rttiWriteElem(mIsActive, dataPtr);
  119. dataPtr = rttiWriteElem(mBrightness, dataPtr);
  120. dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
  121. SPtr<ct::Texture>* texture = new (dataPtr) SPtr<ct::Texture>();
  122. if (mTexture.isLoaded(false))
  123. *texture = mTexture->getCore();
  124. else
  125. *texture = nullptr;
  126. dataPtr += sizeof(SPtr<ct::Texture>);
  127. return CoreSyncData(buffer, size);
  128. }
  129. void Skybox::_markCoreDirty(SkyboxDirtyFlag flags)
  130. {
  131. if(flags == SkyboxDirtyFlag::Texture)
  132. filterTexture();
  133. markCoreDirty((UINT32)flags);
  134. }
  135. RTTITypeBase* Skybox::getRTTIStatic()
  136. {
  137. return SkyboxRTTI::instance();
  138. }
  139. RTTITypeBase* Skybox::getRTTI() const
  140. {
  141. return Skybox::getRTTIStatic();
  142. }
  143. namespace ct
  144. {
  145. Skybox::Skybox(const SPtr<Texture>& filteredRadiance, const SPtr<Texture>& irradiance)
  146. :mFilteredRadiance(filteredRadiance), mIrradiance(irradiance)
  147. { }
  148. Skybox::~Skybox()
  149. {
  150. gRenderer()->notifySkyboxRemoved(this);
  151. }
  152. void Skybox::initialize()
  153. {
  154. gRenderer()->notifySkyboxAdded(this);
  155. CoreObject::initialize();
  156. }
  157. void Skybox::syncToCore(const CoreSyncData& data)
  158. {
  159. char* dataPtr = (char*)data.getBuffer();
  160. SkyboxDirtyFlag dirtyFlags;
  161. bool oldIsActive = mIsActive;
  162. dataPtr = rttiReadElem(mIsActive, dataPtr);
  163. dataPtr = rttiReadElem(mBrightness, dataPtr);
  164. dataPtr = rttiReadElem(dirtyFlags, dataPtr);
  165. SPtr<Texture>* texture = (SPtr<Texture>*)dataPtr;
  166. mTexture = *texture;
  167. texture->~SPtr<Texture>();
  168. dataPtr += sizeof(SPtr<Texture>);
  169. if (oldIsActive != mIsActive)
  170. {
  171. if (mIsActive)
  172. gRenderer()->notifySkyboxAdded(this);
  173. else
  174. gRenderer()->notifySkyboxRemoved(this);
  175. }
  176. else
  177. {
  178. if (dirtyFlags != SkyboxDirtyFlag::Texture)
  179. {
  180. gRenderer()->notifySkyboxRemoved(this);
  181. gRenderer()->notifySkyboxAdded(this);
  182. }
  183. }
  184. }
  185. }
  186. }