Browse Source

Fix denoising of GI

Panagiotis Christopoulos Charitos 5 months ago
parent
commit
246127099c

+ 0 - 1
AnKi/Renderer/HistoryLength.cpp

@@ -88,7 +88,6 @@ void HistoryLength::populateRenderGraph(RenderingContext& ctx)
 		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 
 		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-		cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 		if(g_preferComputeCVar)
 		{

+ 3 - 1
AnKi/Renderer/IndirectDiffuseClipmaps.cpp

@@ -601,7 +601,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 		pass.newTextureDependency(getMotionVectors().getMotionVectorsRt(), TextureUsageBit::kSrvCompute);
 		pass.newTextureDependency(outRt, TextureUsageBit::kUavCompute);
 
-		pass.setWork([this, fullRtTmp, historyRt, outRt](RenderPassWorkContext& rgraphCtx) {
+		pass.setWork([this, &ctx, fullRtTmp, historyRt, outRt](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 			cmdb.bindShaderProgram(m_temporalDenoiseGrProg.get());
@@ -615,6 +615,8 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 
+			cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
+
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 		});
 	}

+ 1 - 1
AnKi/Resource/MeshResource.cpp

@@ -399,7 +399,7 @@ Error MeshResource::loadAsync(MeshBinaryLoader& loader) const
 					BufferBarrierInfo barr;
 					barr.m_bufferView = scratchBuff;
 					barr.m_previousUsage = BufferUsageBit::kAccelerationStructureBuildScratch;
-					barr.m_previousUsage = BufferUsageBit::kAccelerationStructureBuildScratch;
+					barr.m_nextUsage = BufferUsageBit::kAccelerationStructureBuildScratch;
 					cmdb->setPipelineBarrier({}, {&barr, 1}, {});
 				}
 

+ 14 - 46
AnKi/Shaders/HistoryLength.ankiprog

@@ -38,7 +38,9 @@ F32 computeLength(Vec2 coord)
 
 	const Vec2 uv = (coord + 0.5) / viewport;
 	const Vec2 ndc = uvToNdc(uv);
-	const Vec2 historyUv = uv + TEX(g_motionVectorsTex, coord);
+	const Vec2 historyUv =
+		uv + TEX(g_motionVectorsTex, coord)
+		+ (g_globalRendererConsts.m_previousMatrices.m_jitterOffsetNdc - g_globalRendererConsts.m_matrices.m_jitterOffsetNdc) / Vec2(2.0, -2.0);
 
 	// Compute length
 	F32 good = 0.0; // Zero means "new" pixel this frame
@@ -48,56 +50,22 @@ F32 computeLength(Vec2 coord)
 	}
 	else
 	{
-		// Read neighbours to find min and max depth
-		// +-+-+-+
-		// |6|7|8|
-		// +-+-+-+
-		// |3|4|5|
-		// +-+-+-+
-		// |0|1|2|
-		// +-+-+-+
-		// "uv" points to the middle of 4
-		const Vec2 halfTexelSize = (1.0 / viewport) / 2.0;
-		Vec4 depth4 = g_depthTex.GatherRed(g_linearAnyClampSampler, uv + halfTexelSize); // Read 4, 5, 1, 2
-		F32 minDepth = min4(depth4);
-		F32 maxDepth = max4(depth4);
-		depth4 = g_depthTex.GatherRed(g_linearAnyClampSampler, uv - halfTexelSize); // Read 6, 7, 3, 4
-		minDepth = min(minDepth, min4(depth4));
-		maxDepth = max(maxDepth, max4(depth4));
-		F32 d = g_depthTex[clamp(coord + Vec2(1.0, -1.0), 0.0, viewport - 1.0)]; // Read 8
-		minDepth = min(minDepth, d);
-		maxDepth = max(maxDepth, d);
-		d = g_depthTex[clamp(coord + Vec2(-1.0, 1.0), 0.0, viewport - 1.0)]; // Read 0
-		minDepth = min(minDepth, d);
-		maxDepth = max(maxDepth, d);
-
-		// Compute the AABB from the min and max depth
-		const Vec3 boundA = unproject(ndc, minDepth);
-		const Vec3 boundB = unproject(ndc, maxDepth);
-		const Vec3 aabbMinVspace = min(boundA, boundB);
-		const Vec3 aabbMaxVspace = max(boundA, boundB);
+		const F32 crntDepth = g_depthTex[coord];
+		if(crntDepth == 1.0)
+		{
+			return 0.0;
+		}
+
+		const F32 crntViewZ = cheapPerspectiveUnprojection(g_globalRendererConsts.m_matrices.m_unprojectionParameters, ndc, crntDepth).z;
 
 		// Read history
-		const Vec2 historyNdc = uvToNdc(historyUv);
 		const F32 historyDepth = g_historyDepthTex.SampleLevel(g_linearAnyClampSampler, historyUv, 0.0f);
-		Vec4 v = mul(g_globalRendererConsts.m_previousMatrices.m_invertedViewProjection, Vec4(historyNdc, historyDepth, 1.0));
-		const Vec3 historyWspace = v.xyz / v.w;
-		const Vec3 historyVspace = mul(g_globalRendererConsts.m_matrices.m_view, Vec4(historyWspace, 1.0));
 
-		F32 maxDist = 0.0;
-		[unroll] for(U32 i = 0; i < 3; ++i)
-		{
-			if(historyVspace[i] < aabbMinVspace[i])
-			{
-				maxDist = max(maxDist, aabbMinVspace[i] - historyVspace[i]);
-			}
-			else if(historyVspace[i] > aabbMaxVspace[i])
-			{
-				maxDist = max(maxDist, historyVspace[i] - aabbMaxVspace[i]);
-			}
-		}
+		const Vec4 v = mul(g_globalRendererConsts.m_previousMatrices.m_invertedViewProjection, Vec4(uvToNdc(historyUv), historyDepth, 1.0));
+		const F32 historyViewZ = mul(g_globalRendererConsts.m_matrices.m_view, Vec4(v.xyz / v.w, 1.0)).z;
 
-		const F32 factor = maxDist / kZDistanceLimit;
+		const F32 dist = abs(crntViewZ - historyViewZ);
+		const F32 factor = dist / kZDistanceLimit;
 		good = 1.0 - min(factor, 1.0);
 	}
 

+ 5 - 1
AnKi/Shaders/IndirectDiffuseClipmaps.ankiprog

@@ -768,6 +768,8 @@ RWTexture2D<Vec4> g_outTex : register(u0);
 
 SamplerState g_linearAnyClampSampler : register(s0);
 
+ConstantBuffer<GlobalRendererConstants> g_globalRendererConsts : register(b0);
+
 [numthreads(64, 1, 1)] void main(COMPUTE_ARGS)
 {
 	const Vec2 coord = getOptimalDispatchThreadId8x8Amd(svGroupIndex, svGroupId.xy);
@@ -791,7 +793,9 @@ SamplerState g_linearAnyClampSampler : register(s0);
 		g_historyLengthTex.GetDimensions(viewport.x, viewport.y);
 
 		const Vec2 uv = (coord + 0.5) / viewport;
-		const Vec2 historyUv = uv + TEX(g_motionVectorsTex, coord);
+		const Vec2 historyUv =
+			uv + TEX(g_motionVectorsTex, coord)
+			+ (g_globalRendererConsts.m_previousMatrices.m_jitterOffsetNdc - g_globalRendererConsts.m_matrices.m_jitterOffsetNdc) / Vec2(2.0, -2.0);
 
 		const Vec3 history = g_historyTex.SampleLevel(g_linearAnyClampSampler, historyUv, 0.0);
 

+ 3 - 1
AnKi/Shaders/Reflections.ankiprog

@@ -965,7 +965,9 @@ Vec2 computeHistoryUv(UVec2 coords, Vec2 uv)
 	const Vec2 hitHistoryUv = uv + diff;
 
 	// Read the motion vectors as well
-	const Vec2 motionHistoryUv = uv + g_motionVectorsTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0f).xy;
+	const Vec2 motionHistoryUv =
+		uv + g_motionVectorsTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0f).xy
+		+ (g_globalRendererConstants.m_previousMatrices.m_jitterOffsetNdc - g_globalRendererConstants.m_matrices.m_jitterOffsetNdc) / Vec2(2.0, -2.0);
 
 	// Blend the 2 histories. The more the projected hit point is in the view the more we use it
 	F32 factor = max(abs(clipPos.x), abs(clipPos.y));