瀏覽代碼

More work on the GI clipmaps

Panagiotis Christopoulos Charitos 9 月之前
父節點
當前提交
d680e35ac8

+ 4 - 4
AnKi/Renderer/IndirectDiffuse.cpp

@@ -18,7 +18,7 @@ namespace anki {
 
 Error IndirectDiffuse::init()
 {
-	const Bool bRt = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar;
+	[[maybe_unused]] const Bool bRt = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar;
 	ANKI_ASSERT(bRt);
 
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/IndirectDiffuse.ankiprogbin", m_mainProg));
@@ -168,7 +168,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 				(!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
 			if(bSkySolidColor)
 			{
-				cmdb.bindSrv(4, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+				cmdb.bindSrv(4, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
 			}
 			else if(sky->getSkyboxType() == SkyboxType::kImage2D)
 			{
@@ -180,11 +180,11 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			}
 
 			cmdb.bindSrv(5, 2, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView());
-			cmdb.bindSrv(6, 2, BufferView(&getRenderer().getDummyBuffer()));
+			cmdb.bindSrv(6, 2, BufferView(getDummyGpuResources().m_buffer.get()));
 			rgraphCtx.bindSrv(7, 2, getRenderer().getShadowMapping().getShadowmapRt());
 
 			rgraphCtx.bindUav(0, 2, transientRt1);
-			cmdb.bindUav(1, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+			cmdb.bindUav(1, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::all()));
 
 			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
 			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());

+ 43 - 33
AnKi/Renderer/IndirectDiffuseClipmaps.cpp

@@ -23,19 +23,23 @@ Error IndirectDiffuseClipmaps::init()
 	m_tmpRtDesc.bake();
 
 	m_clipmapInfo[0].m_probeCounts = Vec3(F32(g_indirectDiffuseClipmap0ProbesPerDimCVar));
+	m_clipmapInfo[1].m_probeCounts = Vec3(F32(g_indirectDiffuseClipmap1ProbesPerDimCVar));
+	m_clipmapInfo[2].m_probeCounts = Vec3(F32(g_indirectDiffuseClipmap2ProbesPerDimCVar));
 	m_clipmapInfo[0].m_size = Vec3(g_indirectDiffuseClipmap0SizeCVar);
+	m_clipmapInfo[1].m_size = Vec3(g_indirectDiffuseClipmap1SizeCVar);
+	m_clipmapInfo[2].m_size = Vec3(g_indirectDiffuseClipmap2SizeCVar);
 
 	for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 	{
-		for(U32 i = 0; i < 3; ++i)
+		for(U32 dir = 0; dir < 6; ++dir)
 		{
 			TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
-				g_indirectDiffuseClipmap0ProbesPerDimCVar, g_indirectDiffuseClipmap0ProbesPerDimCVar, Format::kR16G16B16A16_Sfloat,
-				TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap #%u comp #%u", clipmap, i));
-			volumeInit.m_depth = g_indirectDiffuseClipmap0ProbesPerDimCVar;
+				U32(m_clipmapInfo[clipmap].m_probeCounts.x()), U32(m_clipmapInfo[clipmap].m_probeCounts.y()), Format::kB10G11R11_Ufloat_Pack32,
+				TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap #%u dir #%u", clipmap, dir));
+			volumeInit.m_depth = U32(m_clipmapInfo[clipmap].m_probeCounts.z());
 			volumeInit.m_type = TextureType::k3D;
 
-			m_clipmapVolumes[clipmap].m_perColorComponent[i] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
+			m_clipmapVolumes[clipmap].m_directions[dir] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
 		}
 	}
 
@@ -77,19 +81,18 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
 
-	Array2d<RenderTargetHandle, kIndirectDiffuseClipmapCount, 3> volumeRts;
+	Array2d<RenderTargetHandle, kIndirectDiffuseClipmapCount, 6> volumeRts;
 	for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 	{
-		for(U32 c = 0; c < 3; ++c)
+		for(U32 dir = 0; dir < 6; ++dir)
 		{
 			if(!m_clipmapsImportedOnce)
 			{
-				volumeRts[clipmap][c] =
-					rgraph.importRenderTarget(m_clipmapVolumes[clipmap].m_perColorComponent[c].get(), TextureUsageBit::kSrvCompute);
+				volumeRts[clipmap][dir] = rgraph.importRenderTarget(m_clipmapVolumes[clipmap].m_directions[dir].get(), TextureUsageBit::kSrvCompute);
 			}
 			else
 			{
-				volumeRts[clipmap][c] = rgraph.importRenderTarget(m_clipmapVolumes[clipmap].m_perColorComponent[c].get());
+				volumeRts[clipmap][dir] = rgraph.importRenderTarget(m_clipmapVolumes[clipmap].m_directions[dir].get());
 			}
 		}
 	}
@@ -157,9 +160,9 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 
 		for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 		{
-			for(U32 c = 0; c < 3; ++c)
+			for(U32 dir = 0; dir < 6; ++dir)
 			{
-				pass.newTextureDependency(volumeRts[clipmap][c], TextureUsageBit::kUavCompute);
+				pass.newTextureDependency(volumeRts[clipmap][dir], TextureUsageBit::kUavCompute);
 			}
 		}
 		pass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
@@ -193,9 +196,9 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindConstantBuffer(0, 2, ctx.m_globalRenderingConstantsBuffer);
 
 			rgraphCtx.bindSrv(0, 2, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
-			cmdb.bindSrv(1, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
-			cmdb.bindSrv(2, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
-			cmdb.bindSrv(3, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(1, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(2, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(3, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
 
 			const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
 			const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
@@ -203,7 +206,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 				(!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
 			if(bSkySolidColor)
 			{
-				cmdb.bindSrv(4, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+				cmdb.bindSrv(4, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
 			}
 			else if(sky->getSkyboxType() == SkyboxType::kImage2D)
 			{
@@ -214,24 +217,27 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 				rgraphCtx.bindSrv(4, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
 			}
 
-			cmdb.bindSrv(5, 2, BufferView(&getRenderer().getDummyBuffer(), 0, sizeof(U32)));
-			cmdb.bindSrv(6, 2, BufferView(&getRenderer().getDummyBuffer(), 0, sizeof(U32)));
+			cmdb.bindSrv(5, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
+			cmdb.bindSrv(6, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
 			rgraphCtx.bindSrv(7, 2, getRenderer().getShadowMapping().getShadowmapRt());
 
 			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
 			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
 
+			cmdb.bindUav(7, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
+			cmdb.bindUav(8, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
+
 			for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 			{
-				for(U32 c = 0; c < 3; ++c)
+				for(U32 dir = 0; dir < 6; ++dir)
 				{
-					rgraphCtx.bindUav(c, 2, volumeRts[clipmap][c]);
+					rgraphCtx.bindUav(dir, 2, volumeRts[clipmap][dir]);
 				}
 
-				const Vec4 consts(F32(U32(g_indirectDiffuseClipmap0SizeCVar) << clipmap));
+				const UVec4 consts(clipmap);
 				cmdb.setFastConstants(&consts, sizeof(consts));
 
-				const U32 probeCount = m_clipmapVolumes[clipmap].m_perColorComponent[0]->getWidth();
+				const U32 probeCount = m_clipmapVolumes[clipmap].m_directions[0]->getWidth();
 				cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
 							   probeCount, probeCount, probeCount);
 			}
@@ -241,11 +247,12 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 	{
 		NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps test");
 
-		const U32 clipmap = 2;
-
-		for(U32 c = 0; c < 3; ++c)
+		for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 		{
-			pass.newTextureDependency(volumeRts[clipmap][c], TextureUsageBit::kSrvCompute);
+			for(U32 dir = 0; dir < 6; ++dir)
+			{
+				pass.newTextureDependency(volumeRts[clipmap][dir], TextureUsageBit::kSrvCompute);
+			}
 		}
 		pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
 		pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
@@ -256,14 +263,17 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindShaderProgram(m_tmpVisGrProg.get());
 
-			const Vec4 consts(F32(U32(g_indirectDiffuseClipmap0SizeCVar) << clipmap));
-			cmdb.setFastConstants(&consts, sizeof(consts));
+			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getColorRt(2));
+
+			for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
+			{
+				for(U32 dir = 0; dir < 6; ++dir)
+				{
+					rgraphCtx.bindSrv(clipmap * 6 + dir + 2, 0, volumeRts[clipmap][dir]);
+				}
+			}
 
-			rgraphCtx.bindSrv(0, 0, volumeRts[clipmap][0]);
-			rgraphCtx.bindSrv(1, 0, volumeRts[clipmap][1]);
-			rgraphCtx.bindSrv(2, 0, volumeRts[clipmap][2]);
-			rgraphCtx.bindSrv(3, 0, getRenderer().getGBuffer().getDepthRt());
-			rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getColorRt(2));
 			rgraphCtx.bindUav(0, 0, m_runCtx.m_tmpRt);
 
 			cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);

+ 9 - 9
AnKi/Renderer/IndirectDiffuseClipmaps.h

@@ -16,16 +16,16 @@ namespace anki {
 
 inline BoolCVar g_rtIndirectDiffuseClipmapsCVar("R", "RtIndirectDiffuseClipmaps", false);
 
-inline NumericCVar<U32> g_indirectDiffuseClipmap0ProbesPerDimCVar("R", "IndirectDiffuseClipmap0ProbesPerDim", 20, 10, 50,
+inline NumericCVar<U32> g_indirectDiffuseClipmap0ProbesPerDimCVar("R", "IndirectDiffuseClipmap0ProbesPerDim", 32, 10, 100,
 																  "The cell count of each dimension of 1st clipmap");
-inline NumericCVar<U32> g_indirectDiffuseClipmap1ProbesPerDimCVar("R", "IndirectDiffuseClipmap1ProbesPerDim", 20, 10, 50,
+inline NumericCVar<U32> g_indirectDiffuseClipmap1ProbesPerDimCVar("R", "IndirectDiffuseClipmap1ProbesPerDim", 32, 10, 100,
 																  "The cell count of each dimension of 2nd clipmap");
-inline NumericCVar<U32> g_indirectDiffuseClipmap2ProbesPerDimCVar("R", "IndirectDiffuseClipmap2ProbesPerDim", 20, 10, 50,
+inline NumericCVar<U32> g_indirectDiffuseClipmap2ProbesPerDimCVar("R", "IndirectDiffuseClipmap2ProbesPerDim", 32, 10, 100,
 																  "The cell count of each dimension of 3rd clipmap");
 
-inline NumericCVar<F32> g_indirectDiffuseClipmap0SizeCVar("R", "IndirectDiffuseClipmap0Size", 20.0, 10.0, 1000.0, "The clipmap size in meters");
-inline NumericCVar<F32> g_indirectDiffuseClipmap1SizeCVar("R", "IndirectDiffuseClipmap1Size", 40.0, 10.0, 1000.0, "The clipmap size in meters");
-inline NumericCVar<F32> g_indirectDiffuseClipmap2SizeCVar("R", "IndirectDiffuseClipmap2Size", 80.0, 10.0, 1000.0, "The clipmap size in meters");
+inline NumericCVar<F32> g_indirectDiffuseClipmap0SizeCVar("R", "IndirectDiffuseClipmap0Size", 32.0, 10.0, 1000.0, "The clipmap size in meters");
+inline NumericCVar<F32> g_indirectDiffuseClipmap1SizeCVar("R", "IndirectDiffuseClipmap1Size", 64.0, 10.0, 1000.0, "The clipmap size in meters");
+inline NumericCVar<F32> g_indirectDiffuseClipmap2SizeCVar("R", "IndirectDiffuseClipmap2Size", 128.0, 10.0, 1000.0, "The clipmap size in meters");
 
 /// Ambient global illumination passes.
 class IndirectDiffuseClipmaps : public RendererObject
@@ -46,7 +46,7 @@ public:
 		handles[0] = m_runCtx.m_tmpRt;
 	}
 
-	const Array<IndirectDiffuseClipmap, kIndirectDiffuseClipmapCount>& getClipmapsInfo() const
+	const Array<Clipmap, kIndirectDiffuseClipmapCount>& getClipmapsInfo() const
 	{
 		return m_clipmapInfo;
 	}
@@ -55,12 +55,12 @@ private:
 	class ClipmapVolumes
 	{
 	public:
-		Array<TexturePtr, 3> m_perColorComponent;
+		Array<TexturePtr, 6> m_directions;
 	};
 
 	Array<ClipmapVolumes, kIndirectDiffuseClipmapCount> m_clipmapVolumes;
 
-	Array<IndirectDiffuseClipmap, kIndirectDiffuseClipmapCount> m_clipmapInfo;
+	Array<Clipmap, kIndirectDiffuseClipmapCount> m_clipmapInfo;
 
 	ShaderProgramResourcePtr m_prog;
 	ShaderProgramResourcePtr m_missProg;

+ 10 - 6
AnKi/Renderer/Reflections.cpp

@@ -362,7 +362,7 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 				(!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
 			if(bSkySolidColor)
 			{
-				cmdb.bindSrv(4, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+				cmdb.bindSrv(4, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
 			}
 			else if(sky->getSkyboxType() == SkyboxType::kImage2D)
 			{
@@ -377,13 +377,17 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 				5, 2,
 				(GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementCount())
 					? GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView()
-					: BufferView(&getRenderer().getDummyBuffer(), 0, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementSize()));
+					: BufferView(getDummyGpuResources().m_buffer.get(), 0, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementSize()));
 			cmdb.bindSrv(6, 2, pixelsFailedSsrBuff);
 			rgraphCtx.bindSrv(7, 2, getRenderer().getShadowMapping().getShadowmapRt());
 
-			rgraphCtx.bindUav(0, 2, transientRt1);
-			rgraphCtx.bindUav(1, 2, hitPosAndDepthRt);
-			cmdb.bindUav(2, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::firstSurface()));
+			for(U32 i = 0; i < 6; ++i)
+			{
+				cmdb.bindUav(i, 2, TextureView(getDummyGpuResources().m_texture3DUav.get(), TextureSubresourceDesc::firstSurface()));
+			}
+
+			rgraphCtx.bindUav(7, 2, transientRt1);
+			rgraphCtx.bindUav(8, 2, hitPosAndDepthRt);
 
 			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
 			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
@@ -439,7 +443,7 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 				(!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
 			if(bSkySolidColor)
 			{
-				cmdb.bindSrv(5, 0, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+				cmdb.bindSrv(5, 0, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
 			}
 			else if(sky->getSkyboxType() == SkyboxType::kImage2D)
 			{

+ 22 - 6
AnKi/Renderer/Renderer.cpp

@@ -167,18 +167,27 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 
 	// Dummy resources
 	{
-		TextureInitInfo texinit("RendererDummy");
+		TextureInitInfo texinit("DummyTexture");
 		texinit.m_width = texinit.m_height = 4;
-		texinit.m_usage = TextureUsageBit::kAllSrv | TextureUsageBit::kUavCompute;
+		texinit.m_usage = TextureUsageBit::kAllSrv | TextureUsageBit::kRtvDsvWrite;
 		texinit.m_format = Format::kR8G8B8A8_Unorm;
-		m_dummyTex2d = createAndClearRenderTarget(texinit, TextureUsageBit::kAllSrv);
+		m_dummyResources.m_texture2DSrv = createAndClearRenderTarget(texinit, TextureUsageBit::kAllSrv);
 
 		texinit.m_depth = 4;
 		texinit.m_type = TextureType::k3D;
-		m_dummyTex3d = createAndClearRenderTarget(texinit, TextureUsageBit::kAllSrv);
+		m_dummyResources.m_texture3DSrv = createAndClearRenderTarget(texinit, TextureUsageBit::kAllSrv);
 
-		m_dummyBuff = GrManager::getSingleton().newBuffer(
-			BufferInitInfo(1024, BufferUsageBit::kAllConstant | BufferUsageBit::kAllUav, BufferMapAccessBit::kNone, "Dummy"));
+		texinit.m_type = TextureType::k2D;
+		texinit.m_usage = TextureUsageBit::kAllUav;
+		texinit.m_depth = 1;
+		m_dummyResources.m_texture2DUav = createAndClearRenderTarget(texinit, TextureUsageBit::kAllUav);
+
+		texinit.m_depth = 4;
+		texinit.m_type = TextureType::k3D;
+		m_dummyResources.m_texture3DUav = createAndClearRenderTarget(texinit, TextureUsageBit::kAllUav);
+
+		m_dummyResources.m_buffer = GrManager::getSingleton().newBuffer(
+			BufferInitInfo(1024, BufferUsageBit::kAllConstant | BufferUsageBit::kAllUav, BufferMapAccessBit::kNone, "DummyBuffer"));
 	}
 
 	{
@@ -213,7 +222,14 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 		sinit.m_minMagFilter = SamplingFilter::kNearest;
 		m_samplers.m_nearestNearestClamp = GrManager::getSingleton().newSampler(sinit);
 
+		sinit.setName("NearestNearestRepeat");
+		sinit.m_addressing = SamplingAddressing::kRepeat;
+		sinit.m_mipmapFilter = SamplingFilter::kNearest;
+		sinit.m_minMagFilter = SamplingFilter::kNearest;
+		m_samplers.m_nearestNearestRepeat = GrManager::getSingleton().newSampler(sinit);
+
 		sinit.setName("TrilinearClamp");
+		sinit.m_addressing = SamplingAddressing::kClamp;
 		sinit.m_minMagFilter = SamplingFilter::kLinear;
 		sinit.m_mipmapFilter = SamplingFilter::kLinear;
 		m_samplers.m_trilinearClamp = GrManager::getSingleton().newSampler(sinit);

+ 15 - 18
AnKi/Renderer/Renderer.h

@@ -46,6 +46,7 @@ class RendererPrecreatedSamplers
 {
 public:
 	SamplerPtr m_nearestNearestClamp;
+	SamplerPtr m_nearestNearestRepeat;
 	SamplerPtr m_trilinearClamp;
 	SamplerPtr m_trilinearRepeat;
 	SamplerPtr m_trilinearRepeatAniso;
@@ -53,6 +54,17 @@ public:
 	SamplerPtr m_trilinearClampShadow;
 };
 
+/// Some dummy resources to fill the slots.
+class DummyGpuResources
+{
+public:
+	TexturePtr m_texture2DSrv;
+	TexturePtr m_texture3DSrv;
+	TexturePtr m_texture2DUav;
+	TexturePtr m_texture3DUav;
+	BufferPtr m_buffer;
+};
+
 enum class MeshletRenderingType
 {
 	kNone,
@@ -72,6 +84,8 @@ public:
 /// Offscreen renderer.
 class Renderer : public MakeSingleton<Renderer>
 {
+	friend class RendererObject;
+
 public:
 	Renderer();
 
@@ -133,21 +147,6 @@ public:
 	[[nodiscard]] TexturePtr createAndClearRenderTarget(const TextureInitInfo& inf, TextureUsageBit initialUsage,
 														const ClearValue& clearVal = ClearValue());
 
-	Texture& getDummyTexture2d() const
-	{
-		return *m_dummyTex2d;
-	}
-
-	Texture& getDummyTexture3d() const
-	{
-		return *m_dummyTex3d;
-	}
-
-	Buffer& getDummyBuffer() const
-	{
-		return *m_dummyBuff;
-	}
-
 	const RendererPrecreatedSamplers& getSamplers() const
 	{
 		return m_samplers;
@@ -237,9 +236,7 @@ private:
 
 	Array<Vec2, 64> m_jitterOffsets;
 
-	TexturePtr m_dummyTex2d;
-	TexturePtr m_dummyTex3d;
-	BufferPtr m_dummyBuff;
+	DummyGpuResources m_dummyResources;
 
 	RendererPrecreatedSamplers m_samplers;
 

+ 6 - 2
AnKi/Renderer/RendererObject.h

@@ -5,7 +5,7 @@
 
 #pragma once
 
-#include <AnKi/Renderer/Common.h>
+#include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Util/StdTypes.h>
 #include <AnKi/Gr.h>
 #include <AnKi/Resource/ResourceManager.h>
@@ -15,7 +15,6 @@
 namespace anki {
 
 // Forward
-class Renderer;
 class ResourceManager;
 
 /// @addtogroup renderer
@@ -122,6 +121,11 @@ protected:
 	{
 		fillBuffers(cmdb, ConstWeakArray<BufferView>(&buffer, 1), value);
 	}
+
+	static DummyGpuResources& getDummyGpuResources()
+	{
+		return Renderer::getSingleton().m_dummyResources;
+	}
 };
 /// @}
 

+ 21 - 9
AnKi/Renderer/RtMaterialFetchDbg.cpp

@@ -28,10 +28,15 @@ Error RtMaterialFetchDbg::init()
 		m_rtProg->getOrCreateVariant(variantInitInfo, variant);
 		m_libraryGrProg.reset(&variant->getProgram());
 		m_rayGenShaderGroupIdx = variant->getShaderGroupHandleIndex();
+	}
+
+	{
+		ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtMaterialFetchMiss.ankiprogbin", m_missProg));
 
-		ShaderProgramResourceVariantInitInfo variantInitInfo2(m_rtProg);
-		variantInitInfo2.requestTechniqueAndTypes(ShaderTypeBit::kMiss, "RtMaterialFetch");
-		m_rtProg->getOrCreateVariant(variantInitInfo2, variant);
+		ShaderProgramResourceVariantInitInfo variantInitInfo(m_missProg);
+		variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kMiss, "RtMaterialFetch");
+		const ShaderProgramResourceVariant* variant;
+		m_missProg->getOrCreateVariant(variantInitInfo, variant);
 		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
 	}
 
@@ -137,14 +142,21 @@ void RtMaterialFetchDbg::populateRenderGraph(RenderingContext& ctx)
 
 			rgraphCtx.bindSrv(0, 2, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
 
+			// Fill the rest of the interface resources
+			cmdb.bindSrv(1, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(2, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(3, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(4, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+			cmdb.bindSrv(5, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(GpuSceneGlobalIlluminationProbe)));
+			cmdb.bindSrv(6, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(PixelFailedSsr)));
+			cmdb.bindSrv(7, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
+
 			rgraphCtx.bindUav(0, 2, m_runCtx.m_rt);
+			cmdb.bindUav(1, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
+			cmdb.bindUav(2, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
 
-			// Fill the rest of the interface resources
-			cmdb.bindSrv(1, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
-			cmdb.bindSrv(2, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
-			cmdb.bindSrv(3, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
-			cmdb.bindSrv(4, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
-			cmdb.bindUav(1, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::firstSurface()));
+			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
 
 			cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
 						   getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), 1);

+ 1 - 0
AnKi/Renderer/RtMaterialFetchDbg.h

@@ -36,6 +36,7 @@ public:
 public:
 	ShaderProgramResourcePtr m_sbtProg;
 	ShaderProgramResourcePtr m_rtProg;
+	ShaderProgramResourcePtr m_missProg;
 	ShaderProgramPtr m_sbtBuildGrProg;
 	ShaderProgramPtr m_libraryGrProg;
 

+ 4 - 3
AnKi/Renderer/ShadowMapping.cpp

@@ -558,15 +558,16 @@ BufferView ShadowMapping::createVetVisibilityPass(CString passName, const LightC
 		cmdb.setFastConstants(&lightIndex, sizeof(lightIndex));
 
 		cmdb.bindSrv(0, 0, hashBuff);
-		cmdb.bindUav(0, 0, mdiBuff.isValid() ? mdiBuff : BufferView(&getRenderer().getDummyBuffer()).setRange(sizeof(U32)));
+		cmdb.bindUav(0, 0, mdiBuff.isValid() ? mdiBuff : BufferView(getDummyGpuResources().m_buffer.get()).setRange(sizeof(U32)));
 		cmdb.bindUav(1, 0, GpuSceneArrays::Light::getSingleton().getBufferView());
 		cmdb.bindUav(2, 0, GpuSceneArrays::LightVisibleRenderablesHash::getSingleton().getBufferView());
 		cmdb.bindUav(3, 0, clearTileIndirectArgs);
 		cmdb.bindUav(4, 0,
 					 dispatchMeshIndirectArgs.isValid() ? dispatchMeshIndirectArgs
-														: BufferView(&getRenderer().getDummyBuffer()).setRange(sizeof(DispatchIndirectArgs)));
+														: BufferView(getDummyGpuResources().m_buffer.get()).setRange(sizeof(DispatchIndirectArgs)));
 		cmdb.bindUav(5, 0,
-					 drawIndirectArgs.isValid() ? drawIndirectArgs : BufferView(&getRenderer().getDummyBuffer()).setRange(sizeof(DrawIndirectArgs)));
+					 drawIndirectArgs.isValid() ? drawIndirectArgs
+												: BufferView(getDummyGpuResources().m_buffer.get()).setRange(sizeof(DrawIndirectArgs)));
 
 		ANKI_ASSERT(RenderStateBucketContainer::getSingleton().getBucketCount(RenderingTechnique::kDepth) <= 64 && "TODO");
 		cmdb.dispatchCompute(1, 1, 1);

+ 4 - 4
AnKi/Renderer/Utils/GpuVisibility.cpp

@@ -657,11 +657,11 @@ void GpuVisibility::populateRenderGraphInternal(Bool distanceBased, BaseGpuVisib
 
 			cmdb.bindUav(0, 0, stage1Mem.m_counters);
 
-			cmdb.bindUav(1, 0, (bLegacyRendering) ? stage1Mem.m_visibleRenderables : BufferView(&getRenderer().getDummyBuffer()));
-			cmdb.bindUav(2, 0, (bMeshletRendering) ? stage1Mem.m_visibleMeshlets : BufferView(&getRenderer().getDummyBuffer()));
+			cmdb.bindUav(1, 0, (bLegacyRendering) ? stage1Mem.m_visibleRenderables : BufferView(getDummyGpuResources().m_buffer.get()));
+			cmdb.bindUav(2, 0, (bMeshletRendering) ? stage1Mem.m_visibleMeshlets : BufferView(getDummyGpuResources().m_buffer.get()));
 
-			cmdb.bindUav(3, 0, (bLegacyRendering) ? stage1Mem.m_renderablePrefixSums : BufferView(&getRenderer().getDummyBuffer()));
-			cmdb.bindUav(4, 0, (bMeshletRendering) ? stage1Mem.m_meshletPrefixSums : BufferView(&getRenderer().getDummyBuffer()));
+			cmdb.bindUav(3, 0, (bLegacyRendering) ? stage1Mem.m_renderablePrefixSums : BufferView(getDummyGpuResources().m_buffer.get()));
+			cmdb.bindUav(4, 0, (bMeshletRendering) ? stage1Mem.m_meshletPrefixSums : BufferView(getDummyGpuResources().m_buffer.get()));
 
 			cmdb.bindUav(5, 0, stage1Mem.m_gpuVisIndirectDispatchArgs);
 

+ 4 - 2
AnKi/Shaders/Common.hlsl

@@ -86,8 +86,10 @@ U32 getMaxNumericLimit()
 	return kMaxU32;
 }
 
-constexpr F32 kPi = 3.14159265358979323846f;
-constexpr F32 kNaN = 0.0f / 0.0f;
+constexpr F32 kPi = 3.14159265358979323846;
+constexpr F32 k2Pi = 2.0 * kPi;
+constexpr F32 kHalfPi = kPi / 2.0;
+constexpr F32 kNaN = 0.0 / 0.0;
 
 struct Barycentrics
 {

+ 13 - 13
AnKi/Shaders/FastMathFunctions.hlsl

@@ -8,23 +8,22 @@
 #include <AnKi/Shaders/Common.hlsl>
 
 /// Sin approximation: https://www.desmos.com/calculator/svgcjfskne
-F32 fastSin(F32 x)
+template<typename T>
+T fastSin(T x)
 {
-	const F32 k2Pi = 2.0 * kPi;
-	const F32 kPiOver2 = kPi / 2.0;
-
-	x = (x + kPiOver2) / (k2Pi) + 0.75;
+	x = (x + kHalfPi) / (k2Pi) + T(0.75);
 	x = frac(x);
-	x = x * 2.0 - 1.0;
+	x = x * T(2) - T(1);
 	x = x * abs(x) - x;
-	x *= 4.0;
+	x *= T(4);
 	return x;
 }
 
 /// Cos approximation
-F32 fastCos(F32 x)
+template<typename T>
+T fastCos(T x)
 {
-	return fastSin(x + kPi / 2.0);
+	return fastSin<T>(x + T(kHalfPi));
 }
 
 F32 fastSqrt(F32 x)
@@ -32,9 +31,10 @@ F32 fastSqrt(F32 x)
 	return asfloat(0x1FBD1DF5 + (asint(x) >> 1));
 }
 
-F32 fastAcos(F32 x)
+template<typename T>
+T fastAcos(T x)
 {
-	F32 res = -0.156583f * abs(x) + kPi / 2.0f;
-	res *= fastSqrt(1.0f - abs(x));
-	return (x > 0.0f) ? res : kPi - res;
+	T res = T(-0.156583) * abs(x) + T(kHalfPi);
+	res *= fastSqrt(T(1) - abs(x));
+	return (x > T(0)) ? res : T(kPi) - res;
 }

+ 39 - 0
AnKi/Shaders/Functions.hlsl

@@ -806,3 +806,42 @@ Vec3 octahedronDecode(Vec2 f)
 	n.xy += select(n.xy >= 0.0, -t, t);
 	return normalize(n);
 }
+
+/// Manual texture sampling of a 3D texture.
+template<typename T, U32 kComp>
+vector<T, kComp> linearTextureSampling(Texture3D<Vec4> sam, Vec3 uv)
+{
+	Vec3 texSize;
+	sam.GetDimensions(texSize.x, texSize.y, texSize.z);
+
+	uv = frac(uv);
+	uv = uv * texSize - 0.5;
+	Vec3 iuv = floor(uv);
+	Vec3 fuv = frac(uv);
+
+	vector<T, kComp> o = T(0);
+
+	[unroll] for(F32 x = 0.0; x < 2.0; x += 1.0)
+	{
+		[unroll] for(F32 y = 0.0; y < 2.0; y += 1.0)
+		{
+			[unroll] for(F32 z = 0.0; z < 2.0; z += 1.0)
+			{
+				Vec3 coords = iuv + Vec3(x, y, z);
+
+				// Repeat
+				coords = select(coords >= 0.0, coords, texSize + coords);
+				coords = select(coords < texSize, coords, coords - texSize);
+
+				const vector<T, kComp> s = sam[coords];
+
+				const vector<T, 3> w3 = select(Vec3(x, y, z) == T(0), T(1) - fuv, fuv);
+				const T w = w3.x * w3.y * w3.z;
+
+				o += s * w;
+			}
+		}
+	}
+
+	return o;
+}

+ 2 - 4
AnKi/Shaders/GpuVisibilityAccelerationStructures.ankiprog

@@ -109,10 +109,8 @@ ANKI_FAST_CONSTANTS(GpuVisibilityAccelerationStructuresConstants, g_consts)
 				AccelerationStructureInstance instance;
 				instance.m_transform = finalTrf;
 				instance.m_mask8_instanceCustomIndex24 = (meshLod.m_tlasInstanceMask << 24u) | (instanceIdx & 0x00FFFFFFu);
-				instance.m_flags8_instanceShaderBindingTableRecordOffset24 =
-					((kAccellerationStructureFlagTriangleFrontCounterlockwise | kAccellerationStructureFlagTriangleFacingCullDisable)
-					 << (AccellerationStructureFlag)24u)
-					| (instanceIdx & 0x00FFFFFFu);
+				const U32 instanceFlags = kAccellerationStructureFlagTriangleFrontCounterlockwise;
+				instance.m_flags8_instanceShaderBindingTableRecordOffset24 = (instanceFlags << 24u) | (instanceIdx & 0x00FFFFFFu);
 				instance.m_accelerationStructureAddress = meshLod.m_blasAddress;
 
 				SBUFF(g_visibleInstances, instanceIdx) = instance;

+ 28 - 1
AnKi/Shaders/ImportanceSampling.hlsl

@@ -7,7 +7,7 @@
 
 #pragma once
 
-#include <AnKi/Shaders/Common.hlsl>
+#include <AnKi/Shaders/FastMathFunctions.hlsl>
 
 /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
 /// Using reversebits instead of bitwise ops
@@ -120,3 +120,30 @@ Vec2 spatioTemporalNoise(UVec2 fragCoord, U32 temporalIdx)
 	index += 288u * (temporalIdx % 64u);
 	return Vec2(frac(0.5f + index * Vec2(0.75487766624669276005f, 0.5698402909980532659114f)));
 }
+
+/// Generates a point on the unit sphere. The frameIndex can be used as a randomizer. No need to modulate the frameIndex.
+/// Usage:
+/// for(U32 s = 0; s < 32; ++s) {
+///		Vec3 point = generateUniformPointOnSphere(s, 32, frameIndex);
+/// }
+template<typename T, typename TInt>
+vector<T, 3> generateUniformPointOnSphere(TInt sampleIndex, TInt sampleCount, U32 frameIndex)
+{
+	const T sampleIndexf = sampleIndex;
+	const T sampleCountf = sampleCount;
+
+	// Apply frame-dependent phase shift for randomness
+	const T phaseShift = (frameIndex % sampleCount) * (T(k2Pi) / sampleCountf);
+
+	// Compute spherical coordinates
+	const T goldenRatio = 1.618;
+	const T theta = fastAcos(T(1) - T(2) * (sampleIndexf + T(0.5)) / sampleCountf); // Evenly spaced latitudes
+	const T phi = fmod((T(k2Pi * goldenRatio) * sampleIndexf + phaseShift), T(k2Pi)); // Golden ratio spiral with phase shift
+
+	// Convert to Cartesian coordinates
+	const T x = fastSin(theta) * fastCos(phi);
+	const T y = fastSin(theta) * fastSin(phi);
+	const T z = fastCos(theta);
+
+	return vector<T, 3>(x, y, z);
+}

+ 2 - 0
AnKi/Shaders/Include/Common.h

@@ -410,6 +410,8 @@ typedef min16float3 RVec3;
 typedef min16float4 RVec4;
 _ANKI_MAT3(RMat3, RVec3, RF32)
 #		endif
+#	else // ANKI_SUPPORTS_16BIT_TYPES == 0
+	_ANKI_MAT3(HMat3, HVec3, F16)
 #	endif // ANKI_SUPPORTS_16BIT_TYPES == 0
 
 #endif // defined(__HLSL_VERSION)

+ 3 - 3
AnKi/Shaders/Include/MiscRendererTypes.h

@@ -70,10 +70,10 @@ struct Sky
 	U32 m_type;
 };
 
-struct IndirectDiffuseClipmap
+struct Clipmap
 {
 	Vec3 m_probeCounts;
-	F32 m_padding1;
+	U32 m_padding1;
 
 	Vec3 m_size;
 	F32 m_padding2;
@@ -110,7 +110,7 @@ struct GlobalRendererConstants
 
 	Sky m_sky;
 
-	IndirectDiffuseClipmap m_indirectDiffuseClipmaps[kIndirectDiffuseClipmapCount];
+	Clipmap m_indirectDiffuseClipmaps[kIndirectDiffuseClipmapCount];
 };
 
 // RT shadows

+ 95 - 83
AnKi/Shaders/IndirectDiffuseClipmaps.ankiprog

@@ -15,60 +15,64 @@
 #include <AnKi/Shaders/ImportanceSampling.hlsl>
 #include <AnKi/Shaders/PackFunctions.hlsl>
 #include <AnKi/Shaders/SH.hlsl>
+#include <AnKi/Shaders/IrradianceDice.hlsl>
+#include <AnKi/Shaders/FastMathFunctions.hlsl>
 
 #define CLIPMAP_VOLUME 1
 #include <AnKi/Shaders/RtMaterialFetch.hlsl>
 
-struct Clipmap
+Vec3 worldPosToVolumeUvw(Clipmap clipmap, Vec3 worldPos)
 {
-	F32 m_size;
-	F32 m_padding0;
-	F32 m_padding1;
-	F32 m_padding2;
-};
-
-ANKI_FAST_CONSTANTS(Clipmap, g_clipmap)
+	const Vec3 uvw = frac(worldPos / clipmap.m_size);
+	return uvw;
+}
 
-Vec3 worldPosToVolumeUvw(Vec3 worldPos, Vec3 clipmapSize)
+UVec3 worldPosToVolumeTexel(Clipmap clipmap, Vec3 worldPos)
 {
-	const Vec3 uvw = frac(worldPos / clipmapSize);
-	return uvw;
+	const Vec3 uvw = worldPosToVolumeUvw(clipmap, worldPos);
+	return uvw * clipmap.m_probeCounts;
 }
 
-UVec3 worldPosToVolumeTexel(Vec3 worldPos, Vec3 clipmapSize, F32 probeCountPerDim)
+void computeClipmapBounds(Clipmap clipmap, Vec3 cameraPos, out Vec3 aabbMin, out Vec3 aabbMax)
 {
-	const Vec3 uvw = worldPosToVolumeUvw(worldPos, clipmapSize);
-	return uvw * probeCountPerDim;
+	const Vec3 halfSize = clipmap.m_size * 0.5;
+	const Vec3 probeSize = clipmap.m_size / clipmap.m_probeCounts;
+	const Vec3 roundedPos = round(cameraPos / probeSize) * probeSize;
+	aabbMin = roundedPos - halfSize;
+	aabbMax = roundedPos + halfSize;
 }
 
-void computeClipmapBounds(Vec3 cameraPos, Vec3 clipmapSize, out Vec3 aabbMin, out Vec3 aabbMax)
+void computeClipmapBoundsConservative(Clipmap clipmap, Vec3 cameraPos, out Vec3 aabbMin, out Vec3 aabbMax)
 {
-	aabbMin = round(cameraPos) - clipmapSize * 0.5;
-	aabbMax = round(cameraPos) + clipmapSize * 0.5;
+	const Vec3 halfSize = clipmap.m_size * 0.5;
+	const Vec3 probeSize = clipmap.m_size / clipmap.m_probeCounts;
+	const Vec3 roundedPos = round(cameraPos / probeSize) * probeSize;
+	aabbMin = roundedPos - halfSize + probeSize * 0.5;
+	aabbMax = roundedPos + halfSize - probeSize * 0.5;
 }
 
-SHL1<F16> readClipmap(GlobalRendererConstants consts, Texture3D<Vec4> volumes[3 * kIndirectDiffuseClipmapCount], SamplerState linearAnyRepeatSampler,
-					  Vec3 worldPos)
+SHL1<F16> readClipmap(Clipmap clipmaps[kIndirectDiffuseClipmapCount], Texture3D<Vec4> volumes[3 * kIndirectDiffuseClipmapCount],
+					  SamplerState linearAnyRepeatSampler, Vec3 cameraPos, Vec3 worldPos)
 {
 	Vec3 clipmapAabbMin, clipmapAabbMax;
-	computeClipmapBounds(consts.m_cameraPosition, consts.m_indirectDiffuseClipmaps[0].m_size, clipmapAabbMin, clipmapAabbMax);
+	computeClipmapBoundsConservative(clipmaps[0], cameraPos, clipmapAabbMin, clipmapAabbMax);
 	if(all(worldPos > clipmapAabbMin) && all(worldPos < clipmapAabbMax))
 	{
-		const Vec3 uvw = worldPosToVolumeUvw(worldPos, consts.m_indirectDiffuseClipmaps[0].m_size);
+		const Vec3 uvw = worldPosToVolumeUvw(clipmaps[0], worldPos);
 		return loadSH<F16>(volumes[0], volumes[1], volumes[2], linearAnyRepeatSampler, uvw);
 	}
 
-	computeClipmapBounds(consts.m_cameraPosition, consts.m_indirectDiffuseClipmaps[1].m_size, clipmapAabbMin, clipmapAabbMax);
+	computeClipmapBoundsConservative(clipmaps[1], cameraPos, clipmapAabbMin, clipmapAabbMax);
 	if(all(worldPos > clipmapAabbMin) && all(worldPos < clipmapAabbMax))
 	{
-		const Vec3 uvw = worldPosToVolumeUvw(worldPos, consts.m_indirectDiffuseClipmaps[1].m_size);
+		const Vec3 uvw = worldPosToVolumeUvw(clipmaps[1], worldPos);
 		return loadSH<F16>(volumes[3], volumes[4], volumes[5], linearAnyRepeatSampler, uvw);
 	}
 
-	computeClipmapBounds(consts.m_cameraPosition, consts.m_indirectDiffuseClipmaps[2].m_size, clipmapAabbMin, clipmapAabbMax);
+	computeClipmapBoundsConservative(clipmaps[2], cameraPos, clipmapAabbMin, clipmapAabbMax);
 	if(all(worldPos > clipmapAabbMin) && all(worldPos < clipmapAabbMax))
 	{
-		const Vec3 uvw = worldPosToVolumeUvw(worldPos, consts.m_indirectDiffuseClipmaps[2].m_size);
+		const Vec3 uvw = worldPosToVolumeUvw(clipmaps[2], worldPos);
 		return loadSH<F16>(volumes[6], volumes[7], volumes[8], linearAnyRepeatSampler, uvw);
 	}
 
@@ -76,75 +80,99 @@ SHL1<F16> readClipmap(GlobalRendererConstants consts, Texture3D<Vec4> volumes[3
 	return sh;
 }
 
+IrradianceDice<F16> readClipmap(Clipmap clipmaps[kIndirectDiffuseClipmapCount], Texture3D<Vec4> volumes[6 * kIndirectDiffuseClipmapCount],
+								SamplerState linearAnyRepeatSampler, Vec3 cameraPos, Vec3 worldPos)
+{
+	Vec3 clipmapAabbMin, clipmapAabbMax;
+	computeClipmapBoundsConservative(clipmaps[0], cameraPos, clipmapAabbMin, clipmapAabbMax);
+	if(all(worldPos > clipmapAabbMin) && all(worldPos < clipmapAabbMax))
+	{
+		const Vec3 uvw = worldPosToVolumeUvw(clipmaps[0], worldPos);
+		return loadIrradianceDice<F16>(volumes, linearAnyRepeatSampler, uvw, 0);
+	}
+
+	computeClipmapBoundsConservative(clipmaps[1], cameraPos, clipmapAabbMin, clipmapAabbMax);
+	if(all(worldPos > clipmapAabbMin) && all(worldPos < clipmapAabbMax))
+	{
+		const Vec3 uvw = worldPosToVolumeUvw(clipmaps[1], worldPos);
+		return loadIrradianceDice<F16>(volumes, linearAnyRepeatSampler, uvw, 6);
+	}
+
+	computeClipmapBoundsConservative(clipmaps[2], cameraPos, clipmapAabbMin, clipmapAabbMax);
+	if(all(worldPos > clipmapAabbMin) && all(worldPos < clipmapAabbMax))
+	{
+		const Vec3 uvw = worldPosToVolumeUvw(clipmaps[2], worldPos);
+		return loadIrradianceDice<F16>(volumes, linearAnyRepeatSampler, uvw, 12);
+	}
+
+	IrradianceDice<F16> dice = (IrradianceDice<F16>)0;
+	return dice;
+}
+
 // ===========================================================================
 // RayGen                                                                    =
 // ===========================================================================
 #if ANKI_RAY_GEN_SHADER
 
+struct Consts
+{
+	U32 m_clipmapIdx;
+	F32 m_padding0;
+	F32 m_padding1;
+	F32 m_padding2;
+};
+ANKI_FAST_CONSTANTS(Consts, g_consts)
+
 [Shader("raygeneration")] void main()
 {
-	F32 probeCountPerDim, unused0, unused1;
-	g_clipmapRedVolume.GetDimensions(probeCountPerDim, unused0, unused1);
+	const Clipmap clipmap = g_globalRendererConstants.m_indirectDiffuseClipmaps[g_consts.m_clipmapIdx];
 
 	// Compute clipmap bounds
 	Vec3 clipmapAabbMin, clipmapAabbMax;
-	computeClipmapBounds(g_globalRendererConstants.m_cameraPosition, g_clipmap.m_size, clipmapAabbMin, clipmapAabbMax);
+	computeClipmapBounds(clipmap, g_globalRendererConstants.m_cameraPosition, clipmapAabbMin, clipmapAabbMax);
 
 	const Vec3 prevCameraPos = g_globalRendererConstants.m_previousMatrices.m_cameraTransform.getTranslationPart();
 	Vec3 prevClipmapAabbMin, prevClipmapAabbMax;
-	computeClipmapBounds(prevCameraPos, g_clipmap.m_size, prevClipmapAabbMin, prevClipmapAabbMax);
+	computeClipmapBounds(clipmap, prevCameraPos, prevClipmapAabbMin, prevClipmapAabbMax);
 
 	// Compute probe info
-	const F32 probeSize = g_clipmap.m_size / probeCountPerDim;
+	const Vec3 probeSize = clipmap.m_size / clipmap.m_probeCounts;
 	const Vec3 cellWorldPos = DispatchRaysIndex().xyz * probeSize + probeSize * 0.5 + clipmapAabbMin;
 
-	const UVec3 probeTexelCoord = worldPosToVolumeTexel(cellWorldPos, g_clipmap.m_size, probeCountPerDim);
-	ANKI_ASSERT(all(probeTexelCoord < probeCountPerDim));
+	const UVec3 probeTexelCoord = worldPosToVolumeTexel(clipmap, cellWorldPos);
+	ANKI_ASSERT(all(probeTexelCoord < clipmap.m_probeCounts));
 
 	// Integrate to build the SH
-	SHL1<F16> sh = (SHL1<F16>)0;
-	const U32 slices = 8u;
-	const U32 rayCount = slices * slices / 2u;
-
-	const UVec3 seed = rand3DPCG16(UVec3(DispatchRaysIndex().xy, g_globalRendererConstants.m_frame % 32u));
-	const Vec2 randFactors = hammersleyRandom16(0, 1, seed);
+	IrradianceDice<F16> dice = (IrradianceDice<F16>)0;
+	const U16 sampleCount = 32u;
 
-	const F32 angle = 2.0 * kPi / slices;
-
-	for(U32 i = 0; i < slices; ++i)
+	for(U16 i = 0; i < sampleCount; ++i)
 	{
-		for(U32 j = 0; j < slices / 2u; ++j)
-		{
-			const F32 phi = angle * i + angle * randFactors.x;
-			const F32 theta = angle * j + angle * randFactors.y;
+		HVec3 dir = generateUniformPointOnSphere<F16>(i, sampleCount, g_globalRendererConstants.m_frame);
 
-			HVec3 dir;
-			dir.x = sin(theta) * cos(phi);
-			dir.y = sin(theta) * sin(phi);
-			dir.z = cos(theta);
+		const F32 tMax = 1000.0; // TODO
 
-			const F32 tMax = 1000.0; // TODO
+		constexpr U32 traceFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES;
 
-			GBufferLight<F16> gbuffer = (GBufferLight<F16>)0;
-			F32 rayT = 0.0;
-			const Bool hit = materialRayTrace<F16>(cellWorldPos, dir, 0.01, tMax, 1000.0, gbuffer, rayT);
+		GBufferLight<F16> gbuffer = (GBufferLight<F16>)0;
+		F32 rayT = 0.0;
+		const Bool hit = materialRayTrace<F16>(cellWorldPos, dir, 0.0, tMax, 1000.0, gbuffer, rayT, traceFlags);
 
-			const Vec3 hitPos = cellWorldPos + dir * rayT;
-			const HVec3 radiance = directLighting(gbuffer, hitPos, !hit, true, tMax);
+		const Vec3 hitPos = cellWorldPos + dir * rayT;
+		const HVec3 radiance = directLighting<F16>(gbuffer, hitPos, !hit, false, tMax, traceFlags | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH);
 
-			sh = appendSH(sh, dir, radiance, rayCount);
-		}
+		dice = appendIrradianceDice(dice, dir, radiance, sampleCount);
 	}
 
 	// Store the SH
 	const Bool blendWithHistory = all(cellWorldPos > prevClipmapAabbMin) && all(cellWorldPos < prevClipmapAabbMax);
 	if(blendWithHistory)
 	{
-		const SHL1<F16> historySH = loadSH<F16>(g_clipmapRedVolume, g_clipmapGreenVolume, g_clipmapBlueVolume, probeTexelCoord);
-		sh = lerpSH<F16>(historySH, sh, 0.01);
+		const IrradianceDice<F16> historyDice = loadIrradianceDice<F16>(g_clipmapVolumes, probeTexelCoord);
+		dice = lerpIrradianceDice<F16>(historyDice, dice, 0.01);
 	}
 
-	storeSH(sh, g_clipmapRedVolume, g_clipmapGreenVolume, g_clipmapBlueVolume, probeTexelCoord);
+	storeIrradianceDice(dice, g_clipmapVolumes, probeTexelCoord);
 }
 #endif // ANKI_RAY_GEN_SHADER
 
@@ -155,11 +183,11 @@ SHL1<F16> readClipmap(GlobalRendererConstants consts, Texture3D<Vec4> volumes[3
 Texture2D<Vec4> g_depthTex : register(t0);
 Texture2D<Vec4> g_gbufferRt2 : register(t1);
 
-Texture3D<Vec4> g_clipmapVolumes[3 * kIndirectDiffuseClipmapCount] : register(t2);
+Texture3D<Vec4> g_clipmapVolumes[6 * kIndirectDiffuseClipmapCount] : register(t2);
 
 RWTexture2D<Vec4> g_outTex : register(u0);
 
-ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
+ConstantBuffer<GlobalRendererConstants> g_globalRendererConstants : register(b0);
 
 SamplerState g_linearAnyRepeatSampler : register(s0);
 
@@ -177,29 +205,13 @@ SamplerState g_linearAnyRepeatSampler : register(s0);
 
 	const F32 depth = g_depthTex[svDispatchThreadId].r;
 	const Vec2 ndc = uvToNdc(Vec2(svDispatchThreadId) / Vec2(viewportSize));
-	const Vec4 worldPos4 = mul(g_globalConstants.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
+	const Vec4 worldPos4 = mul(g_globalRendererConstants.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
 	Vec3 worldPos = worldPos4.xyz / worldPos4.w;
 
-	worldPos += normal * 0.5;
-
-	const Vec3 uvw = worldPosToVolumeUvw(worldPos, g_clipmap.m_size);
-
-	const SHL1<F32> sh = loadSH<F32>(g_clipmapVolumes[0], g_clipmapVolumes[1], g_clipmapVolumes[2], g_linearAnyRepeatSampler, uvw);
-	// const SHL1<F32> sh = loadSH<F32>(g_clipmapRedVolume, g_clipmapGreenVolume, g_clipmapBlueVolume, uvw * 20);
-
-	const Vec3 color = evaluateSH(sh, normal);
-
-	// const Vec3 color = g_volume.SampleLevel(g_linearAnyRepeatSampler, uvw, 0.0);
-	// const Vec3 color = g_volume[uvw * 40.0];
-
-	Vec3 clipMin, clipMax;
-	computeClipmapBounds(g_globalConstants.m_cameraPosition, g_clipmap.m_size, clipMin, clipMax);
-	clipMin += 2;
-	clipMax -= 2;
+	const IrradianceDice<F16> dice = readClipmap(g_globalRendererConstants.m_indirectDiffuseClipmaps, g_clipmapVolumes, g_linearAnyRepeatSampler,
+												 g_globalRendererConstants.m_cameraPosition, worldPos);
+	const HVec3 irradiance = evaluateIrradianceDice<F16>(dice, normal);
 
-	if(any(worldPos > clipMax) || any(worldPos < clipMin))
-		g_outTex[svDispatchThreadId] = 0.1;
-	else
-		g_outTex[svDispatchThreadId] = Vec4(color, 1.0);
+	g_outTex[svDispatchThreadId] = Vec4(irradiance, 1.0);
 }
 #endif

+ 3 - 0
AnKi/Shaders/Intellisense.hlsl

@@ -245,6 +245,9 @@ T round(T x);
 template<typename T>
 T ceil(T x);
 
+template<typename T>
+T floor(T x);
+
 template<typename T>
 T frac(T x);
 

+ 15 - 14
AnKi/Shaders/IrradianceDice.hlsl

@@ -37,14 +37,14 @@ template<typename T>
 vector<T, 3> evaluateIrradianceDice(IrradianceDice<T> dice, vector<T, 3> direction)
 {
 	const vector<T, 3> axisWeights = direction * direction;
-	const vector<T, 3> uv = direction * 0.5 + 0.5;
+	const vector<T, 3> uv = direction * T(0.5) + T(0.5);
 
 	vector<T, 3> irradiance = lerp(dice.m_directions[1], dice.m_directions[0], uv.x) * axisWeights.x;
 	irradiance += lerp(dice.m_directions[3], dice.m_directions[2], uv.y) * axisWeights.y;
 	irradiance += lerp(dice.m_directions[5], dice.m_directions[4], uv.z) * axisWeights.z;
 
 	// Divide by weight
-	irradiance /= axisWeights.x + axisWeights.y + axisWeights.z + 0.0001;
+	irradiance /= axisWeights.x + axisWeights.y + axisWeights.z + T(0.0001);
 
 	return irradiance;
 }
@@ -60,47 +60,48 @@ IrradianceDice<T> lerpIrradianceDice(IrradianceDice<T> a, IrradianceDice<T> b, T
 	return a;
 }
 
-template<typename T>
-IrradianceDice<T> loadIrradianceDice(Texture3D<Vec4> volumes[6u], SamplerState sampler, Vec3 uvw)
+template<typename T, U32 kVolumeCount>
+IrradianceDice<T> loadIrradianceDice(Texture3D<Vec4> volumes[kVolumeCount], SamplerState sampler, Vec3 uvw, U32 firstVolume = 0)
 {
 	IrradianceDice<T> dice;
 	[unroll] for(U32 i = 0; i < 6; ++i)
 	{
-		dice.m_directions[i] = volumes[i].SampleLevel(sampler, uvw, 0.0).xyz;
+		dice.m_directions[i] = volumes[firstVolume + i].SampleLevel(sampler, uvw, 0.0).xyz;
+		// dice.m_directions[i] = textureLinear<F16, 3>(volumes[firstVolume + i], uvw).xyz;
 	}
 
 	return dice;
 }
 
-template<typename T>
-IrradianceDice<T> loadIrradianceDice(Texture3D<Vec4> volumes[6u], UVec3 uvw)
+template<typename T, U32 kVolumeCount>
+IrradianceDice<T> loadIrradianceDice(Texture3D<Vec4> volumes[kVolumeCount], UVec3 uvw, U32 firstVolume = 0)
 {
 	IrradianceDice<T> dice;
 	[unroll] for(U32 i = 0; i < 6; ++i)
 	{
-		dice.m_directions[i] = volumes[i][uvw].xyz;
+		dice.m_directions[i] = volumes[firstVolume + i][uvw].xyz;
 	}
 
 	return dice;
 }
 
-template<typename T>
-IrradianceDice<T> loadIrradianceDice(RWTexture3D<Vec4> volumes[6u], UVec3 uvw)
+template<typename T, U32 kVolumeCount>
+IrradianceDice<T> loadIrradianceDice(RWTexture3D<Vec4> volumes[kVolumeCount], UVec3 uvw, U32 firstVolume = 0)
 {
 	IrradianceDice<T> dice;
 	[unroll] for(U32 i = 0; i < 6; ++i)
 	{
-		dice.m_directions[i] = volumes[i][uvw].xyz;
+		dice.m_directions[i] = volumes[firstVolume + i][uvw].xyz;
 	}
 
 	return dice;
 }
 
-template<typename T>
-void storeIrradianceDice(IrradianceDice<T> dice, RWTexture3D<Vec4> volumes[6u], UVec3 coords)
+template<typename T, U32 kVolumeCount>
+void storeIrradianceDice(IrradianceDice<T> dice, RWTexture3D<Vec4> volumes[kVolumeCount], UVec3 coords, U32 firstVolume = 0)
 {
 	[unroll] for(U32 i = 0; i < 6; ++i)
 	{
-		volumes[i][coords] = vector<T, 4>(dice.m_directions[i], T(0));
+		volumes[firstVolume + i][coords] = vector<T, 4>(dice.m_directions[i], T(0));
 	}
 }

+ 14 - 16
AnKi/Shaders/RtMaterialFetch.hlsl

@@ -25,6 +25,7 @@ struct [raypayload] RtMaterialFetchRayPayload // TODO make it FP16 when you chan
 
 ConstantBuffer<GlobalRendererConstants> g_globalRendererConstants : register(b0, SPACE);
 
+// SRVs
 RaytracingAccelerationStructure g_tlas : register(t0, SPACE);
 #	if defined(CLIPMAP_VOLUME)
 Texture2D<Vec4> g_dummyTex1 : register(t1, SPACE);
@@ -45,15 +46,13 @@ StructuredBuffer<PixelFailedSsr> g_pixelsFailedSsr : register(t6, SPACE);
 #	endif
 Texture2D<Vec4> g_shadowAtlasTex : register(t7, SPACE);
 
-#	if defined(CLIPMAP_VOLUME)
-RWTexture3D<Vec4> g_clipmapRedVolume : register(u0, SPACE);
-RWTexture3D<Vec4> g_clipmapGreenVolume : register(u1, SPACE);
-RWTexture3D<Vec4> g_clipmapBlueVolume : register(u2, SPACE);
-#	else
-RWTexture2D<Vec4> g_colorAndPdfTex : register(u0, SPACE);
-RWTexture2D<Vec4> g_hitPosAndDepthTex : register(u1, SPACE);
-#	endif
+// UAVs
+RWTexture3D<Vec4> g_clipmapVolumes[6u] : register(u0, SPACE);
+
+RWTexture2D<Vec4> g_colorAndPdfTex : register(u7, SPACE);
+RWTexture2D<Vec4> g_hitPosAndDepthTex : register(u8, SPACE);
 
+// Samplers
 SamplerState g_linearClampAnySampler : register(s0, SPACE);
 SamplerComparisonState g_shadowSampler : register(s1, SPACE);
 
@@ -66,11 +65,11 @@ struct GBufferLight
 };
 
 template<typename T>
-Bool materialRayTrace(Vec3 rayOrigin, Vec3 rayDir, F32 tMin, F32 tMax, T textureLod, out GBufferLight<T> gbuffer, out F32 rayT)
+Bool materialRayTrace(Vec3 rayOrigin, Vec3 rayDir, F32 tMin, F32 tMax, T textureLod, out GBufferLight<T> gbuffer, out F32 rayT,
+					  U32 traceFlags = RAY_FLAG_FORCE_OPAQUE)
 {
 	RtMaterialFetchRayPayload payload;
 	payload.m_textureLod = textureLod;
-	const U32 flags = RAY_FLAG_FORCE_OPAQUE;
 	const U32 sbtRecordOffset = 0u;
 	const U32 sbtRecordStride = 0u;
 	const U32 missIndex = 0u;
@@ -80,7 +79,7 @@ Bool materialRayTrace(Vec3 rayOrigin, Vec3 rayDir, F32 tMin, F32 tMax, T texture
 	ray.TMin = tMin;
 	ray.Direction = rayDir;
 	ray.TMax = tMax;
-	TraceRay(g_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
+	TraceRay(g_tlas, traceFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
 
 	rayT = payload.m_rayT;
 	const Bool hasHitSky = payload.m_rayT < 0.0;
@@ -109,7 +108,8 @@ Bool materialRayTrace(Vec3 rayOrigin, Vec3 rayDir, F32 tMin, F32 tMax, T texture
 }
 
 template<typename T>
-vector<T, 3> directLighting(GBufferLight<T> gbuffer, Vec3 hitPos, Bool isSky, Bool tryShadowmapFirst, F32 shadowTMax)
+vector<T, 3> directLighting(GBufferLight<T> gbuffer, Vec3 hitPos, Bool isSky, Bool tryShadowmapFirst, F32 shadowTMax,
+							U32 traceFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH)
 {
 	vector<T, 3> color = gbuffer.m_emission;
 
@@ -134,16 +134,14 @@ vector<T, 3> directLighting(GBufferLight<T> gbuffer, Vec3 hitPos, Bool isSky, Bo
 		}
 		else
 		{
-			constexpr U32 qFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH;
-			RayQuery<qFlags> q;
-			const U32 flags = RAY_FLAG_FORCE_OPAQUE;
+			RayQuery<RAY_FLAG_NONE> q;
 			const U32 cullMask = 0xFFu;
 			RayDesc ray;
 			ray.Origin = hitPos;
 			ray.TMin = 0.01;
 			ray.Direction = -dirLight.m_direction;
 			ray.TMax = shadowTMax;
-			q.TraceRayInline(g_tlas, qFlags, cullMask, ray);
+			q.TraceRayInline(g_tlas, traceFlags, cullMask, ray);
 			q.Proceed();
 			shadow = (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) ? 0.0 : 1.0;
 		}

+ 4 - 22
AnKi/Shaders/RtMaterialFetchDbg.ankiprog

@@ -3,15 +3,11 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#pragma anki technique RtMaterialFetch rgen miss
+#pragma anki technique RtMaterialFetch rgen
 
 #include <AnKi/Shaders/RtMaterialFetch.hlsl>
 #include <AnKi/Shaders/Include/GpuSceneTypes.h>
 
-// ===========================================================================
-// RayGen                                                                    =
-// ===========================================================================
-#if ANKI_RAY_GEN_SHADER
 [shader("raygeneration")] void main()
 {
 	Vec2 outSize;
@@ -28,7 +24,7 @@
 	RtMaterialFetchRayPayload payload;
 	payload = (RtMaterialFetchRayPayload)0;
 	payload.m_textureLod = 0.0;
-	const U32 flags = RAY_FLAG_FORCE_OPAQUE;
+	const U32 flags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_CULL_FRONT_FACING_TRIANGLES;
 	const U32 sbtRecordOffset = 0u;
 	const U32 sbtRecordStride = 0u;
 	const U32 missIndex = 0u;
@@ -40,20 +36,6 @@
 	ray.TMax = 100.0; // TODO
 	TraceRay(g_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
 
-	g_colorAndPdfTex[DispatchRaysIndex().xy] =
-		Vec4(payload.m_diffuseColor + payload.m_worldNormal * 0.0 + payload.m_rayT * 0.0 + payload.m_emission * 0.0, 0.0);
+	const Vec3 col = payload.m_diffuseColor * 1.0 + (payload.m_worldNormal.xyz / 2.0 + 0.5) * 0.0 + payload.m_rayT * 0.0 + payload.m_emission * 0.0;
+	g_colorAndPdfTex[DispatchRaysIndex().xy] = Vec4(col, 0.0);
 }
-#endif // ANKI_RAY_GEN_SHADER
-
-// ===========================================================================
-// Miss                                                                      =
-// ===========================================================================
-#if ANKI_MISS_SHADER
-[shader("miss")] void main(inout RtMaterialFetchRayPayload payload)
-{
-	payload.m_diffuseColor = 0.0;
-	payload.m_worldNormal = 0.0;
-	payload.m_emission = Vec3(0.0, 0.0, 0.5); // TODO
-	payload.m_rayT = -1.0;
-}
-#endif // ANKI_MISS_SHADER

+ 1 - 1
AnKi/Shaders/SH.hlsl

@@ -59,7 +59,7 @@ vector<T, 3> evaluateSH(SHL1<T> sh, vector<T, 3> direction)
 {
 	vector<T, 3> res = T(0);
 
-	if(true)
+	if(false)
 	{
 		// L0
 		res += sh.m_c[0];

+ 1 - 1
Samples/Common/SampleApp.cpp

@@ -80,7 +80,7 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::kO) == 1)
 	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "ResolvedShadows") ? "" : "ResolvedShadows");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "RtMaterialFetchDbg") ? "" : "RtMaterialFetchDbg");
 	}
 
 	if(in.getKey(KeyCode::kP) == 1)

+ 4 - 8
Sandbox/Main.cpp

@@ -338,7 +338,9 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::kY) == 1)
 	{
-		g_shadowMappingPcssCVar = !g_shadowMappingPcssCVar;
+		renderer.setCurrentDebugRenderTarget(
+			(renderer.getCurrentDebugRenderTarget() == "IndirectDiffuseClipmapsTest") ? "" : "IndirectDiffuseClipmapsTest");
+		// g_shadowMappingPcssCVar = !g_shadowMappingPcssCVar;
 	}
 
 	if(in.getKey(KeyCode::kU) == 1)
@@ -353,13 +355,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::kO) == 1)
 	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "ResolvedShadows") ? "" : "ResolvedShadows");
-	}
-
-	if(in.getKey(KeyCode::kH) == 1)
-	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "MotionVectorsHistoryLength") ? ""
-																													  : "MotionVectorsHistoryLength");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "RtMaterialFetchDbg") ? "" : "RtMaterialFetchDbg");
 	}
 
 	/*if(in.getKey(KeyCode::J) == 1)