浏览代码

More work

Panagiotis Christopoulos Charitos 5 年之前
父节点
当前提交
d5122df57b

+ 20 - 0
samples/common/Framework.cpp

@@ -61,6 +61,26 @@ Error SampleApp::userMainLoop(Bool& quit)
 		setDisplayDeveloperConsole(!getDisplayDeveloperConsole());
 		setDisplayDeveloperConsole(!getDisplayDeveloperConsole());
 	}
 	}
 
 
+	static Bool pressed = false;
+	Bool somethingPressed = false;
+	if(in.getKey(KeyCode::U) == 1)
+	{
+		pressed = !pressed;
+		somethingPressed = true;
+	}
+
+	if(somethingPressed)
+	{
+		if(pressed)
+		{
+			renderer.setCurrentDebugRenderTarget("SSGI");
+		}
+		else
+		{
+			renderer.setCurrentDebugRenderTarget("");
+		}
+	}
+
 	if(!getDisplayDeveloperConsole())
 	if(!getDisplayDeveloperConsole())
 	{
 	{
 		in.hideCursor(true);
 		in.hideCursor(true);

+ 3 - 3
shaders/Functions.glsl

@@ -519,10 +519,10 @@ Bool aabbsOverlap(const Vec3 aMin, const Vec3 aMax, const Vec3 bMin, const Vec3
 	}
 	}
 
 
 // Create a matrix from some direction.
 // Create a matrix from some direction.
-Mat3 rotationFromDirection(Vec3 normal)
+Mat3 rotationFromDirection(Vec3 zAxis)
 {
 {
 #if 0
 #if 0
-	const Vec3 z = normal;
+	const Vec3 z = zAxis;
 	const Bool alignsWithXBasis = abs(z.x - 1.0) <= EPSILON; // aka z == Vec3(1.0, 0.0, 0.0)
 	const Bool alignsWithXBasis = abs(z.x - 1.0) <= EPSILON; // aka z == Vec3(1.0, 0.0, 0.0)
 	Vec3 x = (alignsWithXBasis) ? Vec3(0.0, 0.0, 1.0) : Vec3(1.0, 0.0, 0.0);
 	Vec3 x = (alignsWithXBasis) ? Vec3(0.0, 0.0, 1.0) : Vec3(1.0, 0.0, 0.0);
 	const Vec3 y = normalize(cross(x, z));
 	const Vec3 y = normalize(cross(x, z));
@@ -530,7 +530,7 @@ Mat3 rotationFromDirection(Vec3 normal)
 	return Mat3(x, y, z);
 	return Mat3(x, y, z);
 #else
 #else
 	// http://jcgt.org/published/0006/01/01/
 	// http://jcgt.org/published/0006/01/01/
-	const Vec3 z = normal;
+	const Vec3 z = zAxis;
 	const F32 sign = (z.z >= 0) ? 1.0 : -1.0;
 	const F32 sign = (z.z >= 0) ? 1.0 : -1.0;
 	const F32 a = -1.0 / (sign + z.z);
 	const F32 a = -1.0 / (sign + z.z);
 	const F32 b = z.x * z.y * a;
 	const F32 b = z.x * z.y * a;

+ 57 - 0
shaders/ImportanceSampling.glsl

@@ -0,0 +1,57 @@
+// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <shaders/Common.glsl>
+
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+// Using bitfieldReverse instead of bitwise ops
+F32 radicalInverseVdC(U32 bits)
+{
+	bits = bitfieldReverse(bits);
+	return F32(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+Vec2 hammersley2d(U32 i, U32 N)
+{
+	return Vec2(F32(i) / F32(N), radicalInverseVdC(i));
+}
+
+// Stolen from Unreal
+// Returns three elements with 16 random bits each (0-0xffff)
+UVec3 rand3DPCG16(UVec3 v)
+{
+	v = v * 1664525u + 1013904223u;
+
+	v.x += v.y * v.z;
+	v.y += v.z * v.x;
+	v.z += v.x * v.y;
+	v.x += v.y * v.z;
+	v.y += v.z * v.x;
+	v.z += v.x * v.y;
+
+	return v >> 16u;
+}
+
+// Stolen from Unreal
+// It will return a uniform 2D point inside a circle. For random use rand3DPCG16()
+Vec2 hammersleyRandom16(U32 sampleIdx, U32 sampleCount, UVec2 random)
+{
+	const F32 e1 = fract(F32(sampleIdx) / sampleCount + F32(random.x) * (1.0 / 65536.0));
+	const F32 e2 = F32((bitfieldReverse(sampleIdx) >> 16) ^ random.y) * (1.0 / 65536.0);
+	return Vec2(e1, e2);
+}
+
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+// From a uniform 2D point inside a circle get a 3D point in a hemisphere. It's oriented in the z axis
+Vec3 hemisphereSampleUniform(Vec2 uv)
+{
+	const F32 phi = uv.y * 2.0 * PI;
+	const F32 cosTheta = 1.0 - uv.x;
+	const F32 sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+	return Vec3(cos(phi) * sinTheta, cosTheta, sin(phi) * sinTheta);
+}

+ 54 - 5
shaders/Ssgi.ankiprog

@@ -15,6 +15,7 @@
 #include <shaders/SsRaymarching.glsl>
 #include <shaders/SsRaymarching.glsl>
 #include <shaders/Functions.glsl>
 #include <shaders/Functions.glsl>
 #include <shaders/Pack.glsl>
 #include <shaders/Pack.glsl>
+#include <shaders/ImportanceSampling.glsl>
 #include <shaders/glsl_cpp_common/Ssgi.h>
 #include <shaders/glsl_cpp_common/Ssgi.h>
 
 
 const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
 const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
@@ -32,9 +33,6 @@ layout(set = 0, binding = 3) uniform texture2D u_gbufferRt2;
 layout(set = 0, binding = 4) uniform texture2D u_depthRt;
 layout(set = 0, binding = 4) uniform texture2D u_depthRt;
 layout(set = 0, binding = 5) uniform texture2D u_lightBufferRt;
 layout(set = 0, binding = 5) uniform texture2D u_lightBufferRt;
 
 
-layout(set = 0, binding = 6) uniform sampler u_trilinearRepeatSampler;
-layout(set = 0, binding = 7) uniform texture2D u_noiseTex;
-
 void main()
 void main()
 {
 {
 	// Compute a global invocation ID that takes the checkerboard pattern into account
 	// Compute a global invocation ID that takes the checkerboard pattern into account
@@ -54,16 +52,67 @@ void main()
 
 
 	const Vec2 uv = (Vec2(fixedInvocationId.xy) + 0.5) / Vec2(u_unis.m_framebufferSize);
 	const Vec2 uv = (Vec2(fixedInvocationId.xy) + 0.5) / Vec2(u_unis.m_framebufferSize);
 
 
+	// Get normal
 	const Vec3 worldNormal = readNormalFromGBuffer(u_gbufferRt2, u_trilinearClampSampler, uv);
 	const Vec3 worldNormal = readNormalFromGBuffer(u_gbufferRt2, u_trilinearClampSampler, uv);
 
 
 	// Get depth
 	// Get depth
 	const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, uv, 0.0).r;
 	const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, uv, 0.0).r;
 
 
-	// Get view pos
+	// Compute view pos
 	const Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
 	const Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
 	const Vec3 viewPos = viewPos4.xyz / viewPos4.w;
 	const Vec3 viewPos = viewPos4.xyz / viewPos4.w;
 
 
-	imageStore(out_img, fixedInvocationId, Vec4(worldNormal, depth));
+	// Get a random point inside the hemisphere
+	const UVec2 random = rand3DPCG16(UVec3(fixedInvocationId, u_unis.m_frameCount)).xy;
+	const Vec2 randomCircle = hammersleyRandom16(0, 0xFFFFu, random);
+	const Vec3 randomHemisphere = rotationFromDirection(worldNormal) * hemisphereSampleUniform(randomCircle);
+
+	// Trace
+	Vec3 hitPoint;
+	F32 hitAttenuation;
+	const U32 lod = 0;
+	const U32 step = 16u;
+	const F32 stepf = step;
+	const F32 minStepf = 4.0;
+	const F32 noise = F32(random.x) * (1.0 / 65536.0);
+	raymarchGroundTruth(viewPos,
+		randomHemisphere,
+		uv,
+		depth,
+		u_unis.m_projMat,
+		u_unis.m_maxSteps,
+		u_depthRt,
+		u_trilinearClampSampler,
+		F32(lod),
+		u_unis.m_depthBufferSize,
+		step,
+		U32((stepf - minStepf) * noise + minStepf),
+		hitPoint,
+		hitAttenuation);
+
+	// Read the light buffer
+	Vec4 outColor;
+	ANKI_BRANCH if(hitAttenuation > 0.0)
+	{
+		// Reproject the UV because you are reading the previous frame
+		const Vec4 v4 = u_unis.m_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(hitPoint.xy), hitPoint.z, 1.0);
+		hitPoint.xy = NDC_TO_UV(v4.xy / v4.w);
+
+		// Read the light buffer
+		outColor.rgb = textureLod(u_lightBufferRt, u_trilinearClampSampler, hitPoint.xy, 0.0).rgb; // TODO lower lod
+		outColor.rgb = clamp(outColor.rgb, 0.0, FLT_MAX); // Fix the value just in case
+		outColor.rgb *= hitAttenuation;
+		outColor.a = 1.0 - hitAttenuation;
+	}
+	else
+	{
+		outColor = Vec4(0.0, 0.0, 0.0, 1.0);
+	}
+
+	const F32 NoL = dot(randomHemisphere, worldNormal);
+	outColor.xyz *= NoL;
+
+	imageStore(out_img, fixedInvocationId, outColor);
 }
 }
 
 
 #pragma anki end
 #pragma anki end

+ 5 - 0
shaders/glsl_cpp_common/Ssgi.h

@@ -14,7 +14,12 @@ struct SsgiUniforms
 {
 {
 	UVec2 m_depthBufferSize;
 	UVec2 m_depthBufferSize;
 	UVec2 m_framebufferSize;
 	UVec2 m_framebufferSize;
+	UVec2 m_padding0;
+	U32 m_frameCount;
+	U32 m_maxSteps;
 	Mat4 m_invProjMat;
 	Mat4 m_invProjMat;
+	Mat4 m_projMat;
+	Mat4 m_prevViewProjMatMulInvViewProjMat;
 };
 };
 
 
 ANKI_END_NAMESPACE
 ANKI_END_NAMESPACE

+ 5 - 3
src/anki/renderer/Ssgi.cpp

@@ -97,6 +97,11 @@ void Ssgi::run(RenderPassWorkContext& rgraphCtx)
 	unis->m_depthBufferSize = UVec2(m_r->getWidth(), m_r->getHeight()) >> (m_main.m_depthLod + 1);
 	unis->m_depthBufferSize = UVec2(m_r->getWidth(), m_r->getHeight()) >> (m_main.m_depthLod + 1);
 	unis->m_framebufferSize = UVec2(m_r->getWidth(), m_r->getHeight());
 	unis->m_framebufferSize = UVec2(m_r->getWidth(), m_r->getHeight());
 	unis->m_invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 	unis->m_invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
+	unis->m_projMat = ctx.m_matrices.m_projectionJitter;
+	unis->m_prevViewProjMatMulInvViewProjMat =
+		ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_viewProjectionJitter.getInverse();
+	unis->m_frameCount = m_r->getFrameCount() & MAX_U32;
+	unis->m_maxSteps = m_main.m_maxSteps;
 
 
 	cmdb->bindSampler(0, 2, m_r->getSamplers().m_trilinearClamp);
 	cmdb->bindSampler(0, 2, m_r->getSamplers().m_trilinearClamp);
 
 
@@ -108,9 +113,6 @@ void Ssgi::run(RenderPassWorkContext& rgraphCtx)
 
 
 	rgraphCtx.bindColorTexture(0, 5, m_r->getDownscaleBlur().getRt());
 	rgraphCtx.bindColorTexture(0, 5, m_r->getDownscaleBlur().getRt());
 
 
-	cmdb->bindSampler(0, 6, m_r->getSamplers().m_trilinearRepeat);
-	cmdb->bindTexture(0, 7, m_main.m_noiseTex->getGrTextureView(), TextureUsageBit::SAMPLED_ALL);
-
 	// Dispatch
 	// Dispatch
 	dispatchPPCompute(cmdb, 16, 16, m_r->getWidth() / 2, m_r->getHeight());
 	dispatchPPCompute(cmdb, 16, 16, m_r->getWidth() / 2, m_r->getHeight());
 }
 }