BsReflectionProbe.cpp 8.8 KB

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