Browse Source

Complete the GlobalIlluminationProbeNode

Panagiotis Christopoulos Charitos 6 years ago
parent
commit
c9a2d94e45

+ 176 - 3
src/anki/scene/GlobalIlluminationProbeNode.cpp

@@ -4,24 +4,197 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/scene/GlobalIlluminationProbeNode.h>
+#include <anki/scene/SceneGraph.h>
+#include <anki/scene/components/FrustumComponent.h>
+#include <anki/scene/components/MoveComponent.h>
+#include <anki/scene/components/SpatialComponent.h>
+#include <anki/scene/components/GlobalIlluminationProbeComponent.h>
 
 namespace anki
 {
 
+const FrustumComponentVisibilityTestFlag FRUSTUM_TEST_FLAGS =
+	FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS
+	| FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE;
+
+/// Feedback component
+class GlobalIlluminationProbeNode::MoveFeedbackComponent : public SceneComponent
+{
+public:
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
+	{
+	}
+
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
+	{
+		updated = false;
+
+		MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
+		{
+			// Move updated
+			GlobalIlluminationProbeNode& dnode = static_cast<GlobalIlluminationProbeNode&>(node);
+			dnode.onMoveUpdate(move);
+		}
+
+		return Error::NONE;
+	}
+};
+
+/// Feedback component
+class GlobalIlluminationProbeNode::ShapeFeedbackComponent : public SceneComponent
+{
+public:
+	ShapeFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
+	{
+	}
+
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
+	{
+		updated = false;
+
+		GlobalIlluminationProbeComponent& probec = node.getComponent<GlobalIlluminationProbeComponent>();
+		if(probec.getTimestamp() == node.getGlobalTimestamp() || probec.getMarkedForRendering())
+		{
+			// Move updated
+			GlobalIlluminationProbeNode& dnode = static_cast<GlobalIlluminationProbeNode&>(node);
+			dnode.onShapeUpdateOrProbeNeedsRendering();
+		}
+
+		return Error::NONE;
+	}
+};
+
 GlobalIlluminationProbeNode::~GlobalIlluminationProbeNode()
 {
 }
 
 Error GlobalIlluminationProbeNode::init()
 {
-	// TODO
+	// Move component first
+	newComponent<MoveComponent>();
+
+	// Feedback component
+	newComponent<MoveFeedbackComponent>();
+
+	// GI probe comp
+	GlobalIlluminationProbeComponent* giprobec =
+		newComponent<GlobalIlluminationProbeComponent>(getSceneGraph().getNewUuid());
+	giprobec->setBoundingBox(m_spatialAabb.getMin(), m_spatialAabb.getMax());
+
+	// Second feedback component
+	newComponent<ShapeFeedbackComponent>();
+
+	// The frustum components
+	const F32 ang = toRad(90.0f);
+	const F32 zNear = LIGHT_FRUSTUM_NEAR_PLANE;
+
+	Mat3 rot;
+	rot = Mat3(Euler(0.0f, -PI / 2.0f, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
+	m_cubeFaceTransforms[0].setRotation(Mat3x4(rot));
+	rot = Mat3(Euler(0.0f, PI / 2.0f, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
+	m_cubeFaceTransforms[1].setRotation(Mat3x4(rot));
+	rot = Mat3(Euler(PI / 2.0f, 0.0f, 0.0f));
+	m_cubeFaceTransforms[2].setRotation(Mat3x4(rot));
+	rot = Mat3(Euler(-PI / 2.0f, 0.0f, 0.0f));
+	m_cubeFaceTransforms[3].setRotation(Mat3x4(rot));
+	rot = Mat3(Euler(0.0f, PI, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
+	m_cubeFaceTransforms[4].setRotation(Mat3x4(rot));
+	rot = Mat3(Euler(0.0f, 0.0f, PI));
+	m_cubeFaceTransforms[5].setRotation(Mat3x4(rot));
+
+	for(U i = 0; i < 6; ++i)
+	{
+		m_cubeFaceTransforms[i].setOrigin(Vec4(0.0f));
+		m_cubeFaceTransforms[i].setScale(1.0f);
+
+		FrustumComponent* frc = newComponent<FrustumComponent>(this, FrustumType::PERSPECTIVE);
+		const F32 tempEffectiveDistance = 1.0f;
+		frc->setPerspective(zNear, tempEffectiveDistance, ang, ang);
+		frc->setTransform(m_cubeFaceTransforms[i]);
+		frc->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
+		frc->setEffectiveShadowDistance(getSceneGraph().getLimits().m_reflectionProbeShadowEffectiveDistance);
+	}
+
+	// Spatial component
+	SpatialComponent* spatialc = newComponent<SpatialComponent>(this, &m_spatialAabb);
+	spatialc->setUpdateOctreeBounds(false);
+
 	return Error::NONE;
 }
 
+void GlobalIlluminationProbeNode::onMoveUpdate(MoveComponent& move)
+{
+	// Update the probe comp
+	const Vec4 displacement = move.getWorldTransform().getOrigin() - m_previousPosition;
+	m_previousPosition = move.getWorldTransform().getOrigin();
+
+	GlobalIlluminationProbeComponent& gic = getComponent<GlobalIlluminationProbeComponent>();
+	gic.setBoundingBox(gic.getAlignedBoundingBoxMin() + displacement, gic.getAlignedBoundingBoxMax() + displacement);
+}
+
+void GlobalIlluminationProbeNode::onShapeUpdateOrProbeNeedsRendering()
+{
+	GlobalIlluminationProbeComponent& gic = getComponent<GlobalIlluminationProbeComponent>();
+
+	// Update the frustum component if the shape was updated or the probe needs rendering
+	{
+		// Compute effective distance
+		F32 effectiveDistance = gic.getAlignedBoundingBoxMax().x() - gic.getAlignedBoundingBoxMin().x();
+		effectiveDistance =
+			max(effectiveDistance, gic.getAlignedBoundingBoxMax().y() - gic.getAlignedBoundingBoxMin().y());
+		effectiveDistance =
+			max(effectiveDistance, gic.getAlignedBoundingBoxMax().z() - gic.getAlignedBoundingBoxMin().z());
+		effectiveDistance = max(effectiveDistance, getSceneGraph().getLimits().m_reflectionProbeEffectiveDistance);
+
+		// Update frustum components
+		U count = 0;
+		Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
+			Transform trf = m_cubeFaceTransforms[count];
+			trf.setOrigin(gic.getRenderPosition());
+
+			frc.setTransform(trf);
+			frc.setFar(effectiveDistance);
+			++count;
+
+			return Error::NONE;
+		});
+
+		ANKI_ASSERT(count == 6);
+		(void)err;
+	}
+
+	// Update the spatial comp
+	const Bool shapeWasUpdated = gic.getTimestamp() == getGlobalTimestamp();
+	if(shapeWasUpdated)
+	{
+		// Update only when the shape was actually update
+
+		SpatialComponent& sp = getComponent<SpatialComponent>();
+		sp.markForUpdate();
+		sp.setSpatialOrigin((m_spatialAabb.getMax() + m_spatialAabb.getMin()) / 2.0f);
+		m_spatialAabb.setMin(gic.getAlignedBoundingBoxMin());
+		m_spatialAabb.setMax(gic.getAlignedBoundingBoxMax());
+	}
+}
+
 Error GlobalIlluminationProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 {
-	// TODO
+	// Check the reflection probe component and if it's marked for rendering enable the frustum components
+	const GlobalIlluminationProbeComponent& gic = getComponent<GlobalIlluminationProbeComponent>();
+
+	const FrustumComponentVisibilityTestFlag testFlags =
+		gic.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
+
+	const Error err = iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) -> Error {
+		frc.setEnabledVisibilityTests(testFlags);
+		return Error::NONE;
+	});
+	(void)err;
+
 	return Error::NONE;
 }
 
-} // end namespace anki
+} // end namespace anki

+ 4 - 1
src/anki/scene/GlobalIlluminationProbeNode.h

@@ -31,11 +31,14 @@ public:
 
 private:
 	class MoveFeedbackComponent;
+	class ShapeFeedbackComponent;
 
 	Array<Transform, 6> m_cubeFaceTransforms;
-	Aabb m_spatialAabb;
+	Aabb m_spatialAabb = Aabb(Vec3(-1.0f), Vec3(1.0f));
+	Vec4 m_previousPosition = Vec4(0.0f);
 
 	void onMoveUpdate(MoveComponent& move);
+	void onShapeUpdateOrProbeNeedsRendering();
 };
 /// @}
 

+ 2 - 2
src/anki/scene/ReflectionProbeNode.cpp

@@ -147,10 +147,10 @@ Error ReflectionProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 	// Check the reflection probe component and if it's marked for rendering enable the frustum components
 	const ReflectionProbeComponent& reflc = getComponent<ReflectionProbeComponent>();
 
-	FrustumComponentVisibilityTestFlag testFlags =
+	const FrustumComponentVisibilityTestFlag testFlags =
 		reflc.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
 
-	Error err = iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) -> Error {
+	const Error err = iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) -> Error {
 		frc.setEnabledVisibilityTests(testFlags);
 		return Error::NONE;
 	});