Jelajahi Sumber

Add some code

Panagiotis Christopoulos Charitos 7 tahun lalu
induk
melakukan
11ec16eb87

+ 12 - 0
shaders/Functions.glsl

@@ -354,4 +354,16 @@ F32 cubeCoordSolidAngle(Vec2 norm, F32 cubeFaceSize)
 	return areaElement(v0.x, v0.y) - areaElement(v0.x, v1.y) - areaElement(v1.x, v0.y) + areaElement(v1.x, v1.y);
 }
 
+/// Intersect a ray against an AABB. The ray is inside the AABB. The function returns the distance 'a' where the
+/// intersection point is rayOrigin + rayDir * a
+/// https://community.arm.com/graphics/b/blog/posts/reflections-based-on-local-cubemaps-in-unity
+F32 rayAabbIntersectionInside(Vec3 rayOrigin, Vec3 rayDir, Vec3 aabbMin, Vec3 aabbMax)
+{
+	Vec3 intersectMaxPointPlanes = (aabbMax - rayOrigin) / rayDir;
+	Vec3 intersectMinPointPlanes = (aabbMin - rayOrigin) / rayDir;
+	Vec3 largestParams = max(intersectMaxPointPlanes, intersectMinPointPlanes);
+	F32 distToIntersect = min(min(largestParams.x, largestParams.y), largestParams.z);
+	return distToIntersect;
+}
+
 #endif

+ 32 - 0
shaders/LightFunctions.glsl

@@ -191,4 +191,36 @@ F32 computeAttenuationFactor(F32 lightRadius, Vec3 frag2Light)
 	return att * att;
 }
 
+// Given the probe properties trace a ray inside the probe and find the cube tex coordinates to sample and the color
+// blend weight
+void intersectProbe(Vec3 fragPos, // Ray origin
+	Vec3 rayDir, // Ray direction
+	Vec3 probeAabbMin,
+	Vec3 probeAabbMax,
+	Vec3 probeOrigin, // Cubemap origin
+	F32 fadeDistance,
+	out Vec3 cubeTexCoord, // Cubemap tex coord
+	out F32 blendWeight // Blend weight
+)
+{
+	// Compute the intersection point
+	F32 intresectionDist = rayAabbIntersectionInside(fragPos, rayDir, probeAabbMin, probeAabbMax);
+	Vec3 intresectionPoint = fragPos + intresectionDist * rayDir;
+
+	// Compute the cubemap vector
+	cubeTexCoord = intersectionPoint - probeOrigin;
+
+	// Calculate the weight
+	{
+		// Distance between the frag and the AABB bounds
+		F32 fragBoxDist = length(fragPos - intresectionPoint);
+
+		// Cap the distance
+		fragBoxDist = min(fragBoxDist, fadeDistance);
+
+		// The weight will be zero close to AABB bounds and 1.0 at fadeDistance and less
+		blendWeight = fragBoxDist / fadeDistance;
+	}
+}
+
 #endif

+ 3 - 5
shaders/glsl_cpp_common/ClusteredShading.h

@@ -52,11 +52,9 @@ const U32 SIZEOF_SPOT_LIGHT = 4 * SIZEOF_VEC4 + SIZEOF_MAT4;
 // Representation of a reflection probe
 struct ReflectionProbe
 {
-	// Position of the prove in view space. Radius of probe squared
-	Vec4 m_positionRadiusSq;
-
-	// Slice in u_reflectionsTex vector.
-	Vec4 m_cubemapIndexPad3;
+	Vec4 m_positionCubemapIndex; // xyz: Position of the prove in view space. w: Slice in u_reflectionsTex vector.
+	Vec4 m_aabbMinPad1;
+	Vec4 m_aabbMaxPad1;
 };
 const U32 SIZEOF_REFLECTION_PROBE = 2 * SIZEOF_VEC4;
 

+ 2 - 1
src/anki/renderer/RenderQueue.h

@@ -120,7 +120,8 @@ public:
 	void* m_userData;
 	U64 m_uuid;
 	Vec3 m_worldPosition;
-	F32 m_radius;
+	Vec3 m_aabbMin;
+	Vec3 m_aabbMax;
 	Array<RenderQueue*, 6> m_renderQueues;
 	U32 m_textureArrayIndex; ///< Renderer internal.
 };

+ 22 - 15
src/anki/scene/ReflectionProbeNode.cpp

@@ -46,7 +46,7 @@ ReflectionProbeNode::~ReflectionProbeNode()
 {
 }
 
-Error ReflectionProbeNode::init(F32 radius)
+Error ReflectionProbeNode::init(const Vec4& aabbMinLSpace, const Vec4& aabbMaxLSpace)
 {
 	// Move component first
 	newComponent<MoveComponent>(this);
@@ -55,28 +55,28 @@ Error ReflectionProbeNode::init(F32 radius)
 	newComponent<ReflectionProbeMoveFeedbackComponent>(this);
 
 	// The frustum components
-	const F32 ang = toRad(90.0);
+	const F32 ang = toRad(90.0f);
 	const F32 zNear = FRUSTUM_NEAR_PLANE;
 
 	Mat3 rot;
 
-	rot = Mat3(Euler(0.0, -PI / 2.0, 0.0)) * Mat3(Euler(0.0, 0.0, PI));
+	rot = Mat3(Euler(0.0f, -PI / 2.0f, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
 	m_cubeSides[0].m_localTrf.setRotation(Mat3x4(rot));
-	rot = Mat3(Euler(0.0, PI / 2.0, 0.0)) * Mat3(Euler(0.0, 0.0, PI));
+	rot = Mat3(Euler(0.0f, PI / 2.0f, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
 	m_cubeSides[1].m_localTrf.setRotation(Mat3x4(rot));
-	rot = Mat3(Euler(PI / 2.0, 0.0, 0.0));
+	rot = Mat3(Euler(PI / 2.0f, 0.0f, 0.0f));
 	m_cubeSides[2].m_localTrf.setRotation(Mat3x4(rot));
-	rot = Mat3(Euler(-PI / 2.0, 0.0, 0.0));
+	rot = Mat3(Euler(-PI / 2.0f, 0.0f, 0.0f));
 	m_cubeSides[3].m_localTrf.setRotation(Mat3x4(rot));
-	rot = Mat3(Euler(0.0, PI, 0.0)) * Mat3(Euler(0.0, 0.0, PI));
+	rot = Mat3(Euler(0.0f, PI, 0.0f)) * Mat3(Euler(0.0f, 0.0f, PI));
 	m_cubeSides[4].m_localTrf.setRotation(Mat3x4(rot));
-	rot = Mat3(Euler(0.0, 0.0, PI));
+	rot = Mat3(Euler(0.0f, 0.0f, PI));
 	m_cubeSides[5].m_localTrf.setRotation(Mat3x4(rot));
 
 	for(U i = 0; i < 6; ++i)
 	{
-		m_cubeSides[i].m_localTrf.setOrigin(Vec4(0.0));
-		m_cubeSides[i].m_localTrf.setScale(1.0);
+		m_cubeSides[i].m_localTrf.setOrigin(Vec4(0.0f));
+		m_cubeSides[i].m_localTrf.setScale(1.0f);
 
 		m_cubeSides[i].m_frustum.setAll(ang, ang, zNear, EFFECTIVE_DISTANCE);
 		m_cubeSides[i].m_frustum.resetTransform(m_cubeSides[i].m_localTrf);
@@ -87,13 +87,16 @@ Error ReflectionProbeNode::init(F32 radius)
 	}
 
 	// Spatial component
-	m_spatialSphere.setCenter(Vec4(0.0));
-	m_spatialSphere.setRadius(radius);
-	newComponent<SpatialComponent>(this, &m_spatialSphere);
+	m_aabbMinLSpace = aabbMinLSpace.xyz();
+	m_aabbMaxLSpace = aabbMaxLSpace.xyz();
+	m_spatialAabb.setMin(aabbMinLSpace);
+	m_spatialAabb.setMax(aabbMaxLSpace);
+	newComponent<SpatialComponent>(this, &m_spatialAabb);
 
 	// Reflection probe comp
 	ReflectionProbeComponent* reflc = newComponent<ReflectionProbeComponent>(this);
-	reflc->setRadius(radius);
+	reflc->setPosition(Vec4(0.0f));
+	reflc->setBoundingBox(aabbMinLSpace, aabbMaxLSpace);
 
 	return Error::NONE;
 }
@@ -120,11 +123,15 @@ void ReflectionProbeNode::onMoveUpdate(MoveComponent& move)
 	SpatialComponent& sp = getComponent<SpatialComponent>();
 	sp.markForUpdate();
 	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
-	m_spatialSphere.setCenter(move.getWorldTransform().getOrigin());
+	const Vec3 aabbMinWSpace = m_aabbMinLSpace + move.getWorldTransform().getOrigin().xyz();
+	const Vec3 aabbMaxWSpace = m_aabbMaxLSpace + move.getWorldTransform().getOrigin().xyz();
+	m_spatialAabb.setMin(aabbMinWSpace);
+	m_spatialAabb.setMax(aabbMaxWSpace);
 
 	// Update the refl comp
 	ReflectionProbeComponent& reflc = getComponent<ReflectionProbeComponent>();
 	reflc.setPosition(move.getWorldTransform().getOrigin());
+	reflc.setBoundingBox(aabbMinWSpace.xyz0(), aabbMaxWSpace.xyz0());
 }
 
 Error ReflectionProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)

+ 4 - 15
src/anki/scene/ReflectionProbeNode.h

@@ -32,19 +32,7 @@ public:
 
 	~ReflectionProbeNode();
 
-	ANKI_USE_RESULT Error init(F32 radius);
-
-	U getCubemapArrayIndex() const
-	{
-		ANKI_ASSERT(m_cubemapArrayIdx < 0xFF);
-		return m_cubemapArrayIdx;
-	}
-
-	void setCubemapArrayIndex(U cubemapArrayIdx)
-	{
-		ANKI_ASSERT(cubemapArrayIdx < 0xFF);
-		m_cubemapArrayIdx = cubemapArrayIdx;
-	}
+	ANKI_USE_RESULT Error init(const Vec4& aabbMinLSpace, const Vec4& aabbMaxLSpace);
 
 	ANKI_USE_RESULT Error frameUpdate(Second prevUpdateTime, Second crntTime) override;
 
@@ -57,8 +45,9 @@ private:
 	};
 
 	Array<CubeSide, 6> m_cubeSides;
-	Sphere m_spatialSphere;
-	U8 m_cubemapArrayIdx = 0xFF; ///< Used by the renderer
+	Vec3 m_aabbMinLSpace = Vec3(+1.0f);
+	Vec3 m_aabbMaxLSpace = Vec3(-1.0f);
+	Aabb m_spatialAabb;
 
 	void onMoveUpdate(MoveComponent& move);
 };

+ 20 - 30
src/anki/scene/components/ReflectionProbeComponent.h

@@ -25,67 +25,57 @@ public:
 	{
 	}
 
-	const Vec4& getPosition() const
+	Vec4 getPosition() const
 	{
-		return m_pos;
+		return m_pos.xyz0();
 	}
 
 	void setPosition(const Vec4& pos)
 	{
-		m_pos = pos.xyz0();
+		m_pos = pos.xyz();
 	}
 
-	F32 getRadius() const
+	void setBoundingBox(const Vec4& min, const Vec4& max)
 	{
-		ANKI_ASSERT(m_radius > 0.0);
-		return m_radius;
+		m_aabbMin = min.xyz();
+		m_aabbMax = max.xyz();
 	}
 
-	void setRadius(F32 radius)
+	Vec4 getBoundingBoxMin() const
 	{
-		ANKI_ASSERT(radius > 0.0);
-		m_radius = radius;
+		return m_aabbMin.xyz0();
 	}
 
-	Bool getMarkedForRendering() const
-	{
-		return m_markedForRendering;
-	}
-
-	void setMarkedForRendering(Bool render)
+	Vec4 getBoundingBoxMax() const
 	{
-		m_markedForRendering = render;
+		return m_aabbMax.xyz0();
 	}
 
-	void setTextureArrayIndex(U idx)
-	{
-		m_textureArrayIndex = idx;
-	}
-
-	U getTextureArrayIndex() const
+	Bool getMarkedForRendering() const
 	{
-		ANKI_ASSERT(m_textureArrayIndex < MAX_U16);
-		return m_textureArrayIndex;
+		return m_markedForRendering;
 	}
 
 	void setupReflectionProbeQueueElement(ReflectionProbeQueueElement& el) const
 	{
+		ANKI_ASSERT(m_aabbMin < m_aabbMax);
+		ANKI_ASSERT(m_pos > m_aabbMin & m_pos < m_aabbMax);
 		el.m_feedbackCallback = reflectionProbeQueueElementFeedbackCallback;
 		el.m_userData = const_cast<ReflectionProbeComponent*>(this);
 		el.m_uuid = getUuid();
-		el.m_worldPosition = m_pos.xyz();
-		el.m_radius = m_radius;
+		el.m_worldPosition = m_pos;
+		el.m_aabbMin = m_aabbMin;
+		el.m_aabbMax = m_aabbMax;
 		el.m_textureArrayIndex = MAX_U32;
 		el.m_drawCallback = debugDrawCallback;
 	}
 
 private:
-	Vec4 m_pos = Vec4(0.0);
-	F32 m_radius = 0.0;
+	Vec3 m_pos = Vec3(0.0f);
+	Vec3 m_aabbMin = Vec3(+1.0f);
+	Vec3 m_aabbMax = Vec3(-1.0f);
 	Bool8 m_markedForRendering = false;
 
-	U16 m_textureArrayIndex = MAX_U16; ///< Used by the renderer
-
 	static void reflectionProbeQueueElementFeedbackCallback(Bool fillRenderQueuesOnNextFrame, void* userData)
 	{
 		ANKI_ASSERT(userData);