BsReflectionProbe.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Renderer/BsReflectionProbe.h"
  4. #include "RTTI/BsReflectionProbeRTTI.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. ReflectionProbeBase::ReflectionProbeBase()
  13. : mType(ReflectionProbeType::Box), mRadius(1.0f), mExtents(1.0f, 1.0f, 1.0f), mTransitionDistance(0.1f)
  14. , mBounds(Vector3::ZERO, 1.0f)
  15. { }
  16. ReflectionProbeBase::ReflectionProbeBase(ReflectionProbeType type, float radius, const Vector3& extents)
  17. : mType(type), mRadius(radius), mExtents(extents), mTransitionDistance(0.1f), mBounds(Vector3::ZERO, 1.0f)
  18. { }
  19. float ReflectionProbeBase::getRadius() const
  20. {
  21. Vector3 scale = mTransform.getScale();
  22. return mRadius * std::max(std::max(scale.x, scale.y), scale.z);
  23. }
  24. void ReflectionProbeBase::updateBounds()
  25. {
  26. Vector3 position = mTransform.getPosition();
  27. Vector3 scale = mTransform.getScale();
  28. switch (mType)
  29. {
  30. case ReflectionProbeType::Sphere:
  31. mBounds = Sphere(position, mRadius * std::max(std::max(scale.x, scale.y), scale.z));
  32. break;
  33. case ReflectionProbeType::Box:
  34. mBounds = Sphere(position, (mExtents * scale).length());
  35. break;
  36. }
  37. }
  38. ReflectionProbe::ReflectionProbe()
  39. {
  40. }
  41. ReflectionProbe::ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents)
  42. : ReflectionProbeBase(type, radius, extents)
  43. {
  44. // Calling virtual method is okay here because this is the most derived type
  45. updateBounds();
  46. }
  47. ReflectionProbe::~ReflectionProbe()
  48. {
  49. if (mRendererTask)
  50. mRendererTask->cancel();
  51. }
  52. void ReflectionProbe::capture()
  53. {
  54. if (mCustomTexture != nullptr)
  55. return;
  56. captureAndFilter();
  57. }
  58. void ReflectionProbe::filter()
  59. {
  60. if (mCustomTexture == nullptr)
  61. return;
  62. captureAndFilter();
  63. }
  64. void ReflectionProbe::captureAndFilter()
  65. {
  66. // If previous rendering task exists, cancel it
  67. if (mRendererTask != nullptr)
  68. mRendererTask->cancel();
  69. TEXTURE_DESC cubemapDesc;
  70. cubemapDesc.type = TEX_TYPE_CUBE_MAP;
  71. cubemapDesc.format = PF_RG11B10F;
  72. cubemapDesc.width = ct::IBLUtility::REFLECTION_CUBEMAP_SIZE;
  73. cubemapDesc.height = ct::IBLUtility::REFLECTION_CUBEMAP_SIZE;
  74. cubemapDesc.numMips = PixelUtil::getMaxMipmaps(cubemapDesc.width, cubemapDesc.height, 1, cubemapDesc.format);
  75. cubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
  76. mFilteredTexture = Texture::_createPtr(cubemapDesc);
  77. auto renderComplete = [this]()
  78. {
  79. mRendererTask = nullptr;
  80. };
  81. SPtr<ct::ReflectionProbe> coreProbe = getCore();
  82. SPtr<ct::Texture> coreTexture = mFilteredTexture->getCore();
  83. if (mCustomTexture == nullptr)
  84. {
  85. auto renderReflProbe = [coreTexture, coreProbe]()
  86. {
  87. float radius = coreProbe->mType == ReflectionProbeType::Sphere ? coreProbe->mRadius :
  88. coreProbe->mExtents.length();
  89. ct::CaptureSettings settings;
  90. settings.encodeDepth = true;
  91. settings.depthEncodeNear = radius;
  92. settings.depthEncodeFar = radius + 1; // + 1 arbitrary, make it a customizable value?
  93. ct::gRenderer()->captureSceneCubeMap(coreTexture, coreProbe->getTransform().getPosition(), settings);
  94. ct::gIBLUtility().filterCubemapForSpecular(coreTexture, nullptr);
  95. coreProbe->mFilteredTexture = coreTexture;
  96. ct::gRenderer()->notifyReflectionProbeUpdated(coreProbe.get(), true);
  97. return true;
  98. };
  99. mRendererTask = ct::RendererTask::create("ReflProbeRender", renderReflProbe);
  100. }
  101. else
  102. {
  103. SPtr<ct::Texture> coreCustomTex = mCustomTexture->getCore();
  104. auto filterReflProbe = [coreCustomTex, coreTexture, coreProbe]()
  105. {
  106. ct::gIBLUtility().scaleCubemap(coreCustomTex, 0, coreTexture, 0);
  107. ct::gIBLUtility().filterCubemapForSpecular(coreTexture, nullptr);
  108. coreProbe->mFilteredTexture = coreTexture;
  109. ct::gRenderer()->notifyReflectionProbeUpdated(coreProbe.get(), true);
  110. return true;
  111. };
  112. mRendererTask = ct::RendererTask::create("ReflProbeRender", filterReflProbe);
  113. }
  114. mRendererTask->onComplete.connect(renderComplete);
  115. ct::gRenderer()->addTask(mRendererTask);
  116. }
  117. SPtr<ct::ReflectionProbe> ReflectionProbe::getCore() const
  118. {
  119. return std::static_pointer_cast<ct::ReflectionProbe>(mCoreSpecific);
  120. }
  121. SPtr<ReflectionProbe> ReflectionProbe::createSphere(float radius)
  122. {
  123. ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe(ReflectionProbeType::Sphere, radius, Vector3::ZERO);
  124. SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
  125. probePtr->_setThisPtr(probePtr);
  126. probePtr->initialize();
  127. return probePtr;
  128. }
  129. SPtr<ReflectionProbe> ReflectionProbe::createBox(const Vector3& extents)
  130. {
  131. ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe(ReflectionProbeType::Box, 0.0f, extents);
  132. SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
  133. probePtr->_setThisPtr(probePtr);
  134. probePtr->initialize();
  135. return probePtr;
  136. }
  137. SPtr<ReflectionProbe> ReflectionProbe::createEmpty()
  138. {
  139. ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe();
  140. SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
  141. probePtr->_setThisPtr(probePtr);
  142. return probePtr;
  143. }
  144. SPtr<ct::CoreObject> ReflectionProbe::createCore() const
  145. {
  146. SPtr<ct::Texture> filteredTexture;
  147. if (mFilteredTexture != nullptr)
  148. filteredTexture = mFilteredTexture->getCore();
  149. ct::ReflectionProbe* probe = new (bs_alloc<ct::ReflectionProbe>()) ct::ReflectionProbe(mType, mRadius, mExtents,
  150. filteredTexture);
  151. SPtr<ct::ReflectionProbe> probePtr = bs_shared_ptr<ct::ReflectionProbe>(probe);
  152. probePtr->_setThisPtr(probePtr);
  153. return probePtr;
  154. }
  155. CoreSyncData ReflectionProbe::syncToCore(FrameAlloc* allocator)
  156. {
  157. UINT32 size = getActorSyncDataSize();
  158. size += rttiGetElemSize(mType);
  159. size += rttiGetElemSize(mRadius);
  160. size += rttiGetElemSize(mExtents);
  161. size += rttiGetElemSize(mTransitionDistance);
  162. size += rttiGetElemSize(getCoreDirtyFlags());
  163. size += rttiGetElemSize(mBounds);
  164. size += sizeof(SPtr<ct::Texture>);
  165. UINT8* buffer = allocator->alloc(size);
  166. char* dataPtr = (char*)buffer;
  167. dataPtr = syncActorTo(dataPtr);
  168. dataPtr = rttiWriteElem(mType, dataPtr);
  169. dataPtr = rttiWriteElem(mRadius, dataPtr);
  170. dataPtr = rttiWriteElem(mExtents, dataPtr);
  171. dataPtr = rttiWriteElem(mTransitionDistance, dataPtr);
  172. dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
  173. dataPtr = rttiWriteElem(mBounds, dataPtr);
  174. return CoreSyncData(buffer, size);
  175. }
  176. void ReflectionProbe::_markCoreDirty(ActorDirtyFlag flags)
  177. {
  178. markCoreDirty((UINT32)flags);
  179. }
  180. RTTITypeBase* ReflectionProbe::getRTTIStatic()
  181. {
  182. return ReflectionProbeRTTI::instance();
  183. }
  184. RTTITypeBase* ReflectionProbe::getRTTI() const
  185. {
  186. return ReflectionProbe::getRTTIStatic();
  187. }
  188. namespace ct
  189. {
  190. ReflectionProbe::ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents,
  191. const SPtr<Texture>& filteredTexture)
  192. : ReflectionProbeBase(type, radius, extents), mRendererId(0), mFilteredTexture(filteredTexture)
  193. {
  194. }
  195. ReflectionProbe::~ReflectionProbe()
  196. {
  197. gRenderer()->notifyReflectionProbeRemoved(this);
  198. }
  199. void ReflectionProbe::initialize()
  200. {
  201. updateBounds();
  202. gRenderer()->notifyReflectionProbeAdded(this);
  203. CoreObject::initialize();
  204. }
  205. void ReflectionProbe::syncToCore(const CoreSyncData& data)
  206. {
  207. char* dataPtr = (char*)data.getBuffer();
  208. UINT32 dirtyFlags = 0;
  209. bool oldIsActive = mActive;
  210. ReflectionProbeType oldType = mType;
  211. dataPtr = syncActorFrom(dataPtr);
  212. dataPtr = rttiReadElem(mType, dataPtr);
  213. dataPtr = rttiReadElem(mRadius, dataPtr);
  214. dataPtr = rttiReadElem(mExtents, dataPtr);
  215. dataPtr = rttiReadElem(mTransitionDistance, dataPtr);
  216. dataPtr = rttiReadElem(dirtyFlags, dataPtr);
  217. dataPtr = rttiReadElem(mBounds, dataPtr);
  218. updateBounds();
  219. if (dirtyFlags == (UINT32)ActorDirtyFlag::Transform)
  220. {
  221. if (mActive)
  222. gRenderer()->notifyReflectionProbeUpdated(this, false);
  223. }
  224. else
  225. {
  226. if (oldIsActive != mActive)
  227. {
  228. if (mActive)
  229. gRenderer()->notifyReflectionProbeAdded(this);
  230. else
  231. {
  232. ReflectionProbeType newType = mType;
  233. mType = oldType;
  234. gRenderer()->notifyReflectionProbeRemoved(this);
  235. mType = newType;
  236. }
  237. }
  238. else
  239. {
  240. ReflectionProbeType newType = mType;
  241. mType = oldType;
  242. gRenderer()->notifyReflectionProbeRemoved(this);
  243. mType = newType;
  244. gRenderer()->notifyReflectionProbeAdded(this);
  245. }
  246. }
  247. }
  248. }}