Parcourir la source

Have the bluring of ESM depend on the LOD

Panagiotis Christopoulos Charitos il y a 7 ans
Parent
commit
5cd103cf7c

+ 36 - 27
shaders/ExponentialShadowmappingResolve.glslp

@@ -10,6 +10,23 @@ const F32 OFFSET = 1.25;
 const Vec2 TEXEL_SIZE = 1.0 / Vec2(INPUT_TEXTURE_SIZE);
 const Vec2 HALF_TEXEL_SIZE = TEXEL_SIZE / 2.0;
 
+struct Uniforms
+{
+	Vec2 m_uvScale;
+	Vec2 m_uvTranslation;
+	F32 m_near;
+	F32 m_far;
+	U32 m_blur;
+	U32 m_padding;
+};
+
+ANKI_PUSH_CONSTANTS(Uniforms, u_regs);
+#define u_uvScale u_regs.m_uvScale
+#define u_uvTranslation u_regs.m_uvTranslation
+#define u_near u_regs.m_near
+#define u_far u_regs.m_far
+#define u_blur (u_regs.m_blur == 1u)
+
 #pragma anki start vert
 #include <shaders/Common.glsl>
 
@@ -18,12 +35,6 @@ out gl_PerVertex
 	Vec4 gl_Position;
 };
 
-layout(ANKI_UBO_BINDING(0, 0)) uniform u_
-{
-	Vec4 u_nearFarPad2;
-	Vec4 u_uvScaleAndTranslation;
-};
-
 layout(location = 0) out Vec2 out_uv;
 layout(location = 1) flat out Vec2 out_maxUv;
 layout(location = 2) flat out Vec2 out_minUv;
@@ -33,12 +44,12 @@ void main()
 	out_uv = Vec2(gl_VertexID & 1, gl_VertexID >> 1) * 2.0;
 	Vec2 pos = out_uv * 2.0 - 1.0;
 
-	out_uv = fma(out_uv, u_uvScaleAndTranslation.zw, u_uvScaleAndTranslation.xy);
+	out_uv = fma(out_uv, u_uvScale, u_uvTranslation);
 	gl_Position = Vec4(pos, 0.0, 1.0);
 
 	// Compute the limits
-	out_maxUv = fma(Vec2(1.0), u_uvScaleAndTranslation.zw, u_uvScaleAndTranslation.xy) - HALF_TEXEL_SIZE;
-	out_minUv = fma(Vec2(0.0), u_uvScaleAndTranslation.zw, u_uvScaleAndTranslation.xy) + HALF_TEXEL_SIZE;
+	out_maxUv = fma(Vec2(1.0), u_uvScale, u_uvTranslation) - HALF_TEXEL_SIZE;
+	out_minUv = fma(Vec2(0.0), u_uvScale, u_uvTranslation) + HALF_TEXEL_SIZE;
 }
 #pragma anki end
 
@@ -52,15 +63,6 @@ layout(location = 2) flat in Vec2 in_minUv;
 
 layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_inputTex;
 
-layout(ANKI_UBO_BINDING(0, 0)) uniform u_
-{
-	Vec4 u_nearFarPad2;
-	Vec4 u_uvScaleAndTranslation;
-};
-
-#define u_near u_nearFarPad2.x
-#define u_far u_nearFarPad2.y
-
 layout(location = 0) out F32 out_color;
 
 F32 sampleLinearDepth(Vec2 uv)
@@ -73,14 +75,21 @@ void main()
 {
 	const Vec2 UV_OFFSET = OFFSET * TEXEL_SIZE;
 
-	out_color = sampleLinearDepth(in_uv) * BOX_WEIGHTS[0u];
-	out_color += sampleLinearDepth(in_uv + Vec2(UV_OFFSET.x, 0.0)) * BOX_WEIGHTS[1u];
-	out_color += sampleLinearDepth(in_uv + Vec2(-UV_OFFSET.x, 0.0)) * BOX_WEIGHTS[1u];
-	out_color += sampleLinearDepth(in_uv + Vec2(0.0, UV_OFFSET.y)) * BOX_WEIGHTS[1u];
-	out_color += sampleLinearDepth(in_uv + Vec2(0.0, -UV_OFFSET.y)) * BOX_WEIGHTS[1u];
-	out_color += sampleLinearDepth(in_uv + Vec2(UV_OFFSET.x, UV_OFFSET.y)) * BOX_WEIGHTS[2u];
-	out_color += sampleLinearDepth(in_uv + Vec2(-UV_OFFSET.x, UV_OFFSET.y)) * BOX_WEIGHTS[2u];
-	out_color += sampleLinearDepth(in_uv + Vec2(UV_OFFSET.x, -UV_OFFSET.y)) * BOX_WEIGHTS[2u];
-	out_color += sampleLinearDepth(in_uv + Vec2(-UV_OFFSET.x, -UV_OFFSET.y)) * BOX_WEIGHTS[2u];
+	if(u_blur)
+	{
+		out_color = sampleLinearDepth(in_uv) * BOX_WEIGHTS[0u];
+		out_color += sampleLinearDepth(in_uv + Vec2(UV_OFFSET.x, 0.0)) * BOX_WEIGHTS[1u];
+		out_color += sampleLinearDepth(in_uv + Vec2(-UV_OFFSET.x, 0.0)) * BOX_WEIGHTS[1u];
+		out_color += sampleLinearDepth(in_uv + Vec2(0.0, UV_OFFSET.y)) * BOX_WEIGHTS[1u];
+		out_color += sampleLinearDepth(in_uv + Vec2(0.0, -UV_OFFSET.y)) * BOX_WEIGHTS[1u];
+		out_color += sampleLinearDepth(in_uv + Vec2(UV_OFFSET.x, UV_OFFSET.y)) * BOX_WEIGHTS[2u];
+		out_color += sampleLinearDepth(in_uv + Vec2(-UV_OFFSET.x, UV_OFFSET.y)) * BOX_WEIGHTS[2u];
+		out_color += sampleLinearDepth(in_uv + Vec2(UV_OFFSET.x, -UV_OFFSET.y)) * BOX_WEIGHTS[2u];
+		out_color += sampleLinearDepth(in_uv + Vec2(-UV_OFFSET.x, -UV_OFFSET.y)) * BOX_WEIGHTS[2u];
+	}
+	else
+	{
+		out_color = sampleLinearDepth(in_uv);
+	}
 }
 #pragma anki end

+ 47 - 7
src/anki/renderer/ShadowMapping.cpp

@@ -32,6 +32,16 @@ public:
 	U32 m_drawcallCount;
 };
 
+class ShadowMapping::EsmResolveWorkItem
+{
+public:
+	Vec4 m_uvIn; ///< UV + size that point to the scratch buffer.
+	Array<U32, 4> m_viewportOut; ///< Viewport in the ESM RT.
+	F32 m_cameraNear;
+	F32 m_cameraFar;
+	Bool8 m_blur;
+};
+
 ShadowMapping::~ShadowMapping()
 {
 }
@@ -158,9 +168,22 @@ void ShadowMapping::runEsm(RenderPassWorkContext& rgraphCtx)
 		cmdb->setScissor(
 			workItem.m_viewportOut[0], workItem.m_viewportOut[1], workItem.m_viewportOut[2], workItem.m_viewportOut[3]);
 
-		Vec4* unis = allocateAndBindUniforms<Vec4*>(sizeof(Vec4) * 2, cmdb, 0, 0);
-		unis[0] = Vec4(workItem.m_cameraNear, workItem.m_cameraFar, 0.0f, 0.0f);
-		unis[1] = workItem.m_uvIn;
+		struct Uniforms
+		{
+			Vec2 m_uvScale;
+			Vec2 m_uvTranslation;
+			F32 m_near;
+			F32 m_far;
+			U32 m_blur;
+			U32 m_padding;
+		} unis;
+		unis.m_uvScale = workItem.m_uvIn.zw();
+		unis.m_uvTranslation = workItem.m_uvIn.xy();
+		unis.m_near = workItem.m_cameraNear;
+		unis.m_far = workItem.m_cameraFar;
+		unis.m_blur = workItem.m_blur;
+
+		cmdb->setPushConstants(&unis, sizeof(unis));
 
 		drawQuad(cmdb);
 	}
@@ -289,21 +312,23 @@ Mat4 ShadowMapping::createSpotLightTextureMatrix(const Viewport& viewport) const
 		1.0f);
 }
 
-U ShadowMapping::choseLod(const Vec4& cameraOrigin, const PointLightQueueElement& light) const
+U ShadowMapping::choseLod(const Vec4& cameraOrigin, const PointLightQueueElement& light, Bool& blurEsm) const
 {
 	const F32 distFromTheCamera = (cameraOrigin - light.m_worldPosition.xyz0()).getLength() - light.m_radius;
 	if(distFromTheCamera < m_lodDistances[0])
 	{
 		ANKI_ASSERT(m_pointLightsMaxLod == 1);
+		blurEsm = true;
 		return 1;
 	}
 	else
 	{
+		blurEsm = false;
 		return 0;
 	}
 }
 
-U ShadowMapping::choseLod(const Vec4& cameraOrigin, const SpotLightQueueElement& light) const
+U ShadowMapping::choseLod(const Vec4& cameraOrigin, const SpotLightQueueElement& light, Bool& blurEsm) const
 {
 	// Get some data
 	const Vec4 coneOrigin = light.m_worldTransform.getTranslationPart().xyz0();
@@ -319,14 +344,17 @@ U ShadowMapping::choseLod(const Vec4& cameraOrigin, const SpotLightQueueElement&
 	U lod;
 	if(distFromTheCamera < m_lodDistances[0])
 	{
+		blurEsm = true;
 		lod = 2;
 	}
 	else if(distFromTheCamera < m_lodDistances[1])
 	{
+		blurEsm = false;
 		lod = 1;
 	}
 	else
 	{
+		blurEsm = false;
 		lod = 0;
 	}
 
@@ -495,6 +523,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 				// Push work
 				newScratchAndEsmResloveRenderWorkItems(esmViewports[cascade],
 					scratchViewports[cascade],
+					true,
 					light.m_shadowRenderQueues[cascade],
 					lightsToRender,
 					esmWorkItems,
@@ -537,13 +566,16 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 				++numOfFacesThatHaveDrawcalls;
 			}
 		}
+
+		Bool blurEsm;
+		const U lod = choseLod(cameraOrigin, *light, blurEsm);
 		const Bool allocationFailed = numOfFacesThatHaveDrawcalls == 0
 									  || allocateTilesAndScratchTiles(light->m_uuid,
 											 numOfFacesThatHaveDrawcalls,
 											 &timestamps[0],
 											 &faceIndices[0],
 											 &drawcallCounts[0],
-											 choseLod(cameraOrigin, *light),
+											 lod,
 											 &esmViewports[0],
 											 &scratchViewports[0],
 											 &subResults[0])
@@ -577,6 +609,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 					{
 						newScratchAndEsmResloveRenderWorkItems(esmViewport,
 							scratchViewport,
+							blurEsm,
 							light->m_shadowRenderQueues[face],
 							lightsToRender,
 							esmWorkItems,
@@ -616,13 +649,16 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 		Viewport esmViewport;
 		Viewport scratchViewport;
 		const U32 localDrawcallCount = light->m_shadowRenderQueue->m_renderables.getSize();
+
+		Bool blurEsm;
+		const U lod = choseLod(cameraOrigin, *light, blurEsm);
 		const Bool allocationFailed = localDrawcallCount == 0
 									  || allocateTilesAndScratchTiles(light->m_uuid,
 											 1,
 											 &light->m_shadowRenderQueue->m_shadowRenderablesLastUpdateTimestamp,
 											 &faceIdx,
 											 &localDrawcallCount,
-											 choseLod(cameraOrigin, *light),
+											 lod,
 											 &esmViewport,
 											 &scratchViewport,
 											 &subResult)
@@ -639,6 +675,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 			{
 				newScratchAndEsmResloveRenderWorkItems(esmViewport,
 					scratchViewport,
+					blurEsm,
 					light->m_shadowRenderQueue,
 					lightsToRender,
 					esmWorkItems,
@@ -728,6 +765,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 
 void ShadowMapping::newScratchAndEsmResloveRenderWorkItems(const Viewport& esmViewport,
 	const Viewport& scratchVewport,
+	Bool blurEsm,
 	RenderQueue* lightRenderQueue,
 	DynamicArrayAuto<LightToRenderToScratchInfo>& scratchWorkItem,
 	DynamicArrayAuto<EsmResolveWorkItem>& esmResolveWorkItem,
@@ -757,6 +795,8 @@ void ShadowMapping::newScratchAndEsmResloveRenderWorkItems(const Viewport& esmVi
 		esmItem.m_cameraFar = lightRenderQueue->m_cameraFar;
 		esmItem.m_cameraNear = lightRenderQueue->m_cameraNear;
 
+		esmItem.m_blur = blurEsm;
+
 		esmResolveWorkItem.emplaceBack(esmItem);
 	}
 }

+ 4 - 10
src/anki/renderer/ShadowMapping.h

@@ -55,14 +55,7 @@ private:
 	ShaderProgramResourcePtr m_esmResolveProg;
 	ShaderProgramPtr m_esmResolveGrProg;
 
-	class EsmResolveWorkItem
-	{
-	public:
-		Vec4 m_uvIn; ///< UV + size that point to the scratch buffer.
-		Array<U32, 4> m_viewportOut; ///< Viewport in the ESM RT.
-		F32 m_cameraNear;
-		F32 m_cameraFar;
-	};
+	class EsmResolveWorkItem;
 	WeakArray<EsmResolveWorkItem> m_esmResolveWorkItems;
 
 	ANKI_USE_RESULT Error initEsm(const ConfigSet& cfg);
@@ -105,9 +98,9 @@ private:
 	Array<F32, m_lodCount - 1> m_lodDistances;
 
 	/// Find the lod of the light
-	U choseLod(const Vec4& cameraOrigin, const PointLightQueueElement& light) const;
+	U choseLod(const Vec4& cameraOrigin, const PointLightQueueElement& light, Bool& blurEsm) const;
 	/// Find the lod of the light
-	U choseLod(const Vec4& cameraOrigin, const SpotLightQueueElement& light) const;
+	U choseLod(const Vec4& cameraOrigin, const SpotLightQueueElement& light, Bool& blurEsm) const;
 
 	/// Try to allocate a number of scratch tiles and regular tiles.
 	TileAllocatorResult allocateTilesAndScratchTiles(U64 lightUuid,
@@ -123,6 +116,7 @@ private:
 	/// Add new work to render to scratch buffer and ESM buffer.
 	void newScratchAndEsmResloveRenderWorkItems(const Viewport& esmViewport,
 		const Viewport& scratchVewport,
+		Bool blurEsm,
 		RenderQueue* lightRenderQueue,
 		DynamicArrayAuto<LightToRenderToScratchInfo>& scratchWorkItem,
 		DynamicArrayAuto<EsmResolveWorkItem>& esmResolveWorkItem,