Przeglądaj źródła

Switch to sphere reflection

Panagiotis Christopoulos Charitos 10 lat temu
rodzic
commit
8a3e0b2d0c

+ 1 - 1
include/anki/gr/gl/RenderingThread.h

@@ -68,7 +68,7 @@ private:
 	WeakPtr<GrManager> m_manager;
 	WeakPtr<GrManagerInterface> m_interface;
 
-	static const U QUEUE_SIZE = 1024;
+	static const U QUEUE_SIZE = 1024 * 2;
 	DArray<CommandBufferPtr> m_queue; ///< Command queue
 	U64 m_tail; ///< Tail of queue
 	U64 m_head; ///< Head of queue. Points to the end

+ 0 - 6
include/anki/renderer/Ir.h

@@ -40,11 +40,6 @@ anki_internal:
 		return m_probesToken;
 	}
 
-	DynamicBufferToken getProxiesToken() const
-	{
-		return m_proxiesToken;
-	}
-
 	U getCubemapArrayMipmapCount() const
 	{
 		return m_cubemapArrMipCount;
@@ -64,7 +59,6 @@ private:
 	U16 m_cubemapArrSize = 0;
 	U16 m_fbSize = 0;
 	DynamicBufferToken m_probesToken;
-	DynamicBufferToken m_proxiesToken;
 	DArray<CacheEntry> m_cacheEntries;
 
 	ANKI_USE_RESULT Error renderReflection(SceneNode& node,

+ 1 - 0
include/anki/scene/Visibility.h

@@ -60,6 +60,7 @@ public:
 	{
 		m_node = other.m_node;
 		m_spatialIndices = other.m_spatialIndices;
+		m_frustumDistanceSquared = other.m_frustumDistanceSquared;
 		m_spatialsCount = other.m_spatialsCount;
 		return *this;
 	}

+ 34 - 110
shaders/ImageReflections.glsl

@@ -10,25 +10,6 @@
 
 #pragma anki include "shaders/Common.glsl"
 
-/// Basically a quad in view space.
-struct ReflectionProxy
-{
-	// xyz: plane.n, w: plane.offset.
-	vec4 plane;
-
-	// xyz: -plane.n, w: plane.offset.
-	vec4 negPlane;
-
-	// The points of the quad.
-	vec4 quadPoints[4];
-
-	// Used to check if the intersection point fall inside the quad. It's:
-	// edgeCrossProd[0] = cross(plane.n, (quadPoints[1] - quadPoints[0]));
-	// edgeCrossProd[1] = cross(plane.n, (quadPoints[2] - quadPoints[1]));
-	// etc...
-	vec4 edgeCrossProd[4];
-};
-
 // Representation of a reflection probe
 struct ReflectionProbe
 {
@@ -39,16 +20,10 @@ struct ReflectionProbe
 	vec4 cubemapIndexPad3;
 };
 
-layout(std140, row_major, SS_BINDING(IMAGE_REFLECTIONS_SET,
-	IMAGE_REFLECTIONS_PROXY_SS_BINDING)) readonly buffer _irs0
-{
-	uvec4 u_proxyCountReflectionProbeCountPad3;
-	ReflectionProxy u_reflectionProxies[];
-};
-
 layout(std140, row_major, SS_BINDING(IMAGE_REFLECTIONS_SET,
 	IMAGE_REFLECTIONS_PROBE_SS_BINDING)) readonly buffer _irs1
 {
+	uvec4 u_reflectionProbeCountPad3;
 	mat3 u_invViewRotation;
 	ReflectionProbe u_reflectionProbes[];
 };
@@ -57,94 +32,60 @@ layout(TEX_BINDING(IMAGE_REFLECTIONS_SET, IMAGE_REFLECTIONS_TEX_BINDING))
 	uniform samplerCubeArray u_reflectionsTex;
 
 //==============================================================================
-// Test if a ray intersects with the proxy.
-// p is the origin of the ray, r the ray vector, c is the intersection point.
-bool testReflectionProxy(in uint proxyIdx, in vec3 p, in vec3 r, out vec3 c,
-	out float s)
+// Compute the cubemap texture lookup vector given the reflection vector (r)
+// the radius squared of the probe (R2) and the frag pos in sphere space (f)
+vec3 computeCubemapVec(in vec3 r, in float R2, in vec3 f)
 {
-	ReflectionProxy proxy = u_reflectionProxies[proxyIdx];
-	bool intersect;
-
-	// Compute the inverce direction of p to the plane
-	float d = dot(proxy.negPlane, vec4(p, 1.0));
-
-	// Compute another dot
-	float a = dot(proxy.plane.xyz, r);
-
-	if(all(lessThan(vec2(d, a), vec2(0.0))))
-	{
-		s = d / a;
-		c = p + s * r;
-
-		// Now check each edge
-		vec4 tests;
-		for(uint i = 0; i < 4; ++i)
-		{
-			tests[i] =
-				dot(c - proxy.quadPoints[i].xyz, proxy.edgeCrossProd[i].xyz);
-		}
-
-		intersect = all(greaterThanEqual(tests, vec4(0.0)));
-	}
-	else
-	{
-		intersect = false;
-	}
-
-	return intersect;
+	// Compute the collision of the r to the inner part of the sphere
+	// From now on we work on the sphere's space
+
+	// Project the center of the sphere (it's zero now since we are in sphere
+	// space) in ray "f,r"
+	vec3 p = f - r * dot(f, r);
+
+	// The collision to the sphere is point x where x = p + T * r
+	// Because of the pythagorean theorem: R^2 = dot(p, p) + dot(T * r, T * r)
+	// solving for T, T = R / |p|
+	// then x becomes x = sqrt(R^2 - dot(p, p)) * r + p;
+	float pp = dot(p, p);
+	pp = min(pp, R2);
+	float sq = sqrt(R2 - pp);
+	vec3 x = p + sq * r;
+
+	// Rotate UV to move it to world space
+	vec3 uv = u_invViewRotation * normalize(x);
+
+	return uv;
 }
 
 //==============================================================================
-// Find a point that the ray (p,r) hit a proxy. Return the intersection point.
-bool findCloseProxyIntersection(in vec3 p, in vec3 r, out vec3 c)
+vec3 readReflection(in vec3 posVSpace, in vec3 normalVSpace, in float lod)
 {
-	const float BIG_FLOAT = 1000000.0;
-	float distSq = BIG_FLOAT;
-	uint proxyCount = u_proxyCountReflectionProbeCountPad3.x;
-	for(uint i = 0; i < proxyCount; ++i)
-	{
-		vec3 intersection;
-		float s;
-		if(testReflectionProxy(i, p, r, intersection, s))
-		{
-			if(s < distSq)
-			{
-				// Intersection point is closer than the prev one
-				distSq = s;
-				c = intersection;
-			}
-		}
-	}
+	vec3 color = IMAGE_REFLECTIONS_DEFAULT_COLOR;
 
-	return distSq < BIG_FLOAT;
-}
+	// Reflection direction
+	vec3 eye = normalize(posVSpace);
+	vec3 r = reflect(eye, normalVSpace);
 
-//==============================================================================
-void readFromProbes(in vec3 intersection, in float lod, out vec3 color)
-{
-	// Iterate probes to find the cubemap
-	uint count = u_proxyCountReflectionProbeCountPad3.y;
+	// Check proxy
+	uint count = u_reflectionProbeCountPad3.x;
 	for(uint i = 0; i < count; ++i)
 	{
 		float R2 = u_reflectionProbes[i].positionRadiusSq.w;
 		vec3 center = u_reflectionProbes[i].positionRadiusSq.xyz;
 
 		// Check if the point is inside the sphere
-		vec3 f = intersection - center;
+		vec3 f = posVSpace - center;
 		float d = dot(f, f);
 		if(d < R2)
 		{
 			// Found something
-			float cubemapIndex = u_reflectionProbes[i].cubemapIndexPad3.x;
-			vec3 probeOrigin = u_reflectionProbes[i].positionRadiusSq.xyz;
 
 			// Cubemap UV in view space
-			vec3 uv = normalize(intersection - probeOrigin);
-
-			// Rotate UV to move it to world space
-			uv = u_invViewRotation * uv;
+			vec3 uv = computeCubemapVec(r, R2, f);
 
 			// Read!
+			float cubemapIndex = u_reflectionProbes[i].cubemapIndexPad3.x;
 			vec3 c =
 				textureLod(u_reflectionsTex, vec4(uv, cubemapIndex), lod).rgb;
 
@@ -154,23 +95,6 @@ void readFromProbes(in vec3 intersection, in float lod, out vec3 color)
 			//Equivelent: color = c * (1.0 - factor) + color * factor;
 		}
 	}
-}
-
-//==============================================================================
-vec3 readReflection(in vec3 posVSpace, in vec3 normalVSpace, in float lod)
-{
-	vec3 color = IMAGE_REFLECTIONS_DEFAULT_COLOR;
-
-	// Reflection direction
-	vec3 eye = normalize(posVSpace);
-	vec3 r = reflect(eye, normalVSpace);
-
-	// Check proxy
-	vec3 intersection;
-	if(findCloseProxyIntersection(posVSpace, r, intersection))
-	{
-		readFromProbes(intersection, lod, color);
-	}
 
 	return color;
 }

+ 12 - 13
shaders/IsLp.frag.glsl

@@ -29,13 +29,11 @@ layout(location = 0) out vec3 out_color;
 
 #if IR == 1
 #define IMAGE_REFLECTIONS_SET 0
-#define IMAGE_REFLECTIONS_PROXY_SS_BINDING 5
-#define IMAGE_REFLECTIONS_PROBE_SS_BINDING 6
+#define IMAGE_REFLECTIONS_PROBE_SS_BINDING 5
 #define IMAGE_REFLECTIONS_TEX_BINDING 6
-#define IMAGE_REFLECTIONS_DEFAULT_COLOR vec3(1.0)
+#define IMAGE_REFLECTIONS_DEFAULT_COLOR vec3(0.0)
 #pragma anki include "shaders/ImageReflections.glsl"
 #undef IMAGE_REFLECTIONS_SET
-#undef IMAGE_REFLECTIONS_PROXY_SS_BINDING
 #undef IMAGE_REFLECTIONS_PROBE_SS_BINDING
 #undef IMAGE_REFLECTIONS_DEFAULT_COLOR
 #endif
@@ -64,7 +62,7 @@ vec3 getFragPosVSpace()
 	vec3 l = normalize(frag2Light); \
 	float nol = max(0.0, dot(normal, l)); \
 	vec3 specC = computeSpecularColorBrdf(viewDir, l, normal, specCol, \
-		light.specularColorTexId.rgb, a2, nol, refl); \
+		light.specularColorTexId.rgb, a2, nol); \
 	vec3 diffC = computeDiffuseColor( \
 		diffCol, light.diffuseColorShadowmapId.rgb); \
 	float att = computeAttenuationFactor(light.posRadius.w, frag2Light); \
@@ -101,13 +99,6 @@ void main()
 
 	float a2 = pow(max(EPSILON, roughness), 2.0);
 
-#if IR == 1
-	float reflLod = float(IR_MIPMAP_COUNT) * roughness;
-	vec3 refl = readReflection(fragPos, normal, reflLod);
-#else
-	const vec3 refl = vec3(1.0);
-#endif
-
 	// Ambient and emissive color
 	out_color = diffCol * u_lightingUniforms.sceneAmbientColor.rgb
 		+ diffCol * emission;
@@ -174,6 +165,14 @@ void main()
 		* vec3(0.01, 0.001, 0.001);
 #endif
 
+#if IR == 1
+	{
+		float reflLod = float(IR_MIPMAP_COUNT) * roughness;
+		vec3 refl = readReflection(fragPos, normal, reflLod);
+		out_color += refl * (1.0 - roughness);
+	}
+#endif
+
 #if 0
 	if(pointLightsCount == 0)
 	{
@@ -195,7 +194,7 @@ void main()
 		out_color += vec3(1.0, 0.0, 0.0);
 	}
 #if IR == 1
-	out_color = out_color * 0.0000 + readReflection(fragPos, normal, 0.0) *1.0;
+	out_color = readReflection(fragPos, normal, 0.0);
 #endif
 #endif
 }

+ 1 - 3
shaders/LightFunctions.glsl

@@ -45,15 +45,13 @@ vec3 computeSpecularColorBrdf(
 	vec3 specCol,
 	vec3 lightSpecCol,
 	float a2, // rougness^2
-	float nol, // N dot L
-	vec3 reflection) // For fresnel
+	float nol) // N dot L
 {
 	vec3 h = normalize(l + v);
 
 	// Fresnel (Schlick)
 	float loh = max(EPSILON, dot(l, h));
 	vec3 f = specCol + (1.0 - specCol) * pow((1.0 + EPSILON - loh), 5.0);
-	f *= reflection;
 	//float f = specColor + (1.0 - specColor)
 	//	* pow(2.0, (-5.55473 * loh - 6.98316) * loh);
 

+ 1 - 5
src/core/Config.cpp

@@ -14,10 +14,6 @@ Config::Config()
 	// Renderer
 	//
 
-	// Ms
-	newOption("ms.ez.enabled", false);
-	newOption("ms.ez.maxObjectsToDraw", 10);
-
 	// Is
 	newOption("is.sm.enabled", true);
 	newOption("is.sm.poissonEnabled", true);
@@ -64,7 +60,7 @@ Config::Config()
 	// Reflections
 	newOption("ir.enabled", true);
 	newOption("ir.rendererSize", 64);
-	newOption("ir.cubemapTextureArraySize", 8);
+	newOption("ir.cubemapTextureArraySize", 16);
 
 	// Dbg
 	newOption("dbg.enabled", false);

+ 2 - 4
src/renderer/Drawer.cpp

@@ -367,10 +367,8 @@ Error RenderableDrawer::renderSingle(RenderContext& ctx)
 	}
 
 	// Calculate the key
-	Vec4 camPos = ctx.m_frc->getFrustumOrigin();
-	F32 dist = (ctx.m_visibleNode->m_node->getComponent<SpatialComponent>().
-		getSpatialOrigin() - camPos).getLength();
-	F32 flod = m_r->calculateLod(dist);
+	F32 flod = m_r->calculateLod(
+		sqrt(ctx.m_visibleNode->m_frustumDistanceSquared));
 	flod = min<F32>(flod, MAX_LODS - 1);
 	ctx.m_flod = flod;
 

+ 25 - 82
src/renderer/Ir.cpp

@@ -5,12 +5,12 @@
 
 #include <anki/renderer/Ir.h>
 #include <anki/renderer/Is.h>
+#include <anki/renderer/Pps.h>
 #include <anki/core/Config.h>
 #include <anki/scene/SceneNode.h>
 #include <anki/scene/Visibility.h>
 #include <anki/scene/FrustumComponent.h>
 #include <anki/scene/ReflectionProbeComponent.h>
-#include <anki/scene/ReflectionProxyComponent.h>
 
 namespace anki {
 
@@ -18,14 +18,6 @@ namespace anki {
 // Misc                                                                        =
 //==============================================================================
 
-struct ShaderReflectionProxy
-{
-	Vec4 m_plane;
-	Vec4 m_negPlane;
-	Array<Vec4, 4> m_quadPoints;
-	Array<Vec4, 4> m_edgeCrossProd;
-};
-
 struct ShaderReflectionProbe
 {
 	Vec3 m_pos;
@@ -76,7 +68,10 @@ Error Ir::init(const ConfigSet& initializer)
 	config.set("is.sm.poissonEnabled", false);
 	config.set("is.sm.resolution", 16);
 	config.set("lf.maxFlares", 8);
-	config.set("pps.enabled", false);
+	config.set("pps.enabled", true);
+	config.set("pps.bloom.enabled", true);
+	config.set("pps.ssao.enabled", false);
+	config.set("pps.sslr.enabled", false);
 	config.set("renderingQuality", 1.0);
 	config.set("clusterSizeZ", 1); // XXX A bug if more. Fix it
 	config.set("width", m_fbSize);
@@ -96,7 +91,7 @@ Error Ir::init(const ConfigSet& initializer)
 	texinit.m_height = m_fbSize;
 	texinit.m_depth = m_cubemapArrSize;
 	texinit.m_type = TextureType::CUBE_ARRAY;
-	texinit.m_format = Is::RT_PIXEL_FORMAT;
+	texinit.m_format = Pps::RT_PIXEL_FORMAT;
 	texinit.m_mipmapsCount = MAX_U8;
 	texinit.m_samples = 1;
 	texinit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
@@ -116,90 +111,31 @@ Error Ir::run(CommandBufferPtr cmdb)
 	FrustumComponent& frc = m_r->getActiveFrustumComponent();
 	VisibilityTestResults& visRez = frc.getVisibilityTestResults();
 
-	const VisibleNode* it;
-	const VisibleNode* end;
-
-	//
-	// Do the proxies
-	//
 
-	// Count them
-	U quadCount = 0;
-	it = visRez.getReflectionProxiesBegin();
-	end = visRez.getReflectionProxiesEnd();
-	while(it != end)
+	if(visRez.getReflectionProbeCount() > m_cubemapArrSize)
 	{
-		const ReflectionProxyComponent& proxyc =
-			it->m_node->getComponent<ReflectionProxyComponent>();
-
-		quadCount += proxyc.getFaces().getSize();
-		++it;
+		ANKI_LOGW("Increase the ir.cubemapTextureArraySize");
 	}
 
-	// Allocate
-	void* data = getGrManager().allocateFrameHostVisibleMemory(
-		sizeof(ShaderReflectionProxy) * quadCount
-		+ sizeof(UVec4), BufferUsage::STORAGE, m_proxiesToken);
-
-	UVec4* counts = reinterpret_cast<UVec4*>(data);
-	counts->x() = quadCount;
-	counts->y() = visRez.getReflectionProbeCount();
-
-	it = visRez.getReflectionProxiesBegin();
-	end = visRez.getReflectionProxiesEnd();
-	ShaderReflectionProxy* proxies = reinterpret_cast<ShaderReflectionProxy*>(
-		counts + 1);
-
-	while(it != end)
-	{
-		const ReflectionProxyComponent& proxyc =
-			it->m_node->getComponent<ReflectionProxyComponent>();
-		for(const auto& face : proxyc.getFaces())
-		{
-			Plane plane = face.m_plane;
-			plane.transform(Transform(frc.getViewMatrix()));
-
-			proxies->m_plane =
-				Vec4(plane.getNormal().xyz(), plane.getOffset());
-			proxies->m_negPlane =
-				Vec4(-plane.getNormal().xyz(), plane.getOffset());
-
-			for(U i = 0; i < 4; ++i)
-			{
-				proxies->m_quadPoints[i] =
-					frc.getViewMatrix() * face.m_vertices[i].xyz1();
-			}
-
-			for(U i = 0; i < 4; ++i)
-			{
-				U next = (i < 3) ? (i + 1) : 0;
-				proxies->m_edgeCrossProd[i] = plane.getNormal().cross(
-					proxies->m_quadPoints[next] - proxies->m_quadPoints[i]);
-			}
-
-			++proxies;
-		}
-
-		++it;
-	}
-
-	//
 	// Do the probes
-	//
-	it = visRez.getReflectionProbesBegin();
-	end = visRez.getReflectionProbesEnd();
+	const VisibleNode* it = visRez.getReflectionProbesBegin();
+	const VisibleNode* end = visRez.getReflectionProbesEnd();
 
-	data = getGrManager().allocateFrameHostVisibleMemory(
+	void* data = getGrManager().allocateFrameHostVisibleMemory(
 		sizeof(ShaderReflectionProbe) * visRez.getReflectionProbeCount()
-		+ sizeof(Mat3x4),
+		+ sizeof(Mat3x4) + sizeof(UVec4),
 		BufferUsage::STORAGE, m_probesToken);
 
-	Mat3x4* invViewRotation = static_cast<Mat3x4*>(data);
+	UVec4* counts = static_cast<UVec4*>(data);
+	counts->x() = visRez.getReflectionProbeCount();
+
+	Mat3x4* invViewRotation = reinterpret_cast<Mat3x4*>(counts + 1);
 	*invViewRotation =
 		Mat3x4(frc.getViewMatrix().getInverse().getRotationPart());
 
 	ShaderReflectionProbe* probes = reinterpret_cast<ShaderReflectionProbe*>(
 		invViewRotation + 1);
+	ShaderReflectionProbe* probesBegin = probes;
 
 	while(it != end)
 	{
@@ -208,6 +144,13 @@ Error Ir::run(CommandBufferPtr cmdb)
 		++probes;
 	}
 
+	// Sort the probes to satisfy hierarchy
+	std::sort(probesBegin, probes, [](const ShaderReflectionProbe& a,
+		const ShaderReflectionProbe& b) -> Bool
+	{
+		return a.m_radiusSq < b.m_radiusSq;
+	});
+
 	return ErrorCode::NONE;
 }
 
@@ -244,7 +187,7 @@ Error Ir::renderReflection(SceneNode& node, ShaderReflectionProbe& shaderProb)
 
 			// Copy textures
 			cmdb[cmdb.getSize() - 1]->copyTextureToTexture(
-				m_nestedR.getIs().getRt(), 0, 0, m_cubemapArr, 6 * entry + i,
+				m_nestedR.getPps().getRt(), 0, 0, m_cubemapArr, 6 * entry + i,
 				0);
 
 			// Gen mips

+ 1 - 3
src/renderer/Is.cpp

@@ -319,7 +319,6 @@ Error Is::initInternal(const ConfigSet& config)
 		if(m_r->irEnabled())
 		{
 			init.m_storageBuffers[5].m_dynamic = true;
-			init.m_storageBuffers[6].m_dynamic = true;
 		}
 
 		m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
@@ -764,8 +763,7 @@ void Is::setState(CommandBufferPtr& cmdb)
 	dyn.m_storageBuffers[4] = m_lightIdsToken;
 	if(m_r->irEnabled())
 	{
-		dyn.m_storageBuffers[5] = m_r->getIr().getProxiesToken();
-		dyn.m_storageBuffers[6] = m_r->getIr().getProbesToken();
+		dyn.m_storageBuffers[5] = m_r->getIr().getProbesToken();
 	}
 
 	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);

+ 2 - 3
testapp/Main.cpp

@@ -42,7 +42,7 @@ App* app;
 ModelNode* horse;
 PerspectiveCamera* cam;
 
-#define PLAYER 0
+#define PLAYER 1
 #define MOUSE 1
 
 Bool profile = false;
@@ -478,8 +478,6 @@ Error initSubsystems(int argc, char* argv[])
 
 	// Config
 	Config config;
-	config.set("ms.ez.enabled", false);
-	config.set("ms.ez.maxObjectsToDraw", 100);
 	config.set("dbg.enabled", false);
 	config.set("is.sm.bilinearEnabled", true);
 	config.set("is.groundLightEnabled", false);
@@ -514,6 +512,7 @@ Error initSubsystems(int argc, char* argv[])
 	config.set("samples", 1);
 	config.set("tessellation", true);
 	//config.set("maxTextureSize", 256);
+	config.set("ir.enabled", true);
 	config.set("ir.rendererSize", 64);
 	config.set("fullscreenDesktopResolution", true);
 	config.set("debugContext", false);