瀏覽代碼

Merge reflections and light shading into one pass

Panagiotis Christopoulos Charitos 7 年之前
父節點
當前提交
11e7b8e051

+ 75 - 1
shaders/LightShading.glslp

@@ -7,6 +7,7 @@
 #pragma anki input const U32 CLUSTER_COUNT_Y
 #pragma anki input const U32 CLUSTER_COUNT_Y
 #pragma anki input const U32 CLUSTER_COUNT_Z
 #pragma anki input const U32 CLUSTER_COUNT_Z
 #pragma anki input const U32 CLUSTER_COUNT
 #pragma anki input const U32 CLUSTER_COUNT
+#pragma anki input const U32 IR_MIPMAP_COUNT
 
 
 #pragma anki start vert
 #pragma anki start vert
 #include <shaders/Common.glsl>
 #include <shaders/Common.glsl>
@@ -37,7 +38,8 @@ void main()
 #define LIGHT_SET 0
 #define LIGHT_SET 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_UBO_BINDING 0
 #define LIGHT_UBO_BINDING 0
-#define LIGHT_TEX_BINDING 4
+#define LIGHT_TEX_BINDING 5
+#define LIGHT_INDIRECT
 #define LIGHT_LIGHTS
 #define LIGHT_LIGHTS
 #define LIGHT_COMMON_UNIS
 #define LIGHT_COMMON_UNIS
 #include <shaders/ClusterLightCommon.glsl>
 #include <shaders/ClusterLightCommon.glsl>
@@ -46,6 +48,7 @@ layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_msRt0;
 layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_msRt1;
 layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_msRt1;
 layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_msRt2;
 layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_msRt2;
 layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_msDepthRt;
 layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_msDepthRt;
+layout(ANKI_TEX_BINDING(0, 4)) uniform sampler2D u_ssrRt;
 
 
 layout(location = 0) in Vec2 in_uv;
 layout(location = 0) in Vec2 in_uv;
 layout(location = 1) in Vec2 in_clusterIJ;
 layout(location = 1) in Vec2 in_clusterIJ;
@@ -54,6 +57,53 @@ layout(location = 0) out Vec3 out_color;
 
 
 const F32 SUBSURFACE_MIN = 0.05;
 const F32 SUBSURFACE_MIN = 0.05;
 
 
+// Note: All calculations in world space
+void readReflectionsAndIrradianceFromProbes(U32 idxOffset,
+	Vec3 worldPos,
+	Vec3 normal,
+	Vec3 viewDir,
+	F32 roughness,
+	out Vec3 specIndirect,
+	out Vec3 diffIndirect)
+{
+	specIndirect = Vec3(0.0);
+	diffIndirect = Vec3(0.0);
+
+	Vec3 reflDir = reflect(-viewDir, normal);
+	F32 reflLod = F32(IR_MIPMAP_COUNT - 1u) * roughness;
+	F32 totalBlendWeight = EPSILON;
+
+	// Check proxy
+	U32 count = u_lightIndices[idxOffset++];
+	U32 idxOffsetEnd = idxOffset + count;
+	ANKI_LOOP while(idxOffset < idxOffsetEnd)
+	{
+		ReflectionProbe probe = u_reflectionProbes[u_lightIndices[idxOffset++]];
+		Vec3 aabbMin = probe.m_aabbMinPad1.xyz;
+		Vec3 aabbMax = probe.m_aabbMaxPad1.xyz;
+		Vec3 probeOrigin = probe.m_positionCubemapIndex.xyz;
+		F32 cubemapIndex = probe.m_positionCubemapIndex.w;
+
+		// Compute blend weight
+		F32 blendWeight = computeProbeBlendWeight(worldPos, aabbMin, aabbMax, 0.2);
+		totalBlendWeight += blendWeight;
+
+		// Sample reflections
+		Vec3 cubeUv = intersectProbe(worldPos, reflDir, aabbMin, aabbMax, probeOrigin);
+		Vec3 c = textureLod(u_reflectionsTex, Vec4(cubeUv, cubemapIndex), reflLod).rgb;
+		specIndirect += c * blendWeight;
+
+		// Sample irradiance
+		cubeUv = intersectProbe(worldPos, normal, aabbMin, aabbMax, probeOrigin);
+		c = textureLod(u_irradianceTex, Vec4(cubeUv, cubemapIndex), 0.0).rgb;
+		diffIndirect += c * blendWeight;
+	}
+
+	// Normalize the colors
+	specIndirect /= totalBlendWeight;
+	diffIndirect /= totalBlendWeight;
+}
+
 // Common code for lighting
 // Common code for lighting
 #define LIGHTING_COMMON_BRDF() \
 #define LIGHTING_COMMON_BRDF() \
 	Vec3 frag2Light = light.m_posRadius.xyz - worldPos; \
 	Vec3 frag2Light = light.m_posRadius.xyz - worldPos; \
@@ -138,6 +188,30 @@ void main()
 			(diffC + specC) * light.m_diffuseColorShadowmapId.rgb * (att * spot * max(gbuffer.m_subsurface, lambert));
 			(diffC + specC) * light.m_diffuseColorShadowmapId.rgb * (att * spot * max(gbuffer.m_subsurface, lambert));
 	}
 	}
 
 
+	// Refl & indirect
+	{
+		// Do the probe read
+		Vec3 envColor;
+		Vec3 indirectColor;
+		readReflectionsAndIrradianceFromProbes(
+			idxOffset, worldPos, gbuffer.m_normal, viewDir, gbuffer.m_roughness, envColor, indirectColor);
+
+		// Read the SSL result
+		Vec4 ssr = textureLod(u_ssrRt, in_uv, 0.0);
+
+		// Combine the SSR and probe reflections and write the result
+		Vec3 finalRefl = envColor * ssr.a + ssr.rgb;
+
+		// Compute env BRDF
+		F32 NoV = max(EPSILON, dot(gbuffer.m_normal, viewDir));
+		Vec3 env = envBRDF(gbuffer.m_specular, gbuffer.m_roughness, u_integrationLut, NoV);
+
+		out_color += indirectColor * gbuffer.m_diffuse + finalRefl * env;
+
+		// out_color += indirectColor * gbuffer.m_diffuse + ssr.rgb;
+		// out_color = ssr.rgb;
+	}
+
 #if 0
 #if 0
 	count = scount;
 	count = scount;
 	if(count == 0)
 	if(count == 0)

+ 0 - 160
shaders/LightShadingReflectionsAndIndirect.glslp

@@ -1,160 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-// Apply reflections and indirect lighting
-
-#pragma anki input const U32 CLUSTER_COUNT_X
-#pragma anki input const U32 CLUSTER_COUNT_Y
-#pragma anki input const U32 CLUSTER_COUNT_Z
-#pragma anki input const U32 IR_MIPMAP_COUNT
-
-#pragma anki start vert
-#include <shaders/Common.glsl>
-
-layout(location = 0) out Vec2 out_uv;
-layout(location = 1) out Vec2 out_clusterIJ;
-
-out gl_PerVertex
-{
-	Vec4 gl_Position;
-};
-
-void main()
-{
-	out_uv = Vec2(gl_VertexID & 1, gl_VertexID >> 1) * 2.0;
-	Vec2 pos = out_uv * 2.0 - 1.0;
-	gl_Position = Vec4(pos, 0.0, 1.0);
-
-	out_clusterIJ = Vec2(CLUSTER_COUNT_X, CLUSTER_COUNT_Y) * out_uv;
-}
-#pragma anki end
-
-#pragma anki start frag
-#include <shaders/Functions.glsl>
-#include <shaders/Pack.glsl>
-#include <shaders/glsl_cpp_common/Clusterer.h>
-
-#define LIGHT_SET 0
-#define LIGHT_SS_BINDING 0
-#define LIGHT_UBO_BINDING 0
-#define LIGHT_TEX_BINDING 5
-#define LIGHT_INDIRECT
-#define LIGHT_COMMON_UNIS
-#include <shaders/ClusterLightCommon.glsl>
-
-layout(location = 0) in Vec2 in_uv;
-layout(location = 1) in Vec2 in_clusterIJ;
-layout(location = 0) out Vec3 out_color;
-
-layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_gbufferRt0;
-layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_gbufferRt1;
-layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_gbufferRt2;
-layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_depthRt;
-layout(ANKI_TEX_BINDING(0, 4)) uniform sampler2D u_ssrRt;
-
-// Note: All calculations in world space
-void readReflectionsAndIrradianceFromProbes(U32 idxOffset,
-	Vec3 worldPos,
-	Vec3 normal,
-	Vec3 viewDir,
-	F32 roughness,
-	out Vec3 specIndirect,
-	out Vec3 diffIndirect)
-{
-	specIndirect = Vec3(0.0);
-	diffIndirect = Vec3(0.0);
-
-	Vec3 reflDir = reflect(viewDir, normal);
-
-	F32 reflLod = F32(IR_MIPMAP_COUNT - 1u) * roughness;
-
-	F32 totalBlendWeight = EPSILON;
-
-	// Check proxy
-	U32 count = u_lightIndices[idxOffset++];
-	ANKI_LOOP while(count-- != 0)
-	{
-		ReflectionProbe probe = u_reflectionProbes[u_lightIndices[idxOffset++]];
-		Vec3 aabbMin = probe.m_aabbMinPad1.xyz;
-		Vec3 aabbMax = probe.m_aabbMaxPad1.xyz;
-		Vec3 probeOrigin = probe.m_positionCubemapIndex.xyz;
-		F32 cubemapIndex = probe.m_positionCubemapIndex.w;
-
-		// Compute blend weight
-		F32 blendWeight = computeProbeBlendWeight(worldPos, aabbMin, aabbMax, 0.2);
-		totalBlendWeight += blendWeight;
-
-		// Sample reflections
-		Vec3 cubeUv = intersectProbe(worldPos, reflDir, aabbMin, aabbMax, probeOrigin);
-		Vec3 c = textureLod(u_reflectionsTex, Vec4(cubeUv, cubemapIndex), reflLod).rgb;
-		specIndirect += c * blendWeight;
-
-		// Sample irradiance
-		cubeUv = intersectProbe(worldPos, normal, aabbMin, aabbMax, probeOrigin);
-		c = textureLod(u_irradianceTex, Vec4(cubeUv, cubemapIndex), 0.0).rgb;
-		diffIndirect += c * blendWeight;
-	}
-
-	// Normalize the colors
-	specIndirect /= totalBlendWeight;
-	diffIndirect /= totalBlendWeight;
-}
-
-void main()
-{
-	Vec2 uv = in_uv;
-
-	// Compute world position
-	F32 depth = textureLod(u_depthRt, uv, 0.0).r;
-	Vec4 worldPos4 = u_invViewProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
-	Vec3 worldPos = worldPos4.xyz / worldPos4.w;
-	Vec3 viewDir = normalize(u_cameraPos - worldPos);
-
-	// Get first light index
-	U32 idxOffset;
-	{
-		U32 k = computeClusterK(u_clustererMagic, worldPos);
-		U32 clusterIdx =
-			k * (CLUSTER_COUNT_X * CLUSTER_COUNT_Y) + U32(in_clusterIJ.y) * CLUSTER_COUNT_X + U32(in_clusterIJ.x);
-
-		idxOffset = u_clusters[clusterIdx];
-	}
-
-	// Skip decals
-	U32 count = u_lightIndices[idxOffset++];
-	idxOffset += count;
-
-	// Skip point lights
-	count = u_lightIndices[idxOffset++];
-	idxOffset += count;
-
-	// Skip spot lights
-	count = u_lightIndices[idxOffset++];
-	idxOffset += count;
-
-	// Read gbuffer
-	GbufferInfo gbuffer;
-	readGBuffer(u_gbufferRt0, u_gbufferRt1, u_gbufferRt2, uv, 0.0, gbuffer);
-
-	// Do the probe read
-	Vec3 envColor;
-	Vec3 indirectColor;
-	readReflectionsAndIrradianceFromProbes(
-		idxOffset, worldPos, gbuffer.m_normal, viewDir, gbuffer.m_roughness, envColor, indirectColor);
-
-	// Read the SSL result
-	Vec4 ssr = textureLod(u_ssrRt, uv, 0.0);
-
-	// Combine the SSR and probe reflections and write the result
-	Vec3 finalRefl = envColor * (1.0 - ssr.a) + ssr.rgb;
-
-	// Compute env BRDF
-	F32 NoV = max(EPSILON, dot(gbuffer.m_normal, viewDir));
-	Vec3 env = envBRDF(gbuffer.m_specular, gbuffer.m_roughness, u_integrationLut, NoV);
-
-	// Compute the final color
-	out_color = indirectColor * gbuffer.m_diffuse + finalRefl * env;
-}
-#pragma anki end

+ 1 - 1
src/anki/gr/RenderGraph.cpp

@@ -17,7 +17,7 @@
 namespace anki
 namespace anki
 {
 {
 
 
-#define ANKI_DBG_RENDER_GRAPH 1
+#define ANKI_DBG_RENDER_GRAPH 0
 
 
 /// Contains some extra things for render targets.
 /// Contains some extra things for render targets.
 class RenderGraph::RT
 class RenderGraph::RT

+ 3 - 0
src/anki/renderer/Common.h

@@ -68,6 +68,9 @@ const U BLOOM_FRACTION = 4;
 /// Volumetric size is rendererSize/VOLUMETRIC_FRACTION.
 /// Volumetric size is rendererSize/VOLUMETRIC_FRACTION.
 const U VOLUMETRIC_FRACTION = 4;
 const U VOLUMETRIC_FRACTION = 4;
 
 
+/// SSR size is rendererSize/SSR_FRACTION.
+const U SSR_FRACTION = 2;
+
 /// Used to calculate the mipmap count of the HiZ map.
 /// Used to calculate the mipmap count of the HiZ map.
 const U HIERARCHICAL_Z_MIN_HEIGHT = 80;
 const U HIERARCHICAL_Z_MIN_HEIGHT = 80;
 
 

+ 15 - 43
src/anki/renderer/LightShading.cpp

@@ -71,11 +71,12 @@ Error LightShading::initInternal(const ConfigSet& config)
 	// Load shaders and programs
 	// Load shaders and programs
 	ANKI_CHECK(getResourceManager().loadResource("shaders/LightShading.glslp", m_prog));
 	ANKI_CHECK(getResourceManager().loadResource("shaders/LightShading.glslp", m_prog));
 
 
-	ShaderProgramResourceConstantValueInitList<4> consts(m_prog);
+	ShaderProgramResourceConstantValueInitList<5> consts(m_prog);
 	consts.add("CLUSTER_COUNT_X", U32(m_clusterCounts[0]))
 	consts.add("CLUSTER_COUNT_X", U32(m_clusterCounts[0]))
 		.add("CLUSTER_COUNT_Y", U32(m_clusterCounts[1]))
 		.add("CLUSTER_COUNT_Y", U32(m_clusterCounts[1]))
 		.add("CLUSTER_COUNT_Z", U32(m_clusterCounts[2]))
 		.add("CLUSTER_COUNT_Z", U32(m_clusterCounts[2]))
-		.add("CLUSTER_COUNT", U32(m_clusterCount));
+		.add("CLUSTER_COUNT", U32(m_clusterCount))
+		.add("IR_MIPMAP_COUNT", U32(m_r->getIndirect().getReflectionTextureMipmapCount()));
 
 
 	m_prog->getOrCreateVariant(consts.get(), m_progVariant);
 	m_prog->getOrCreateVariant(consts.get(), m_progVariant);
 
 
@@ -89,22 +90,6 @@ Error LightShading::initInternal(const ConfigSet& config)
 	m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
 	m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
 	m_fbDescr.bake();
 	m_fbDescr.bake();
 
 
-	// Refl & indirect
-	{
-		ANKI_CHECK(getResourceManager().loadResource(
-			"shaders/LightShadingReflectionsAndIndirect.glslp", m_reflAndIndirect.m_prog));
-
-		ShaderProgramResourceConstantValueInitList<4> consts(m_reflAndIndirect.m_prog);
-		consts.add("CLUSTER_COUNT_X", U32(m_clusterCounts[0]))
-			.add("CLUSTER_COUNT_Y", U32(m_clusterCounts[1]))
-			.add("CLUSTER_COUNT_Z", U32(m_clusterCounts[2]))
-			.add("IR_MIPMAP_COUNT", U32(m_r->getIndirect().getReflectionTextureMipmapCount()));
-
-		const ShaderProgramResourceVariant* variant;
-		m_reflAndIndirect.m_prog->getOrCreateVariant(consts.get(), variant);
-		m_reflAndIndirect.m_grProg = variant->getProgram();
-	}
-
 	// FS upscale
 	// FS upscale
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb64x64.ankitex", m_fs.m_noiseTex));
 		ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb64x64.ankitex", m_fs.m_noiseTex));
@@ -162,13 +147,24 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 			m_r->getGBuffer().getDepthRt(),
 			m_r->getGBuffer().getDepthRt(),
 			TextureSubresourceInfo(DepthStencilAspectBit::DEPTH),
 			TextureSubresourceInfo(DepthStencilAspectBit::DEPTH),
 			m_r->getNearestSampler());
 			m_r->getNearestSampler());
+		rgraphCtx.bindColorTextureAndSampler(0, 4, m_r->getSsr().getRt(), m_r->getLinearSampler());
 
 
-		rgraphCtx.bindColorTextureAndSampler(0, 4, m_r->getShadowMapping().getShadowmapRt(), m_r->getLinearSampler());
+		rgraphCtx.bindColorTextureAndSampler(0, 5, m_r->getShadowMapping().getShadowmapRt(), m_r->getLinearSampler());
+		rgraphCtx.bindColorTextureAndSampler(
+			0, 6, m_r->getIndirect().getReflectionRt(), m_r->getTrilinearRepeatSampler());
+		rgraphCtx.bindColorTextureAndSampler(
+			0, 7, m_r->getIndirect().getIrradianceRt(), m_r->getTrilinearRepeatSampler());
+		cmdb->bindTextureAndSampler(0,
+			8,
+			m_r->getIndirect().getIntegrationLut(),
+			m_r->getIndirect().getIntegrationLutSampler(),
+			TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 		// Bind uniforms
 		// Bind uniforms
 		bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
 		bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
 		bindUniforms(cmdb, 0, 1, rsrc.m_pointLightsToken);
 		bindUniforms(cmdb, 0, 1, rsrc.m_pointLightsToken);
 		bindUniforms(cmdb, 0, 2, rsrc.m_spotLightsToken);
 		bindUniforms(cmdb, 0, 2, rsrc.m_spotLightsToken);
+		bindUniforms(cmdb, 0, 3, rsrc.m_probesToken);
 
 
 		// Bind storage
 		// Bind storage
 		bindStorage(cmdb, 0, 0, rsrc.m_clustersToken);
 		bindStorage(cmdb, 0, 0, rsrc.m_clustersToken);
@@ -177,30 +173,6 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 		drawQuad(cmdb);
 		drawQuad(cmdb);
 	}
 	}
 
 
-	// Add the reflections & indirect
-	{
-		cmdb->bindShaderProgram(m_reflAndIndirect.m_grProg);
-
-		// Bind textures
-		rgraphCtx.bindColorTextureAndSampler(0, 4, m_r->getSsr().getRt(), m_r->getLinearSampler());
-		rgraphCtx.bindColorTextureAndSampler(
-			0, 5, m_r->getIndirect().getReflectionRt(), m_r->getTrilinearRepeatSampler());
-		rgraphCtx.bindColorTextureAndSampler(
-			0, 6, m_r->getIndirect().getIrradianceRt(), m_r->getTrilinearRepeatSampler());
-		cmdb->bindTextureAndSampler(0,
-			7,
-			m_r->getIndirect().getIntegrationLut(),
-			m_r->getIndirect().getIntegrationLutSampler(),
-			TextureUsageBit::SAMPLED_FRAGMENT);
-
-		// Bind uniforms
-		bindUniforms(cmdb, 0, 1, rsrc.m_probesToken);
-
-		// State & draw
-		cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
-		drawQuad(cmdb);
-	}
-
 	// Forward shading
 	// Forward shading
 	{
 	{
 		// Bind textures
 		// Bind textures

+ 0 - 7
src/anki/renderer/LightShading.h

@@ -70,13 +70,6 @@ private:
 	U32 m_maxLightIds;
 	U32 m_maxLightIds;
 	/// @}
 	/// @}
 
 
-	class
-	{
-	public:
-		ShaderProgramResourcePtr m_prog;
-		ShaderProgramPtr m_grProg;
-	} m_reflAndIndirect; ///< Apply reflections drawcall.
-
 	class
 	class
 	{
 	{
 	public:
 	public:

+ 4 - 3
src/anki/renderer/Ssr.cpp

@@ -31,8 +31,8 @@ Error Ssr::init(const ConfigSet& cfg)
 
 
 Error Ssr::initInternal(const ConfigSet& cfg)
 Error Ssr::initInternal(const ConfigSet& cfg)
 {
 {
-	U32 width = m_r->getWidth() / 2u;
-	U32 height = m_r->getHeight() / 2u;
+	U32 width = m_r->getWidth() / SSR_FRACTION;
+	U32 height = m_r->getHeight() / SSR_FRACTION;
 	ANKI_R_LOGI("Initializing SSR pass (%ux%u)", width, height);
 	ANKI_R_LOGI("Initializing SSR pass (%ux%u)", width, height);
 
 
 	// Create RTs
 	// Create RTs
@@ -104,7 +104,8 @@ void Ssr::run(RenderPassWorkContext& rgraphCtx)
 	unis->m_normalMat = Mat3x4(ctx.m_renderQueue->m_viewMatrix.getRotationPart());
 	unis->m_normalMat = Mat3x4(ctx.m_renderQueue->m_viewMatrix.getRotationPart());
 
 
 	// Dispatch
 	// Dispatch
-	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_r->getWidth() / 2u, m_r->getHeight() / 2u);
+	dispatchPPCompute(
+		cmdb, m_workgroupSize[0], m_workgroupSize[1], m_r->getWidth() / SSR_FRACTION, m_r->getHeight() / SSR_FRACTION);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki