Browse Source

Fixing a bug in spot lights. Add LODing on shadows

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
e95f7e7096
3 changed files with 64 additions and 22 deletions
  1. 2 0
      src/anki/core/Config.cpp
  2. 59 9
      src/anki/renderer/ShadowMapping.cpp
  3. 3 13
      src/anki/renderer/ShadowMapping.h

+ 2 - 0
src/anki/core/Config.cpp

@@ -29,6 +29,8 @@ Config::Config()
 	newOption("r.shadowMapping.tileCountPerRowOrColumn", 16);
 	newOption("r.shadowMapping.scratchTileCountX", 4 * 5);
 	newOption("r.shadowMapping.scratchTileCountY", 4);
+	newOption("r.shadowMapping.lightLodDistance0", 10.0);
+	newOption("r.shadowMapping.lightLodDistance1", 20.0);
 
 	newOption("r.lensFlare.maxSpritesPerFlare", 8);
 	newOption("r.lensFlare.maxFlares", 16);

+ 59 - 9
src/anki/renderer/ShadowMapping.cpp

@@ -126,6 +126,9 @@ Error ShadowMapping::initInternal(const ConfigSet& cfg)
 	ANKI_CHECK(initScratch(cfg));
 	ANKI_CHECK(initEsm(cfg));
 
+	m_lodDistances[0] = cfg.getNumber("r.shadowMapping.lightLodDistance0");
+	m_lodDistances[1] = cfg.getNumber("r.shadowMapping.lightLodDistance1");
+
 	return Error::NONE;
 }
 
@@ -217,7 +220,12 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 			pass.setFramebufferInfo(m_scratchFbDescr, {}, m_scratchRt, minx, miny, width, height);
 			ANKI_ASSERT(
 				threadCountForScratchPass && threadCountForScratchPass <= m_r->getThreadHive().getThreadCount());
-			pass.setWork(runShadowmappingCallback, this, threadCountForScratchPass);
+			pass.setWork(
+				[](RenderPassWorkContext& rgraphCtx) {
+					static_cast<ShadowMapping*>(rgraphCtx.m_userData)->runShadowMapping(rgraphCtx);
+				},
+				this,
+				threadCountForScratchPass);
 
 			TextureSubresourceInfo subresource = TextureSubresourceInfo(DepthStencilAspectBit::DEPTH);
 			pass.newDependency({m_scratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE, subresource});
@@ -229,7 +237,12 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 
 			m_esmRt = rgraph.importRenderTarget(m_esmAtlas, TextureUsageBit::SAMPLED_FRAGMENT);
 			pass.setFramebufferInfo(m_esmFbDescr, {{m_esmRt}}, {});
-			pass.setWork(runEsmCallback, this, 0);
+			pass.setWork(
+				[](RenderPassWorkContext& rgraphCtx) {
+					static_cast<ShadowMapping*>(rgraphCtx.m_userData)->runEsm(rgraphCtx);
+				},
+				this,
+				0);
 
 			pass.newDependency(
 				{m_scratchRt, TextureUsageBit::SAMPLED_FRAGMENT, TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
@@ -243,22 +256,59 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 	}
 }
 
-Mat4 ShadowMapping::createSpotLightTextureMatrix(const Viewport& viewport)
+Mat4 ShadowMapping::createSpotLightTextureMatrix(const Viewport& viewport) const
 {
-	return Mat4(
-		viewport[2], 0.0, 0.0, viewport[0], 0.0, viewport[3], 0.0, viewport[1], 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
+	const F32 atlasSize = m_esmTileResolution * m_esmTileCountBothAxis;
+	const Vec2 uv(F32(viewport[0]) / atlasSize, F32(viewport[1]) / atlasSize);
+	ANKI_ASSERT(uv >= Vec2(0.0f) && uv <= Vec2(1.0f));
+
+	ANKI_ASSERT(viewport[2] == viewport[3]);
+	const F32 sizeTextureSpace = F32(viewport[2]) / atlasSize;
+
+	return Mat4(sizeTextureSpace,
+		0.0f,
+		0.0f,
+		uv.x(),
+		0.0f,
+		sizeTextureSpace,
+		0.0f,
+		uv.y(),
+		0.0f,
+		0.0f,
+		1.0f,
+		0.0f,
+		0.0f,
+		0.0f,
+		0.0f,
+		1.0f);
 }
 
 U ShadowMapping::choseLod(const Vec4& cameraOrigin, const PointLightQueueElement& light) const
 {
-	// TODO
-	return 0;
+	const F32 distFromTheCamera = (cameraOrigin - light.m_worldPosition.xyz0()).getLength() - light.m_radius;
+	if(distFromTheCamera < m_lodDistances[0])
+	{
+		ANKI_ASSERT(m_pointLightsMaxLod == 1);
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
 }
 
 U ShadowMapping::choseLod(const Vec4& cameraOrigin, const SpotLightQueueElement& light) const
 {
-	// TODO
-	return 1;
+	const Vec4 lightPos = light.m_worldTransform.getTranslationPart().xyz0();
+	const F32 distFromTheCamera = (cameraOrigin - lightPos).getLength() - light.m_distance;
+	if(distFromTheCamera < m_lodDistances[0])
+	{
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
 }
 
 TileAllocatorResult ShadowMapping::allocateTilesAndScratchTiles(U64 lightUuid,

+ 3 - 13
src/anki/renderer/ShadowMapping.h

@@ -67,13 +67,7 @@ private:
 
 	ANKI_USE_RESULT Error initEsm(const ConfigSet& cfg);
 
-	static Mat4 createSpotLightTextureMatrix(const Viewport& viewport);
-
-	/// A RenderPassWorkCallback for ESM
-	static void runEsmCallback(RenderPassWorkContext& rgraphCtx)
-	{
-		scast<ShadowMapping*>(rgraphCtx.m_userData)->runEsm(rgraphCtx);
-	}
+	inline Mat4 createSpotLightTextureMatrix(const Viewport& viewport) const;
 
 	void runEsm(RenderPassWorkContext& rgraphCtx);
 	/// @}
@@ -99,12 +93,6 @@ private:
 
 	ANKI_USE_RESULT Error initScratch(const ConfigSet& cfg);
 
-	/// A RenderPassWorkCallback for shadow passes.
-	static void runShadowmappingCallback(RenderPassWorkContext& rgraphCtx)
-	{
-		scast<ShadowMapping*>(rgraphCtx.m_userData)->runShadowMapping(rgraphCtx);
-	}
-
 	void runShadowMapping(RenderPassWorkContext& rgraphCtx);
 	/// @}
 
@@ -114,6 +102,8 @@ private:
 	static const U m_lodCount = 3;
 	static const U m_pointLightsMaxLod = 1;
 
+	Array<F32, m_lodCount - 1> m_lodDistances;
+
 	/// Find the lod of the light
 	U choseLod(const Vec4& cameraOrigin, const PointLightQueueElement& light) const;
 	/// Find the lod of the light