Panagiotis Christopoulos Charitos 7 anni fa
parent
commit
a4aad86b63

+ 1 - 1
programs/DepthDownscale.ankiprog

@@ -29,7 +29,7 @@ http://www.anki3d.org/LICENSE
 #if COPY_TO_CLIENT
 struct PushConsts
 {
-	uvec2 textureSize;
+	uvec4 textureSize;
 };
 ANKI_PUSH_CONSTANTS(PushConsts, u_regs);
 

+ 30 - 20
programs/IrradianceSH.ankiprog

@@ -16,11 +16,12 @@ http://www.anki3d.org/LICENSE
 
 layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
 
-layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
+struct PushConsts
 {
-	vec4 u_layerPad3;
+	uvec4 layerPad3;
 };
-#define u_layer u_layerPad3.x
+ANKI_PUSH_CONSTANTS(PushConsts, u_regs);
+#define u_layer u_regs.layerPad3.x
 
 layout(ANKI_TEX_BINDING(0, 0)) uniform samplerCubeArray u_envTex;
 
@@ -32,10 +33,11 @@ layout(ANKI_TEX_BINDING(0, 0)) uniform samplerCubeArray u_envTex;
 
 layout(std140, ANKI_SS_BINDING(0, 0)) writeonly buffer _s0
 {
-	vec4 u_SHr;
-	vec4 u_SHg;
-	vec4 u_SHb;
+	SHCoefficients u_SH[];
 };
+#define u_SHr u_SH[u_layer * 3u + 0u]
+#define u_SHg u_SH[u_layer * 3u + 1u]
+#define u_SHb u_SH[u_layer * 3u + 2u]
 
 shared SHCoefficients s_scratch[3][WORKGROUP_SIZE.y * WORKGROUP_SIZE.x];
 
@@ -52,6 +54,19 @@ SHCoefficients computeSHCoeffiecients(vec3 dir)
 	return sh;
 }
 
+float areaElement(float x, float y)
+{
+	return atan(x * y, sqrt(x * x + y * y + 1.0));
+}
+
+float cubeCoordSolidAngle(vec2 norm)
+{
+	vec2 invSize = 1.0 / vec2(WORKGROUP_SIZE);
+	vec2 v0 = norm - invSize;
+	vec2 v1 = norm + invSize;
+	return areaElement(v0.x, v0.y) - areaElement(v0.x, v1.y) - areaElement(v1.x, v0.y) + areaElement(v1.x, v1.y);
+}
+
 // Resolve the cube faces
 void initPass()
 {
@@ -61,29 +76,24 @@ void initPass()
 	SHCoefficients SHg = SHCoefficients(0.0);
 	SHCoefficients SHb = SHCoefficients(0.0);
 
-	float weight = EPSILON;
-
 	ANKI_LOOP for(uint face = 0u; face < 6u; ++face)
 	{
-		vec3 direction = getCubemapDirection(ndc, face);
+		vec3 dir = getCubemapDirection(ndc, face);
 
-		SHCoefficients sh = computeSHCoeffiecients(direction);
-		
-		float lambert = max(0.0, dot(r, ri));
-		weight += lambert;
-
-		vec3 rgb = textureLod(u_envTex, vec4(direction, u_layer), 0.0).rgb;
-		rgb *= lambert;
+		SHCoefficients sh = computeSHCoeffiecients(dir);
+		vec3 rgb = textureLod(u_envTex, vec4(dir, 0.0), 0.0).rgb;
 
 		SHr += rgb.r * sh;
 		SHg += rgb.g * sh;
 		SHb += rgb.b * sh;
 	}
 
+	float solidAngle = cubeCoordSolidAngle(ndc);
 	uint idx = gl_LocalInvocationID.y * WORKGROUP_SIZE.x + gl_LocalInvocationID.x;
-	s_scratch[0][idx] = SHr / weight * PI;
-	s_scratch[1][idx] = SHg / weight * PI;
-	s_scratch[2][idx] = SHb / weight * PI;
+
+	s_scratch[0][idx] = SHr * solidAngle;
+	s_scratch[1][idx] = SHg * solidAngle;
+	s_scratch[2][idx] = SHb * solidAngle;
 
 	memoryBarrierShared();
 	barrier();
@@ -93,7 +103,7 @@ void initPass()
 void reducePasses()
 {
 	// Gather the results into one
-	for(uint s = WORKGROUP_SIZE / 2u; s > 0u; s >>= 1u)
+	ANKI_UNROLL for(uint s = (WORKGROUP_SIZE.x * WORKGROUP_SIZE.y) / 2u; s > 0u; s >>= 1u)
 	{
 		if(gl_LocalInvocationIndex < s)
 		{

+ 1 - 1
src/anki/renderer/DepthDownscale.cpp

@@ -191,7 +191,7 @@ void DepthDownscale::run(RenderPassWorkContext& rgraphCtx)
 
 	if(passIdx == m_passes.getSize() - 1)
 	{
-		UVec2 size(m_copyToBuff.m_lastMipWidth, m_copyToBuff.m_lastMipHeight);
+		UVec4 size(m_copyToBuff.m_lastMipWidth, m_copyToBuff.m_lastMipHeight, 0, 0);
 		cmdb->setPushConstants(&size, sizeof(size));
 
 		cmdb->bindStorageBuffer(0, 0, m_copyToBuff.m_buff, 0, m_copyToBuff.m_buff->getSize());

+ 47 - 0
src/anki/renderer/Indirect.cpp

@@ -211,6 +211,22 @@ Error Indirect::initIrradiance(const ConfigSet& config)
 		m_irradiance.m_grProg = variant->getProgram();
 	}
 
+	m_irradiance.m_shBuffer = getGrManager().newBuffer(BufferInitInfo(sizeof(Vec4) * 3 * m_cacheEntries.getSize(),
+		BufferUsageBit::STORAGE_COMPUTE_WRITE | BufferUsageBit::UNIFORM_FRAGMENT,
+		BufferMapAccessBit::NONE,
+		"SH Irrad"));
+
+	{
+		ANKI_CHECK(m_r->getResourceManager().loadResource("programs/IrradianceSH.ankiprog", m_irradiance.m_shProg));
+
+		ShaderProgramResourceConstantValueInitList<1> consts(m_irradiance.m_shProg);
+		consts.add("WORKGROUP_SIZE", UVec2(m_irradiance.m_tileSize, m_irradiance.m_tileSize));
+
+		const ShaderProgramResourceVariant* variant;
+		m_irradiance.m_shProg->getOrCreateVariant(consts.get(), variant);
+		m_irradiance.m_grShProg = variant->getProgram();
+	}
+
 	return Error::NONE;
 }
 
@@ -561,6 +577,22 @@ void Indirect::runIrradiance(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 	drawQuad(cmdb);
 }
 
+void Indirect::runIrradianceSH(RenderPassWorkContext& rgraphCtx)
+{
+	const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
+
+	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
+
+	cmdb->bindShaderProgram(m_irradiance.m_grShProg);
+
+	cmdb->bindStorageBuffer(0, 0, m_irradiance.m_shBuffer, 0, m_irradiance.m_shBuffer->getSize());
+
+	UVec4 uniforms(cacheEntryIdx);
+	cmdb->setPushConstants(&uniforms, sizeof(uniforms));
+
+	cmdb->dispatchCompute(1, 1, 1);
+}
+
 void Indirect::populateRenderGraph(RenderingContext& rctx)
 {
 	ANKI_TRACE_SCOPED_EVENT(R_IR);
@@ -710,6 +742,21 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
 				pass.newProducer({m_ctx.m_irradianceRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
 			}
 		}
+
+		// Irradiance SH
+		{
+			ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Irr SH");
+
+			pass.setWork(runIrradianceSHCallback, this, 0);
+
+			TextureSubresourceInfo subresource;
+			subresource.m_firstFace = 0;
+			subresource.m_faceCount = 6;
+			subresource.m_firstMipmap = m_lightShading.m_cubeArr->getMipmapCount() - 1;
+			subresource.m_firstLayer = probeToUpdateCacheEntryIdx;
+			subresource.m_layerCount = 1;
+			pass.newConsumer({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE, subresource});
+		}
 	}
 	else
 	{

+ 11 - 0
src/anki/renderer/Indirect.h

@@ -97,6 +97,10 @@ private:
 
 		ShaderProgramResourcePtr m_prog;
 		ShaderProgramPtr m_grProg;
+
+		BufferPtr m_shBuffer;
+		ShaderProgramResourcePtr m_shProg;
+		ShaderProgramPtr m_grShProg;
 	} m_irradiance; ///< Irradiance.
 
 	class CacheEntry
@@ -146,6 +150,7 @@ private:
 	void runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
 	void runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
 	void runIrradiance(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
+	void runIrradianceSH(RenderPassWorkContext& rgraphCtx);
 	static void bindVertexIndexBuffers(MeshResourcePtr& mesh, CommandBufferPtr& cmdb, U32& indexCount);
 
 	// A RenderPassWorkCallback for G-buffer pass
@@ -178,6 +183,12 @@ private:
 		Indirect* const self = scast<Indirect*>(rgraphCtx.m_userData);
 		self->runIrradiance(faceIdx, rgraphCtx);
 	}
+
+	static void runIrradianceSHCallback(RenderPassWorkContext& rgraphCtx)
+	{
+		Indirect* const self = scast<Indirect*>(rgraphCtx.m_userData);
+		self->runIrradianceSH(rgraphCtx);
+	}
 };
 /// @}