Browse Source

Try to sample shadowmaps in RT reflections when possible

Panagiotis Christopoulos Charitos 1 year ago
parent
commit
f111dcafcd

+ 4 - 0
AnKi/Renderer/RtReflections.cpp

@@ -12,6 +12,7 @@
 #include <AnKi/Renderer/Bloom.h>
 #include <AnKi/Renderer/Bloom.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/Ssr.h>
 #include <AnKi/Renderer/Ssr.h>
+#include <AnKi/Renderer/ShadowMapping.h>
 #include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
 #include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
 #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
 #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Util/Tracer.h>
@@ -251,6 +252,7 @@ void RtReflections::populateRenderGraph(RenderingContext& ctx)
 		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvTraceRays);
 		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvTraceRays);
 		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
 		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
 		rpass.newTextureDependency(getRenderer().getSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
 		rpass.newTextureDependency(getRenderer().getSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
 		rpass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
 		rpass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
 												 AccelerationStructureUsageBit::kTraceRaysSrv);
 												 AccelerationStructureUsageBit::kTraceRaysSrv);
 		rpass.newBufferDependency(raygenIndirectArgsHandle, BufferUsageBit::kIndirectTraceRays);
 		rpass.newBufferDependency(raygenIndirectArgsHandle, BufferUsageBit::kIndirectTraceRays);
@@ -284,11 +286,13 @@ void RtReflections::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindSrv(4, 2, getRenderer().getSky().getEnvironmentMapRt());
 			rgraphCtx.bindSrv(4, 2, getRenderer().getSky().getEnvironmentMapRt());
 			cmdb.bindSrv(5, 2, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView());
 			cmdb.bindSrv(5, 2, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView());
 			cmdb.bindSrv(6, 2, pixelsFailedSsrBuff);
 			cmdb.bindSrv(6, 2, pixelsFailedSsrBuff);
+			rgraphCtx.bindSrv(7, 2, getRenderer().getShadowMapping().getShadowmapRt());
 
 
 			rgraphCtx.bindUav(0, 2, transientRt1);
 			rgraphCtx.bindUav(0, 2, transientRt1);
 			rgraphCtx.bindUav(1, 2, hitPosAndDepthRt);
 			rgraphCtx.bindUav(1, 2, hitPosAndDepthRt);
 
 
 			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
 			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
 
 
 			const Vec4 consts(g_rtReflectionsMaxRayDistanceCVar);
 			const Vec4 consts(g_rtReflectionsMaxRayDistanceCVar);
 			cmdb.setFastConstants(&consts, sizeof(consts));
 			cmdb.setFastConstants(&consts, sizeof(consts));

+ 2 - 1
AnKi/Renderer/ShadowMapping.cpp

@@ -66,7 +66,8 @@ Error ShadowMapping::init()
 		m_tileResolution = g_shadowMappingTileResolutionCVar;
 		m_tileResolution = g_shadowMappingTileResolutionCVar;
 		m_tileCountBothAxis = g_shadowMappingTileCountPerRowOrColumnCVar;
 		m_tileCountBothAxis = g_shadowMappingTileCountPerRowOrColumnCVar;
 
 
-		const TextureUsageBit usage = TextureUsageBit::kSrvPixel | TextureUsageBit::kSrvCompute | TextureUsageBit::kAllRtvDsv;
+		const TextureUsageBit usage =
+			TextureUsageBit::kSrvPixel | TextureUsageBit::kSrvCompute | TextureUsageBit::kSrvTraceRays | TextureUsageBit::kAllRtvDsv;
 		TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
 		TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
 			m_tileResolution * m_tileCountBothAxis, m_tileResolution * m_tileCountBothAxis, Format::kD32_Sfloat, usage, "ShadowAtlas");
 			m_tileResolution * m_tileCountBothAxis, m_tileResolution * m_tileCountBothAxis, Format::kD32_Sfloat, usage, "ShadowAtlas");
 		ClearValue clearVal;
 		ClearValue clearVal;

+ 2 - 0
AnKi/Shaders/RtMaterialFetch.hlsl

@@ -31,9 +31,11 @@ Texture2D<Vec4> g_gbufferRt2 : register(t3, SPACE);
 Texture2D<Vec4> g_envMap : register(t4, SPACE);
 Texture2D<Vec4> g_envMap : register(t4, SPACE);
 StructuredBuffer<GpuSceneGlobalIlluminationProbe> g_giProbes : register(t5, SPACE);
 StructuredBuffer<GpuSceneGlobalIlluminationProbe> g_giProbes : register(t5, SPACE);
 StructuredBuffer<U32> g_pixelsFailedSsr : register(t6, SPACE);
 StructuredBuffer<U32> g_pixelsFailedSsr : register(t6, SPACE);
+Texture2D<Vec4> g_shadowAtlasTex : register(t7, SPACE);
 
 
 RWTexture2D<Vec4> g_colorAndPdfTex : register(u0, SPACE);
 RWTexture2D<Vec4> g_colorAndPdfTex : register(u0, SPACE);
 RWTexture2D<Vec4> g_hitPosAndDepthTex : register(u1, SPACE);
 RWTexture2D<Vec4> g_hitPosAndDepthTex : register(u1, SPACE);
 
 
 SamplerState g_linearClampAnySampler : register(s0, SPACE);
 SamplerState g_linearClampAnySampler : register(s0, SPACE);
+SamplerComparisonState g_shadowSampler : register(s1, SPACE);
 #endif
 #endif

+ 34 - 15
AnKi/Shaders/RtReflections.ankiprog

@@ -23,6 +23,8 @@ constexpr F32 kSpatialUpscalingPcfTexelOffset = 8.0;
 #define SPATIAL_UPSCALING_POISON_KERNEL kPoissonDisk8
 #define SPATIAL_UPSCALING_POISON_KERNEL kPoissonDisk8
 constexpr F32 kMaxBilateralSamples = 5.0;
 constexpr F32 kMaxBilateralSamples = 5.0;
 constexpr F32 kGaussianSigma = 0.55;
 constexpr F32 kGaussianSigma = 0.55;
+#define STOCHASTIC_REFLECTIONS 1
+#define TRY_SHADOWMAP_FIRST 1
 
 
 // Functions
 // Functions
 Vec3 getDiffuseIndirect(StructuredBuffer<GpuSceneGlobalIlluminationProbe> giProbes, Vec3 worldPos, Vec3 worldNormal,
 Vec3 getDiffuseIndirect(StructuredBuffer<GpuSceneGlobalIlluminationProbe> giProbes, Vec3 worldPos, Vec3 worldNormal,
@@ -107,7 +109,7 @@ ANKI_FAST_CONSTANTS(SsrConstants2, g_consts)
 
 
 	// Compute refl
 	// Compute refl
 	const Vec3 viewDir = -normalize(viewPos);
 	const Vec3 viewDir = -normalize(viewPos);
-#	if 1
+#	if STOCHASTIC_REFLECTIONS
 	F32 pdf;
 	F32 pdf;
 	const Vec3 reflDir = sampleReflectionVectorIsotropic(viewDir, viewNormal, roughness, randFactors, 4, pdf);
 	const Vec3 reflDir = sampleReflectionVectorIsotropic(viewDir, viewNormal, roughness, randFactors, 4, pdf);
 #	else
 #	else
@@ -246,7 +248,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 
 
 	// Compute refl
 	// Compute refl
 	const Vec3 viewDir = normalize(g_globalRendererConstants.m_cameraPosition - worldPos);
 	const Vec3 viewDir = normalize(g_globalRendererConstants.m_cameraPosition - worldPos);
-#	if 1
+#	if STOCHASTIC_REFLECTIONS
 	F32 pdf;
 	F32 pdf;
 	const Vec3 reflDir = sampleReflectionVectorIsotropic(viewDir, worldNormal, roughness, randFactors, 4, pdf);
 	const Vec3 reflDir = sampleReflectionVectorIsotropic(viewDir, worldNormal, roughness, randFactors, 4, pdf);
 #	else
 #	else
@@ -279,11 +281,39 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 	ray.Direction = reflDir;
 	ray.Direction = reflDir;
 	ray.TMax = g_consts.m_maxRayT;
 	ray.TMax = g_consts.m_maxRayT;
 	TraceRay(g_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
 	TraceRay(g_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
+
 	const Bool hasHitSky = payload.m_rayT < 0.0;
 	const Bool hasHitSky = payload.m_rayT < 0.0;
+	if(hasHitSky)
+	{
+		payload.m_rayT = g_consts.m_maxRayT;
+	}
+
+	const Vec3 hitPos = worldPos + reflDir * payload.m_rayT;
 
 
 	// Trace shadow
 	// Trace shadow
-	F32 shadow;
-	if(!hasHitSky)
+	Vec4 vv4 = mul(g_globalRendererConstants.m_matrices.m_viewProjection, Vec4(hitPos, 1.0));
+	vv4.xy /= vv4.w;
+	const Bool bInsideFrustum = all(vv4.xy > -1.0) && all(vv4.xy < 1.0) && vv4.w > 0.0;
+
+	F32 shadow = 0.0;
+	if(hasHitSky)
+	{
+		// Skybox
+		shadow = 1.0;
+
+		const Vec2 uv = octahedronEncode(worldNormal);
+		payload.m_emission = g_envMap.SampleLevel(g_linearClampAnySampler, uv, 0.0).xyz;
+	}
+	else if(bInsideFrustum && TRY_SHADOWMAP_FIRST)
+	{
+		const F32 negativeZViewSpace = -mul(g_globalRendererConstants.m_matrices.m_view, Vec4(hitPos, 1.0)).z;
+		const U32 shadowCascadeCount = dirLight.m_shadowCascadeCount_31bit_active_1bit >> 1u;
+
+		const U32 cascadeIdx = computeShadowCascadeIndex(negativeZViewSpace, dirLight.m_shadowCascadeDistances, shadowCascadeCount);
+
+		shadow = computeShadowFactorDirLight(dirLight, cascadeIdx, hitPos, g_shadowAtlasTex, g_shadowSampler);
+	}
+	else
 	{
 	{
 		constexpr U32 qFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH;
 		constexpr U32 qFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH;
 		RayQuery<qFlags> q;
 		RayQuery<qFlags> q;
@@ -296,20 +326,9 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 		q.Proceed();
 		q.Proceed();
 		shadow = (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) ? 0.0 : 1.0;
 		shadow = (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) ? 0.0 : 1.0;
 	}
 	}
-	else
-	{
-		// Skybox
-		shadow = 1.0;
-		payload.m_rayT = g_consts.m_maxRayT;
-
-		const Vec2 uv = octahedronEncode(worldNormal);
-		payload.m_emission = g_envMap.SampleLevel(g_linearClampAnySampler, uv, 0.0).xyz;
-	}
 
 
 	// Do simple light shading
 	// Do simple light shading
 	Vec3 outColor = payload.m_emission;
 	Vec3 outColor = payload.m_emission;
-
-	const Vec3 hitPos = worldPos + reflDir * payload.m_rayT;
 	Vec3 indirectDiffuse = 0.0;
 	Vec3 indirectDiffuse = 0.0;
 	if(!hasHitSky)
 	if(!hasHitSky)
 	{
 	{