2
0

BsSkybox.cpp 6.2 KB

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