BsSkybox.cpp 6.2 KB

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