ReflectionProbeNode.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/scene/ReflectionProbeNode.h>
  6. #include <anki/scene/components/ReflectionProbeComponent.h>
  7. #include <anki/scene/components/MoveComponent.h>
  8. #include <anki/scene/components/FrustumComponent.h>
  9. #include <anki/scene/components/SpatialComponent.h>
  10. #include <anki/scene/SceneGraph.h>
  11. #include <anki/scene/SceneGraph.h>
  12. #include <anki/renderer/LightShading.h>
  13. #include <anki/shaders/include/ClusteredShadingTypes.h>
  14. namespace anki
  15. {
  16. const FrustumComponentVisibilityTestFlag FRUSTUM_TEST_FLAGS =
  17. FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS
  18. | FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE;
  19. /// Feedback component
  20. class ReflectionProbeNode::MoveFeedbackComponent : public SceneComponent
  21. {
  22. public:
  23. MoveFeedbackComponent()
  24. : SceneComponent(SceneComponentType::NONE)
  25. {
  26. }
  27. Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
  28. {
  29. updated = false;
  30. MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
  31. if(move.getTimestamp() == node.getGlobalTimestamp())
  32. {
  33. // Move updated
  34. ReflectionProbeNode& dnode = static_cast<ReflectionProbeNode&>(node);
  35. dnode.onMoveUpdate(move);
  36. }
  37. return Error::NONE;
  38. }
  39. };
  40. ReflectionProbeNode::~ReflectionProbeNode()
  41. {
  42. }
  43. Error ReflectionProbeNode::init(const Vec4& aabbMinLSpace, const Vec4& aabbMaxLSpace)
  44. {
  45. // Compute effective distance
  46. F32 effectiveDistance = aabbMaxLSpace.x() - aabbMinLSpace.x();
  47. effectiveDistance = max(effectiveDistance, aabbMaxLSpace.y() - aabbMinLSpace.y());
  48. effectiveDistance = max(effectiveDistance, aabbMaxLSpace.z() - aabbMinLSpace.z());
  49. effectiveDistance = max(effectiveDistance, getSceneGraph().getLimits().m_reflectionProbeEffectiveDistance);
  50. // Move component first
  51. newComponent<MoveComponent>();
  52. // Feedback component
  53. newComponent<MoveFeedbackComponent>();
  54. // The frustum components
  55. const F32 ang = toRad(90.0f);
  56. const F32 zNear = LIGHT_FRUSTUM_NEAR_PLANE;
  57. Mat3 rot;
  58. rot = Mat3(Euler(0.0f, -PI / 2.0f, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
  59. m_cubeSides[0].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
  60. rot = Mat3(Euler(0.0f, PI / 2.0f, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
  61. m_cubeSides[1].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
  62. rot = Mat3(Euler(PI / 2.0f, 0.0f, 0.0f));
  63. m_cubeSides[2].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
  64. rot = Mat3(Euler(-PI / 2.0f, 0.0f, 0.0f));
  65. m_cubeSides[3].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
  66. rot = Mat3(Euler(0.0f, PI, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
  67. m_cubeSides[4].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
  68. rot = Mat3(Euler(0.0f, 0.0f, PI));
  69. m_cubeSides[5].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
  70. for(U i = 0; i < 6; ++i)
  71. {
  72. m_cubeSides[i].m_localTrf.setOrigin(Vec4(0.0f));
  73. m_cubeSides[i].m_localTrf.setScale(1.0f);
  74. FrustumComponent* frc = newComponent<FrustumComponent>(this, FrustumType::PERSPECTIVE);
  75. frc->setPerspective(zNear, effectiveDistance, ang, ang);
  76. frc->setTransform(m_cubeSides[i].m_localTrf);
  77. frc->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
  78. frc->setEffectiveShadowDistance(getSceneGraph().getLimits().m_reflectionProbeShadowEffectiveDistance);
  79. }
  80. // Spatial component
  81. m_aabbMinLSpace = aabbMinLSpace.xyz();
  82. m_aabbMaxLSpace = aabbMaxLSpace.xyz();
  83. m_spatialAabb.setMin(aabbMinLSpace);
  84. m_spatialAabb.setMax(aabbMaxLSpace);
  85. SpatialComponent* spatialc = newComponent<SpatialComponent>(this, &m_spatialAabb);
  86. spatialc->setUpdateOctreeBounds(false);
  87. // Reflection probe comp
  88. ReflectionProbeComponent* reflc = newComponent<ReflectionProbeComponent>(getSceneGraph().getNewUuid());
  89. reflc->setPosition(Vec4(0.0f));
  90. reflc->setBoundingBox(aabbMinLSpace, aabbMaxLSpace);
  91. reflc->setDrawCallback(drawCallback, this);
  92. // Misc
  93. ANKI_CHECK(m_dbgDrawer.init(&getResourceManager()));
  94. ANKI_CHECK(getResourceManager().loadResource("engine_data/Mirror.ankitex", m_dbgTex));
  95. return Error::NONE;
  96. }
  97. void ReflectionProbeNode::onMoveUpdate(MoveComponent& move)
  98. {
  99. // Update frustum components
  100. U count = 0;
  101. Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
  102. Transform trf = m_cubeSides[count].m_localTrf;
  103. trf.setOrigin(move.getWorldTransform().getOrigin());
  104. frc.setTransform(trf);
  105. ++count;
  106. return Error::NONE;
  107. });
  108. ANKI_ASSERT(count == 6);
  109. (void)err;
  110. // Update the spatial comp
  111. SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
  112. sp.markForUpdate();
  113. sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
  114. const Vec3 aabbMinWSpace = m_aabbMinLSpace + move.getWorldTransform().getOrigin().xyz();
  115. const Vec3 aabbMaxWSpace = m_aabbMaxLSpace + move.getWorldTransform().getOrigin().xyz();
  116. m_spatialAabb.setMin(aabbMinWSpace);
  117. m_spatialAabb.setMax(aabbMaxWSpace);
  118. // Update the refl comp
  119. ReflectionProbeComponent& reflc = getFirstComponentOfType<ReflectionProbeComponent>();
  120. reflc.setPosition(move.getWorldTransform().getOrigin());
  121. reflc.setBoundingBox(aabbMinWSpace.xyz0(), aabbMaxWSpace.xyz0());
  122. }
  123. Error ReflectionProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
  124. {
  125. // Check the reflection probe component and if it's marked for rendering enable the frustum components
  126. const ReflectionProbeComponent& reflc = getFirstComponentOfType<ReflectionProbeComponent>();
  127. const FrustumComponentVisibilityTestFlag testFlags =
  128. reflc.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
  129. const Error err = iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) -> Error {
  130. frc.setEnabledVisibilityTests(testFlags);
  131. return Error::NONE;
  132. });
  133. (void)err;
  134. return Error::NONE;
  135. }
  136. void ReflectionProbeNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData)
  137. {
  138. Mat4* const mvps = ctx.m_frameAllocator.newArray<Mat4>(userData.getSize());
  139. Vec3* const positions = ctx.m_frameAllocator.newArray<Vec3>(userData.getSize());
  140. for(U32 i = 0; i < userData.getSize(); ++i)
  141. {
  142. const ReflectionProbeNode& self = *static_cast<const ReflectionProbeNode*>(userData[i]);
  143. const ReflectionProbeComponent& rComp = self.getFirstComponentOfType<ReflectionProbeComponent>();
  144. const Vec3 tsl = (rComp.getBoundingBoxMin().xyz() + rComp.getBoundingBoxMax().xyz()) / 2.0f;
  145. const Vec3 scale = (tsl - rComp.getBoundingBoxMin().xyz());
  146. // Set non uniform scale.
  147. Mat3 rot = Mat3::getIdentity();
  148. rot(0, 0) *= scale.x();
  149. rot(1, 1) *= scale.y();
  150. rot(2, 2) *= scale.z();
  151. mvps[i] = ctx.m_viewProjectionMatrix * Mat4(tsl.xyz1(), rot, 1.0f);
  152. positions[i] = tsl.xyz();
  153. }
  154. const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);
  155. if(enableDepthTest)
  156. {
  157. ctx.m_commandBuffer->setDepthCompareOperation(CompareOperation::LESS);
  158. }
  159. else
  160. {
  161. ctx.m_commandBuffer->setDepthCompareOperation(CompareOperation::ALWAYS);
  162. }
  163. const ReflectionProbeNode& self = *static_cast<const ReflectionProbeNode*>(userData[0]);
  164. self.m_dbgDrawer.drawCubes(ConstWeakArray<Mat4>(mvps, userData.getSize()), Vec4(0.0f, 0.0f, 1.0f, 1.0f), 1.0f,
  165. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), 2.0f,
  166. *ctx.m_stagingGpuAllocator, ctx.m_commandBuffer);
  167. self.m_dbgDrawer.drawBillboardTextures(
  168. ctx.m_projectionMatrix, ctx.m_viewMatrix, ConstWeakArray<Vec3>(positions, userData.getSize()), Vec4(1.0f),
  169. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), self.m_dbgTex->getGrTextureView(),
  170. ctx.m_sampler, Vec2(0.75f), *ctx.m_stagingGpuAllocator, ctx.m_commandBuffer);
  171. ctx.m_frameAllocator.deleteArray(positions, userData.getSize());
  172. ctx.m_frameAllocator.deleteArray(mvps, userData.getSize());
  173. // Restore state
  174. if(!enableDepthTest)
  175. {
  176. ctx.m_commandBuffer->setDepthCompareOperation(CompareOperation::LESS);
  177. }
  178. }
  179. } // end namespace anki