Browse Source

Add probe reading in reflections

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
ddedfb372c

+ 3 - 12
programs/LightShading.ankiprog

@@ -77,14 +77,6 @@ const float SUBSURFACE_MIN = 0.05;
 	float att = computeAttenuationFactor(light.posRadius.w, frag2Light); \
 	float lambert = nol;
 
-void debugIncorrectColor(inout vec3 c)
-{
-	if(isnan(c.x) || isnan(c.y) || isnan(c.z) || isinf(c.x) || isinf(c.y) || isinf(c.z))
-	{
-		c = vec3(1.0, 0.0, 1.0);
-	}
-}
-
 // Compute the colors of a decal.
 void appendDecalColors(in Decal decal, in vec3 worldPos, inout vec3 diffuseColor, inout float roughness)
 {
@@ -144,7 +136,7 @@ void readIndirect(uint idxOffset, vec3 pos, vec3 r, vec3 n, float lod, out vec3
 
 void main()
 {
-	float depth = texture(u_msDepthRt, in_uv, 0.0).r;
+	float depth = textureLod(u_msDepthRt, in_uv, 0.0).r;
 	vec2 ndc = UV_TO_NDC(in_uv);
 
 	// Get world position
@@ -190,15 +182,14 @@ void main()
 	}
 
 	// Apply SSAO
-	float ssao = texture(u_ssaoTex, in_uv).r;
+	float ssao = textureLod(u_ssaoTex, in_uv, 0.0).r;
 	diffCol *= ssao;
 
 	// Ambient and emissive color
 	vec3 outC = diffCol * emission;
 
 	// Don't allow zero a2 because we may end up with division with zero
-	float a2 = roughness * 0.95 + 0.05;
-	a2 *= a2 * a2;
+	float a2 = computeRoughnesSquared(roughness);
 
 	// Point lights
 	vec3 viewDir = normalize(u_cameraPos - worldPos);

+ 124 - 35
programs/Reflections.ankiprog

@@ -17,11 +17,24 @@ http://www.anki3d.org/LICENSE
 				<input name="MAX_STEPS" type="uint" const="1"/>
 				<input name="LIGHT_BUFFER_MIP_COUNT" type="uint" const="1"/>
 				<input name="HIZ_MIP_COUNT" type="uint" const="1"/>
+				<input name="CLUSTER_COUNT_X" type="uint" const="1"/>
+				<input name="CLUSTER_COUNT_Y" type="uint" const="1"/>
+				<input name="CLUSTER_COUNT_Z" type="uint" const="1"/>
+				<input name="IR_MIPMAP_COUNT" type="uint" const="1"/>
 			</inputs>
 
 			<source><![CDATA[
 #include "shaders/Functions.glsl"
 #include "shaders/Pack.glsl"
+#include "shaders/Clusterer.glsl"
+
+#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"
 
 const ivec2 HIZ_SIZE = ivec2(FB_SIZE) >> 1;
 
@@ -31,30 +44,20 @@ layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_gbufferRt1;
 layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_gbufferRt2;
 layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_hizRt;
 layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_lightBufferRt;
+layout(ANKI_TEX_BINDING(0, 4)) uniform sampler2D u_depthRt;
 
-layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D u_out;
+layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D out_refl;
+layout(ANKI_IMAGE_BINDING(0, 1)) writeonly uniform image2D out_indirect;
 
-layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform u0_
-{
-	mat4 u_projMat;
-	mat4 u_invViewProjMat;
-	mat4 u_invProjMat;
-	mat4 u_viewMat;
-	vec4 u_camPosNear;
-	vec4 u_unprojParams;
-};
-
-#define u_camPos u_camPosNear.xyz
-#define u_near u_camPosNear.w
 #define u_normalMat mat3(u_viewMat)
 
-float unprojZ(float depth)
-{
-	return u_unprojParams.z / (u_unprojParams.w + depth);
-}
-
 vec4 returnSslrColor(vec3 raySample, float factor, float roughness)
 {
+	// Re-project previous frame
+	vec4 v4 = u_prevViewProjMatMulInvViewProjMat * vec4(UV_TO_NDC(raySample.xy), raySample.z, 1.0);
+	raySample.xy = NDC_TO_UV(v4.xy / v4.w);
+	raySample.xy = saturate(raySample.xy);
+
 	vec2 ndc = abs(UV_TO_NDC(raySample.xy));
 	float contribution = max(ndc.x, ndc.y);
 	contribution = 1.0 - contribution * contribution;
@@ -78,9 +81,9 @@ vec4 doSslr(vec3 r, vec3 n, vec3 viewPos, vec2 uv, float depth, float roughness)
 		return vec4(0.0);
 	}
 
-	// Compute an end point p1. This point is supposed to fall in front of the near plane. u_near is a bit bigger than
-	// the actual near.
-	vec3 p1 = p0 + r * (-p0.z - u_near);
+	// Compute an end point p1. This point is supposed to fall in front of the near plane. Add a small padding to near
+	// to avoid having p1 touching the near plane.
+	vec3 p1 = p0 + r * (-p0.z - (u_near + 0.1));
 
 	// Start point
 	vec3 start = vec3(uv, depth);
@@ -150,6 +153,50 @@ vec4 doSslr(vec3 r, vec3 n, vec3 viewPos, vec2 uv, float depth, float roughness)
 	}
 }
 
+// Note: All calculations in world space
+void doProbeReflections(
+	uint idxOffset, vec3 worldPos, vec3 normal, float roughness, out vec3 specIndirect, out vec3 diffIndirect)
+{
+	specIndirect = vec3(0.0);
+	diffIndirect = vec3(0.0);
+
+	vec3 viewDir = normalize(worldPos - u_cameraPos);
+	vec3 reflDir = reflect(viewDir, normal);
+
+	float reflLod = float(IR_MIPMAP_COUNT - 1u) * roughness;
+
+	// Check proxy
+	uint count = u_lightIndices[idxOffset++];
+	while(count-- != 0)
+	{
+		ReflectionProbe probe = u_reflectionProbes[u_lightIndices[idxOffset++]];
+
+		float R2 = probe.positionRadiusSq.w;
+		vec3 center = probe.positionRadiusSq.xyz;
+
+		// Get distance from the center of the probe
+		vec3 f = worldPos - center;
+
+		// Cubemap UV in view space
+		vec3 uv = computeCubemapVecAccurate(reflDir, R2, f);
+
+		// Read!
+		float cubemapIndex = probe.cubemapIndexPad3.x;
+		vec3 c = textureLod(u_reflectionsTex, vec4(uv, cubemapIndex), reflLod).rgb;
+
+		// Combine (lerp) with previous color
+		float d = dot(f, f);
+		float factor = d / R2;
+		factor = min(factor, 1.0);
+		specIndirect = mix(c, specIndirect, factor);
+
+		// Do the same for diffuse
+		uv = computeCubemapVecAccurate(normal, R2, f);
+		vec3 id = textureLod(u_irradianceTex, vec4(uv, cubemapIndex), 0.0).rgb;
+		diffIndirect = mix(id, diffIndirect, factor);
+	}
+}
+
 void main()
 {
 	uvec2 realInvocationId = gl_GlobalInvocationID.xy;
@@ -169,7 +216,7 @@ void main()
 		return;
 	}
 
-	vec2 uv = vec2(realInvocationId) / vec2(FB_SIZE);
+	vec2 uv = (vec2(realInvocationId) + 0.5) / vec2(FB_SIZE);
 
 	// Get normal
 	vec3 worldNormal;
@@ -180,22 +227,64 @@ void main()
 	vec3 specular;
 	readRoughnessSpecularFromGBuffer(u_gbufferRt1, uv, roughness, specular);
 
-	// Get view pos
-	float depth = textureLod(u_hizRt, uv, 0.0).r;
-	vec4 viewPos4 = u_invProjMat * vec4(UV_TO_NDC(uv), depth, 1.0);
-	vec3 viewPos = viewPos4.xyz / viewPos4.w;
+	// Get depth
+	float depth = textureLod(u_depthRt, uv, 0.0).r;
 
-	// Do SSLR
-	vec3 viewDir = normalize(viewPos);
-	vec3 viewNormal = u_normalMat * worldNormal;
-	vec3 reflVec = reflect(viewDir, viewNormal);
+	// Try SSR
+	float sslrFactor = 0.0;
+	vec3 sslrCol = vec3(0.0);
+	{
+		// Get view pos
+		vec4 viewPos4 = u_invProjMat * vec4(UV_TO_NDC(uv), depth, 1.0);
+		vec3 viewPos = viewPos4.xyz / viewPos4.w;
+
+		// Do SSLR
+		vec3 viewDir = normalize(viewPos);
+		vec3 viewNormal = u_normalMat * worldNormal;
+		vec3 reflVec = reflect(viewDir, viewNormal);
+
+		vec4 sslr = doSslr(reflVec, viewNormal, viewPos, uv, depth, roughness);
+		sslrFactor = sslr.w;
+		sslrCol = sslr.xyz;
+	}
+
+	// Read probes
+	vec3 probeCol;
+	vec3 indirectCol;
+	{
+		vec2 ndc = UV_TO_NDC(uv);
+
+		// Get world position
+		vec4 worldPos4 = u_invViewProjMat * vec4(ndc, depth, 1.0);
+		vec3 worldPos = worldPos4.xyz / worldPos4.w;
+
+		// Get first light index
+		uint clusterIdx = computeClusterIndex(u_clustererMagic, uv, worldPos, CLUSTER_COUNT_X, CLUSTER_COUNT_Y);
+		uint idxOffset = u_clusters[clusterIdx];
+
+		// Skip decals
+		uint count = u_lightIndices[idxOffset++];
+		idxOffset += count;
+		
+		// Skip point lights
+		count = u_lightIndices[idxOffset++];
+		idxOffset += count;
+
+		// Skip spot lights
+		count = u_lightIndices[idxOffset++];
+		idxOffset += count;
+
+		// Do the probe read
+		doProbeReflections(idxOffset, worldPos, worldNormal, roughness, probeCol, indirectCol);
+	}
 
-	vec4 sslr = doSslr(reflVec, viewNormal, viewPos, uv, depth, roughness);
-	float sslrFactor = sslr.w;
-	vec3 sslrCol = sslr.xyz;
+	// Combine the SSR and probe reflections and write the result
+	vec3 finalRefl = mix(probeCol, sslrCol, sslrFactor);
+	finalRefl = clamp(finalRefl, 0.0, FLT_MAX); // XXX
+	imageStore(out_refl, ivec2(realInvocationId), vec4(finalRefl, 0.0));
 
-	// Write it
-	imageStore(u_out, ivec2(realInvocationId), vec4(sslrCol * sslrFactor, 0.0));
+	// Write indirect diffuse
+	imageStore(out_indirect, ivec2(realInvocationId), vec4(indirectCol, 0.0));
 }
 			]]></source>
 		</shader>

+ 2 - 2
programs/VolumetricFog.ankiprog

@@ -46,7 +46,7 @@ layout(std140, ANKI_UBO_BINDING(0, 3), row_major) uniform ubo0_
 {
 	vec4 u_linearizeNoiseTexOffsetLayer;
 	vec4 u_fogParticleColorPad1;
-	mat4 u_prevViewProjMatMulInvViewProjMat;
+	mat4 u_prevViewProjMatMulInvViewProjMat2; // TODO Light common ubo has that. Maybe remove it
 };
 
 #define u_linearize readFirstInvocationARB(u_linearizeNoiseTexOffsetLayer.xy)
@@ -114,7 +114,7 @@ vec3 computeLightColor(vec3 fragPos, uint plightCount, uint plightIdx, uint slig
 
 vec3 readHistory(vec3 ndc, out float historyFeedback)
 {
-	vec4 v4 = u_prevViewProjMatMulInvViewProjMat * vec4(ndc, 1.0);
+	vec4 v4 = u_prevViewProjMatMulInvViewProjMat2 * vec4(ndc, 1.0);
 	v4.xy /= v4.w;
 
 	vec2 oldUv = NDC_TO_UV(v4.xy);

+ 23 - 10
shaders/ClusterLightCommon.glsl

@@ -12,15 +12,19 @@
 // Common uniforms between lights
 struct LightingUniforms
 {
-	vec4 projectionParams;
+	vec4 unprojectionParams;
 	vec4 rendererSizeTimeNear;
 	vec4 cameraPosFar;
 	ClustererMagicValues clustererMagicValues;
 	uvec4 tileCount;
+	mat4 viewMat;
 	mat4 invViewMat;
+	mat4 projMat;
+	mat4 invProjMat;
+	mat4 viewProjMat;
 	mat4 invViewProjMat;
 	mat4 prevViewProjMat;
-	mat4 invProjMat;
+	mat4 prevViewProjMatMulInvViewProjMat; // Used to re-project previous frames
 };
 
 // Point light
@@ -31,6 +35,7 @@ struct PointLight
 	vec4 specularColorRadius; // xyz: spec color, w: radius
 	uvec4 atlasTilesPad2; // x: encodes 6 uints with atlas tile indices in the x dir. y: same for y dir.
 };
+const uint POINT_LIGHT_SIZEOF = (4 * 4) * 4;
 
 // Spot light
 struct SpotLight
@@ -42,6 +47,7 @@ struct SpotLight
 	vec4 outerCosInnerCos;
 	mat4 texProjectionMat;
 };
+const uint SPOT_LIGHT_SIZEOF = (5 * 4 + 16) * 4;
 
 // Representation of a reflection probe
 struct ReflectionProbe
@@ -52,6 +58,7 @@ struct ReflectionProbe
 	// Slice in u_reflectionsTex vector.
 	vec4 cubemapIndexPad3;
 };
+const uint REFLECTION_PROBE_SIZEOF = (2 * 4) * 4;
 
 // Decal
 struct Decal
@@ -61,6 +68,7 @@ struct Decal
 	mat4 texProjectionMat;
 	vec4 blendFactors;
 };
+const uint DECAL_SIZEOF = (3 * 4 + 16) * 4;
 
 //
 // Common uniforms
@@ -69,24 +77,29 @@ struct Decal
 
 const uint _NEXT_UBO_BINDING = LIGHT_UBO_BINDING + 1;
 
-layout(ANKI_UBO_BINDING(LIGHT_SET, LIGHT_UBO_BINDING), std140, row_major) uniform u0_
+layout(ANKI_UBO_BINDING(LIGHT_SET, LIGHT_UBO_BINDING), std140, row_major) uniform lu0_
 {
 	LightingUniforms u_lightingUniforms;
 };
 
 #	define u_near readFirstInvocationARB(u_lightingUniforms.rendererSizeTimeNear.w)
 #	define u_far readFirstInvocationARB(u_lightingUniforms.cameraPosFar.w)
+#	define u_cameraPos readFirstInvocationARB(u_lightingUniforms.cameraPosFar.xyz)
 #	define u_clusterCountX readFirstInvocationARB(u_lightingUniforms.tileCount.x)
 #	define u_clusterCountY readFirstInvocationARB(u_lightingUniforms.tileCount.y)
 #	define u_clustererMagic u_lightingUniforms.clustererMagicValues
 #	define u_time readFirstInvocationARB(u_lightingUniforms.rendererSizeTimeNear.z)
-#	define u_unprojectionParams readFirstInvocationARB(u_lightingUniforms.projectionParams)
+#	define u_unprojectionParams readFirstInvocationARB(u_lightingUniforms.unprojectionParams)
+#	define u_rendererSize u_lightingUniforms.rendererSizeTimeNear.xy
+
+#	define u_viewMat u_lightingUniforms.viewMat
 #	define u_invViewMat u_lightingUniforms.invViewMat
+#	define u_projMat u_lightingUniforms.projMat
 #	define u_invProjMat u_lightingUniforms.invProjMat
+#	define u_viewProjMat u_lightingUniforms.viewProjMat
 #	define u_invViewProjMat u_lightingUniforms.invViewProjMat
 #	define u_prevViewProjMat u_lightingUniforms.prevViewProjMat
-#	define u_cameraPos u_lightingUniforms.cameraPosFar.xyz
-#	define u_rendererSize u_lightingUniforms.rendererSizeTimeNear.xy
+#	define u_prevViewProjMatMulInvViewProjMat u_lightingUniforms.prevViewProjMatMulInvViewProjMat
 
 #else
 const uint _NEXT_UBO_BINDING = LIGHT_UBO_BINDING;
@@ -101,12 +114,12 @@ const uint _NEXT_TEX_BINDING_2 = LIGHT_TEX_BINDING + 1;
 
 layout(ANKI_UBO_BINDING(LIGHT_SET, _NEXT_UBO_BINDING), std140) uniform u1_
 {
-	PointLight u_pointLights[UBO_MAX_SIZE / (3 * 4 * 4)];
+	PointLight u_pointLights[UBO_MAX_SIZE / POINT_LIGHT_SIZEOF];
 };
 
 layout(ANKI_UBO_BINDING(LIGHT_SET, _NEXT_UBO_BINDING + 1), std140, row_major) uniform u2_
 {
-	SpotLight u_spotLights[UBO_MAX_SIZE / (9 * 4 * 4)];
+	SpotLight u_spotLights[UBO_MAX_SIZE / SPOT_LIGHT_SIZEOF];
 };
 
 layout(ANKI_TEX_BINDING(LIGHT_SET, LIGHT_TEX_BINDING + 0)) uniform highp sampler2D u_shadowTex;
@@ -124,7 +137,7 @@ const uint _NEXT_TEX_BINDING_3 = _NEXT_TEX_BINDING_2 + 3;
 
 layout(std140, row_major, ANKI_UBO_BINDING(LIGHT_SET, _NEXT_UBO_BINDING_2)) uniform u3_
 {
-	ReflectionProbe u_reflectionProbes[UBO_MAX_SIZE / (2 * 4 * 4)];
+	ReflectionProbe u_reflectionProbes[UBO_MAX_SIZE / REFLECTION_PROBE_SIZEOF];
 };
 
 layout(ANKI_TEX_BINDING(LIGHT_SET, _NEXT_TEX_BINDING_2 + 0)) uniform samplerCubeArray u_reflectionsTex;
@@ -141,7 +154,7 @@ const uint _NEXT_TEX_BINDING_3 = _NEXT_TEX_BINDING_2;
 #if defined(LIGHT_DECALS)
 layout(std140, row_major, ANKI_UBO_BINDING(LIGHT_SET, _NEXT_UBO_BINDING_3)) uniform u4_
 {
-	Decal u_decals[UBO_MAX_SIZE / ((4 + 16) * 4)];
+	Decal u_decals[UBO_MAX_SIZE / DECAL_SIZEOF];
 };
 
 layout(ANKI_TEX_BINDING(LIGHT_SET, _NEXT_TEX_BINDING_3 + 0)) uniform sampler2D u_diffDecalTex;

+ 7 - 0
shaders/Functions.glsl

@@ -309,6 +309,7 @@ vec3 readErosion(sampler2D tex, vec2 uv)
 	return minValue;
 }
 
+// 5 color heatmap from a factor.
 vec3 heatmap(float factor)
 {
 	float intPart;
@@ -331,4 +332,10 @@ vec3 heatmap(float factor)
 		return mix(vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0), fractional);
 	}
 }
+
+bool incorrectColor(vec3 c)
+{
+	return isnan(c.x) || isnan(c.y) || isnan(c.z) || isinf(c.x) || isinf(c.y) || isinf(c.z);
+}
+
 #endif

+ 7 - 0
shaders/LightFunctions.glsl

@@ -163,4 +163,11 @@ vec3 computeCubemapVecCheap(in vec3 r, in float R2, in vec3 f)
 	return r;
 }
 
+float computeRoughnesSquared(float roughness)
+{
+	float a2 = roughness * 0.95 + 0.05;
+	a2 *= a2 * a2;
+	return a2;
+}
+
 #endif

+ 4 - 0
src/anki/gr/CommandBuffer.h

@@ -166,6 +166,7 @@ public:
 	void setFillMode(FillMode mode);
 
 	/// Set cull mode.
+	/// By default it's FaceSelectionBit::BACK.
 	void setCullMode(FaceSelectionBit mode);
 
 	/// Set depth offset and units. Set zeros to both to disable it.
@@ -203,6 +204,8 @@ public:
 	void setColorChannelWriteMask(U32 attachment, ColorBit mask);
 
 	/// Set blend factors seperate.
+	/// By default the values of srcRgb, dstRgb, srcA and dstA are BlendFactor::ONE, BlendFactor::ONE,
+	/// BlendFactor::ZERO, BlendFactor::ZERO respectively.
 	void setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA);
 
 	/// Set blend factors.
@@ -212,6 +215,7 @@ public:
 	}
 
 	/// Set the blend operation seperate.
+	/// By default the values of funcRgb and funcA are BlendOperation::ADD, BlendOperation::ADD respectively.
 	void setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA);
 
 	/// Set the blend operation.

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

@@ -63,7 +63,7 @@ Error DownscaleBlur::initInternal(const ConfigSet&)
 void DownscaleBlur::importRenderTargets(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
-	m_runCtx.m_rt = rgraph.importRenderTarget("Down/Blur", m_rtTex, TextureUsageBit::NONE);
+	m_runCtx.m_rt = rgraph.importRenderTarget("Down/Blur", m_rtTex, TextureUsageBit::SAMPLED_COMPUTE);
 }
 
 void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)

+ 2 - 2
src/anki/renderer/LightBin.cpp

@@ -136,8 +136,8 @@ public:
 
 	Bool operator<(const ClusterProbeIndex& b) const
 	{
-		ANKI_ASSERT(m_probeRadius > 0.0 && b.m_probeRadius > 0.0);
-		return m_probeRadius < b.m_probeRadius;
+		ANKI_ASSERT(m_probeRadius > 0 && b.m_probeRadius > 0);
+		return (m_probeRadius != b.m_probeRadius) ? (m_probeRadius > b.m_probeRadius) : (m_index < b.m_index);
 	}
 
 private:

+ 22 - 9
src/anki/renderer/LightShading.cpp

@@ -13,6 +13,7 @@
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/ForwardShading.h>
 #include <anki/renderer/DepthDownscale.h>
+#include <anki/renderer/Reflections.h>
 #include <anki/misc/ConfigSet.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/collision/Functions.h>
@@ -23,15 +24,19 @@ namespace anki
 /// @note Should match the shader
 struct ShaderCommonUniforms
 {
-	Vec4 m_projectionParams;
+	Vec4 m_unprojectionParams;
 	Vec4 m_rendererSizeTimeNear;
 	Vec4 m_cameraPosFar;
 	ClustererShaderMagicValues m_clustererMagicValues;
 	UVec4 m_tileCount;
+	Mat4 m_viewMat;
 	Mat4 m_invViewMat;
+	Mat4 m_projMat;
+	Mat4 m_invProjMat;
+	Mat4 m_viewProjMat;
 	Mat4 m_invViewProjMat;
 	Mat4 m_prevViewProjMat;
-	Mat4 m_invProjMat;
+	Mat4 m_prevViewProjMatMulInvViewProjMat;
 };
 
 LightShading::LightShading(Renderer* r)
@@ -184,23 +189,31 @@ void LightShading::updateCommonBlock(RenderingContext& ctx)
 		sizeof(ShaderCommonUniforms), m_runCtx.m_resources.m_commonUniformsToken);
 
 	// Start writing
-	blk->m_projectionParams = ctx.m_unprojParams;
-
-	blk->m_invViewMat = ctx.m_renderQueue->m_viewMatrix.getInverse();
+	blk->m_unprojectionParams = ctx.m_unprojParams;
 
 	blk->m_rendererSizeTimeNear =
 		Vec4(m_r->getWidth(), m_r->getHeight(), HighRezTimer::getCurrentTime(), ctx.m_renderQueue->m_cameraNear);
 
 	blk->m_tileCount = UVec4(m_clusterCounts[0], m_clusterCounts[1], m_clusterCounts[2], m_clusterCount);
 
-	blk->m_invViewProjMat = ctx.m_viewProjMatJitter.getInverse();
-	blk->m_prevViewProjMat = ctx.m_prevViewProjMat;
-	blk->m_invProjMat = ctx.m_projMatJitter.getInverse();
-
 	blk->m_cameraPosFar =
 		Vec4(ctx.m_renderQueue->m_cameraTransform.getTranslationPart().xyz(), ctx.m_renderQueue->m_cameraFar);
 
 	blk->m_clustererMagicValues = m_lightBin->getClusterer().getShaderMagicValues();
+
+	// Matrices
+	blk->m_viewMat = ctx.m_renderQueue->m_viewMatrix;
+	blk->m_invViewMat = ctx.m_renderQueue->m_viewMatrix.getInverse();
+
+	blk->m_projMat = ctx.m_projMatJitter;
+	blk->m_invProjMat = ctx.m_projMatJitter.getInverse();
+
+	blk->m_viewProjMat = ctx.m_viewProjMatJitter;
+	blk->m_invViewProjMat = ctx.m_viewProjMatJitter.getInverse();
+
+	blk->m_prevViewProjMat = ctx.m_prevViewProjMat;
+
+	blk->m_prevViewProjMatMulInvViewProjMat = ctx.m_prevViewProjMat * ctx.m_viewProjMatJitter.getInverse();
 }
 
 void LightShading::populateRenderGraph(RenderingContext& ctx)

+ 48 - 34
src/anki/renderer/Reflections.cpp

@@ -6,9 +6,12 @@
 #include <anki/renderer/Reflections.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/GBuffer.h>
+#include <anki/renderer/Indirect.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/RenderQueue.h>
+#include <anki/renderer/LightShading.h>
+#include <anki/misc/ConfigSet.h>
 
 namespace anki
 {
@@ -33,24 +36,31 @@ Error Reflections::initInternal(const ConfigSet& cfg)
 	U32 height = m_r->getHeight();
 	ANKI_R_LOGI("Initializing reflection pass (%ux%u)", width, height);
 
-	// Create RT descr
-	m_rtDescr = m_r->create2DRenderTargetDescription(width,
+	// Create RTs
+	TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(width,
 		height,
 		LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::IMAGE_COMPUTE_WRITE
 			| TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-		"Refl");
-	m_rtDescr.bake();
+		"Refl_");
+	texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
+
+	m_reflTex = m_r->createAndClearRenderTarget(texinit);
+	m_irradianceTex = m_r->createAndClearRenderTarget(texinit);
 
 	// Create shader
 	ANKI_CHECK(getResourceManager().loadResource("programs/Reflections.ankiprog", m_prog));
 
-	ShaderProgramResourceConstantValueInitList<5> consts(m_prog);
+	ShaderProgramResourceConstantValueInitList<9> consts(m_prog);
 	consts.add("FB_SIZE", UVec2(width, height));
 	consts.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
 	consts.add("MAX_STEPS", U32(64));
 	consts.add("LIGHT_BUFFER_MIP_COUNT", U32(m_r->getDownscaleBlur().getMipmapCount()));
 	consts.add("HIZ_MIP_COUNT", U32(HIERARCHICAL_Z_MIPMAP_COUNT));
+	consts.add("CLUSTER_COUNT_X", U32(cfg.getNumber("r.clusterSizeX")));
+	consts.add("CLUSTER_COUNT_Y", U32(cfg.getNumber("r.clusterSizeY")));
+	consts.add("CLUSTER_COUNT_Z", U32(cfg.getNumber("r.clusterSizeZ")));
+	consts.add("IR_MIPMAP_COUNT", U32(m_r->getIndirect().getReflectionTextureMipmapCount()));
 
 	ShaderProgramResourceMutationInitList<1> mutations(m_prog);
 	mutations.add("VARIANT", 0);
@@ -73,55 +83,59 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 	m_runCtx.m_ctx = &ctx;
 
-	// Create RT
-	m_runCtx.m_rt = rgraph.newRenderTarget(m_rtDescr);
+	// Create RTs
+	m_runCtx.m_reflRt = rgraph.importRenderTarget("Refl", m_reflTex, TextureUsageBit::SAMPLED_FRAGMENT);
+	m_runCtx.m_irradianceRt = rgraph.importRenderTarget("ReflIrr", m_irradianceTex, TextureUsageBit::SAMPLED_FRAGMENT);
 
 	// Create pass
 	ComputeRenderPassDescription& rpass = ctx.m_renderGraphDescr.newComputeRenderPass("Refl");
 	rpass.setWork(runCallback, this, 0);
 
-	rpass.newConsumer({m_runCtx.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
+	rpass.newConsumer({m_runCtx.m_reflRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
+	rpass.newConsumer({m_runCtx.m_irradianceRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
 	rpass.newConsumer({m_r->getGBuffer().getColorRt(1), TextureUsageBit::SAMPLED_COMPUTE});
 	rpass.newConsumer({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE});
+	rpass.newConsumer({m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_COMPUTE});
 	rpass.newConsumer({m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_COMPUTE});
 	rpass.newConsumer({m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
+	rpass.newConsumer({m_r->getIndirect().getReflectionRt(), TextureUsageBit::SAMPLED_COMPUTE});
+	rpass.newConsumer({m_r->getIndirect().getIrradianceRt(), TextureUsageBit::SAMPLED_COMPUTE});
 
-	rpass.newProducer({m_runCtx.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
+	rpass.newProducer({m_runCtx.m_reflRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
+	rpass.newProducer({m_runCtx.m_irradianceRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
 }
 
 void Reflections::run(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
-
-	struct Unis
-	{
-		Mat4 m_projMat;
-		Mat4 m_invViewProjMat;
-		Mat4 m_invProjMat;
-		Mat4 m_viewMat;
-		Vec4 m_camPosNear;
-		Vec4 m_unprojParams;
-	};
-
-	Unis* unis = allocateAndBindUniforms<Unis*>(sizeof(Unis), cmdb, 0, 0);
-	unis->m_projMat = m_runCtx.m_ctx->m_projMatJitter;
-	unis->m_invViewProjMat = m_runCtx.m_ctx->m_viewProjMatJitter.getInverse();
-	unis->m_invProjMat = m_runCtx.m_ctx->m_projMatJitter.getInverse();
-	unis->m_viewMat = m_runCtx.m_ctx->m_renderQueue->m_viewMatrix;
-	unis->m_camPosNear = Vec4(m_runCtx.m_ctx->m_renderQueue->m_cameraTransform.getTranslationPart().xyz(),
-		m_runCtx.m_ctx->m_renderQueue->m_cameraNear + 0.1f);
-
-	unis->m_unprojParams = m_runCtx.m_ctx->m_unprojParams;
+	cmdb->bindShaderProgram(m_grProg[m_r->getFrameCount() & 1]);
 
 	rgraphCtx.bindColorTextureAndSampler(0, 0, m_r->getGBuffer().getColorRt(1), m_r->getNearestSampler());
 	rgraphCtx.bindColorTextureAndSampler(0, 1, m_r->getGBuffer().getColorRt(2), m_r->getNearestSampler());
 	rgraphCtx.bindColorTextureAndSampler(0, 2, m_r->getDepthDownscale().getHiZRt(), m_r->getNearestNearestSampler());
 	rgraphCtx.bindColorTextureAndSampler(0, 3, m_r->getDownscaleBlur().getRt(), m_r->getTrilinearRepeatSampler());
-
-	rgraphCtx.bindImage(0, 0, m_runCtx.m_rt, TextureSubresourceInfo());
-
-	cmdb->bindShaderProgram(m_grProg[m_r->getFrameCount() & 1]);
-
+	rgraphCtx.bindTextureAndSampler(0,
+		4,
+		m_r->getGBuffer().getDepthRt(),
+		TextureSubresourceInfo(DepthStencilAspectBit::DEPTH),
+		m_r->getNearestSampler());
+
+	rgraphCtx.bindImage(0, 0, m_runCtx.m_reflRt, TextureSubresourceInfo());
+	rgraphCtx.bindImage(0, 1, m_runCtx.m_irradianceRt, TextureSubresourceInfo());
+
+	// Bind light shading stuff
+	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->getDummyTextureView(), m_r->getNearestSampler(), TextureUsageBit::SAMPLED_COMPUTE);
+
+	const LightShadingResources& rsrc = m_r->getLightShading().getResources();
+	bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
+	bindUniforms(cmdb, 0, 1, rsrc.m_probesToken);
+	bindStorage(cmdb, 0, 0, rsrc.m_clustersToken);
+	bindStorage(cmdb, 0, 1, rsrc.m_lightIndicesToken);
+
+	// Dispatch
 	const U sizeX = (m_r->getWidth() + m_workgroupSize[0] - 1) / m_workgroupSize[0];
 	const U sizeY = (m_r->getHeight() + m_workgroupSize[1] - 1) / m_workgroupSize[1];
 	cmdb->dispatchCompute(sizeX / 2, sizeY, 1);

+ 11 - 4
src/anki/renderer/Reflections.h

@@ -29,23 +29,30 @@ anki_internal:
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);
 
-	RenderTargetHandle getRt() const
+	RenderTargetHandle getReflectionRt() const
 	{
-		return m_runCtx.m_rt;
+		return m_runCtx.m_reflRt;
+	}
+
+	RenderTargetHandle getIrradianceRt() const
+	{
+		return m_runCtx.m_irradianceRt;
 	}
 
 private:
 	ShaderProgramResourcePtr m_prog;
 	Array<ShaderProgramPtr, 2> m_grProg;
 
-	RenderTargetDescription m_rtDescr;
+	TexturePtr m_reflTex;
+	TexturePtr m_irradianceTex;
 
 	Array<U8, 2> m_workgroupSize = {{16, 16}};
 
 	class
 	{
 	public:
-		RenderTargetHandle m_rt;
+		RenderTargetHandle m_reflRt;
+		RenderTargetHandle m_irradianceRt;
 		RenderingContext* m_ctx ANKI_DBG_NULLIFY;
 	} m_runCtx;
 

+ 5 - 0
src/anki/renderer/UiStage.cpp

@@ -48,6 +48,11 @@ void UiStage::draw(RenderingContext& ctx, CommandBufferPtr& cmdb)
 
 	m_canvas->endBuilding();
 	m_canvas->appendToCommandBuffer(cmdb);
+
+	// UI messes with the state, restore it
+	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ZERO);
+	cmdb->setBlendOperation(0, BlendOperation::ADD);
+	cmdb->setCullMode(FaceSelectionBit::BACK);
 }
 
 } // end namespace anki