Browse Source

Unifying SSLR and cubemap reflections. WIP

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
f1a38f4f74

+ 15 - 0
include/anki/renderer/Clusterer.h

@@ -88,6 +88,21 @@ public:
 		return m_calcNearOpt;
 		return m_calcNearOpt;
 	}
 	}
 
 
+	U getClusterCountX() const
+	{
+		return m_counts[0];
+	}
+
+	U getClusterCountY() const
+	{
+		return m_counts[1];
+	}
+
+	U getClusterCountZ() const
+	{
+		return m_counts[2];
+	}
+
 	U getClusterCount() const
 	U getClusterCount() const
 	{
 	{
 		return m_counts[0] * m_counts[1] * m_counts[2];
 		return m_counts[0] * m_counts[1] * m_counts[2];

+ 1 - 1
include/anki/renderer/Common.h

@@ -17,7 +17,6 @@ class Is;
 class Fs;
 class Fs;
 class Lf;
 class Lf;
 class Ssao;
 class Ssao;
-class Sslr;
 class Sslf;
 class Sslf;
 class Tm;
 class Tm;
 class Bloom;
 class Bloom;
@@ -25,6 +24,7 @@ class Pps;
 class Dbg;
 class Dbg;
 class Tiler;
 class Tiler;
 class Ir;
 class Ir;
+class Refl;
 
 
 /// Cut the job submition into multiple chains. We want to avoid feeding
 /// Cut the job submition into multiple chains. We want to avoid feeding
 /// GL with a huge job chain
 /// GL with a huge job chain

+ 2 - 0
include/anki/renderer/Ir.h

@@ -7,6 +7,7 @@
 
 
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/RenderingPass.h>
 #include <anki/renderer/RenderingPass.h>
+#include <anki/renderer/Clusterer.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -73,6 +74,7 @@ private:
 	U16 m_fbSize = 0;
 	U16 m_fbSize = 0;
 	DArray<CacheEntry> m_cacheEntries;
 	DArray<CacheEntry> m_cacheEntries;
 	Barrier m_barrier;
 	Barrier m_barrier;
+	Clusterer m_clusterer;
 
 
 	// Tokens
 	// Tokens
 	DynamicBufferToken m_probesToken;
 	DynamicBufferToken m_probesToken;

+ 0 - 11
include/anki/renderer/Pps.h

@@ -37,16 +37,6 @@ public:
 		return *m_ssao;
 		return *m_ssao;
 	}
 	}
 
 
-	const Sslr& getSslr() const
-	{
-		return *m_sslr;
-	}
-
-	Sslr& getSslr()
-	{
-		return *m_sslr;
-	}
-
 	const Tm& getTm() const
 	const Tm& getTm() const
 	{
 	{
 		return *m_tm;
 		return *m_tm;
@@ -88,7 +78,6 @@ anki_internal:
 
 
 private:
 private:
 	UniquePtr<Ssao> m_ssao;
 	UniquePtr<Ssao> m_ssao;
-	UniquePtr<Sslr> m_sslr;
 	UniquePtr<Tm> m_tm;
 	UniquePtr<Tm> m_tm;
 	UniquePtr<Bloom> m_bloom;
 	UniquePtr<Bloom> m_bloom;
 	UniquePtr<Sslf> m_sslf;
 	UniquePtr<Sslf> m_sslf;

+ 68 - 0
include/anki/renderer/Refl.h

@@ -0,0 +1,68 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/renderer/RenderingPass.h>
+
+namespace anki {
+
+// Forward
+class Ir;
+
+/// @addtogroup renderer
+/// @{
+
+/// Reflections.
+class Refl: public RenderingPass
+{
+anki_internal:
+	Refl(Renderer* r);
+
+	~Refl();
+
+	ANKI_USE_RESULT Error init(const ConfigSet& config);
+
+	/// Run before MS.
+	ANKI_USE_RESULT Error run1(CommandBufferPtr cmdb);
+
+	/// Run after IS.
+	void run2(CommandBufferPtr cmdb);
+
+private:
+	U32 m_width = 0;
+	U32 m_height = 0;
+
+	Bool8 m_irEnabled = false;
+	Bool8 m_sslrEnabled = false;
+
+	// Sub-stages
+	UniquePtr<Ir> m_ir;
+
+	// 1st pass
+	ShaderResourcePtr m_frag;
+	PipelinePtr m_ppline;
+	TexturePtr m_rt;
+	FramebufferPtr m_fb;
+	ResourceGroupPtr m_rcGroup;
+	BufferPtr m_uniforms;
+	Timestamp m_uniformsUpdateTimestamp = 0;
+
+	// 2nd pass: Blit
+	ResourceGroupPtr m_blitRcGroup;
+	FramebufferPtr m_isFb;
+	ShaderResourcePtr m_blitFrag;
+	PipelinePtr m_blitPpline;
+
+	ANKI_USE_RESULT Error initInternal(const ConfigSet& config);
+	ANKI_USE_RESULT Error init1stPass(const ConfigSet& config);
+	ANKI_USE_RESULT Error init2ndPass();
+
+	void writeUniforms(CommandBufferPtr cmdb);
+};
+/// @}
+
+} // end namespace anki
+

+ 1 - 16
include/anki/renderer/Renderer.h

@@ -68,21 +68,6 @@ public:
 		return *m_dbg;
 		return *m_dbg;
 	}
 	}
 
 
-	const Ir& getIr() const
-	{
-		return *m_ir;
-	}
-
-	Ir& getIr()
-	{
-		return *m_ir;
-	}
-
-	Bool irEnabled() const
-	{
-		return m_ir.isCreated();
-	}
-
 	Dbg& getDbg()
 	Dbg& getDbg()
 	{
 	{
 		return *m_dbg;
 		return *m_dbg;
@@ -307,9 +292,9 @@ private:
 
 
 	/// @name Rendering stages
 	/// @name Rendering stages
 	/// @{
 	/// @{
-	UniquePtr<Ir> m_ir;
 	UniquePtr<Ms> m_ms; ///< Material rendering stage
 	UniquePtr<Ms> m_ms; ///< Material rendering stage
 	UniquePtr<Is> m_is; ///< Illumination rendering stage
 	UniquePtr<Is> m_is; ///< Illumination rendering stage
+	UniquePtr<Refl> m_refl; ///< Reflections.
 	UniquePtr<Tiler> m_tiler;
 	UniquePtr<Tiler> m_tiler;
 	UniquePtr<Pps> m_pps; ///< Postprocessing rendering stage
 	UniquePtr<Pps> m_pps; ///< Postprocessing rendering stage
 	UniquePtr<Fs> m_fs; ///< Forward shading.
 	UniquePtr<Fs> m_fs; ///< Forward shading.

+ 0 - 50
include/anki/renderer/Sslr.h

@@ -1,50 +0,0 @@
-// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/renderer/RenderingPass.h>
-#include <anki/Gr.h>
-
-namespace anki {
-
-/// @addtogroup renderer
-/// @{
-
-/// Screen space local reflections pass
-class Sslr: public RenderingPass
-{
-anki_internal:
-	Sslr(Renderer* r)
-		: RenderingPass(r)
-	{}
-
-	ANKI_USE_RESULT Error init(const ConfigSet& config);
-	void run(CommandBufferPtr& cmdBuff);
-
-private:
-	U32 m_width;
-	U32 m_height;
-
-	// 1st pass
-	ShaderResourcePtr m_reflectionFrag;
-	PipelinePtr m_reflectionPpline;
-	SamplerPtr m_depthMapSampler;
-	TexturePtr m_rt;
-	FramebufferPtr m_fb;
-	ResourceGroupPtr m_rcGroup;
-	ResourceGroupPtr m_rcGroupBlit;
-
-	// 2nd pass: blit
-	FramebufferPtr m_isFb;
-	ShaderResourcePtr m_blitFrag;
-	PipelinePtr m_blitPpline;
-
-	ANKI_USE_RESULT Error initInternal(const ConfigSet& config);
-};
-/// @}
-
-} // end namespace anki
-

+ 37 - 6
shaders/ImageReflections.glsl

@@ -24,6 +24,7 @@ layout(std140, row_major, SS_BINDING(IMAGE_REFLECTIONS_SET,
 	IMAGE_REFLECTIONS_FIRST_SS_BINDING)) readonly buffer _irs1
 	IMAGE_REFLECTIONS_FIRST_SS_BINDING)) readonly buffer _irs1
 {
 {
 	mat3 u_invViewRotation;
 	mat3 u_invViewRotation;
+	vec4 u_nearClusterDivisorPad2;
 	ReflectionProbe u_reflectionProbes[];
 	ReflectionProbe u_reflectionProbes[];
 };
 };
 
 
@@ -71,13 +72,9 @@ vec3 computeCubemapVec(in vec3 r, in float R2, in vec3 f)
 
 
 //==============================================================================
 //==============================================================================
 vec3 readReflection(in uint clusterIndex, in vec3 posVSpace,
 vec3 readReflection(in uint clusterIndex, in vec3 posVSpace,
-	in vec3 normalVSpace, in float lod)
+	in vec3 r, in float lod)
 {
 {
-	vec3 color = IMAGE_REFLECTIONS_DEFAULT_COLOR;
-
-	// Reflection direction
-	vec3 eye = normalize(posVSpace);
-	vec3 r = reflect(eye, normalVSpace);
+	vec3 color = vec3(0.0);
 
 
 	// Check proxy
 	// Check proxy
 	uvec2 cluster = u_reflectionClusters[clusterIndex];
 	uvec2 cluster = u_reflectionClusters[clusterIndex];
@@ -113,5 +110,39 @@ vec3 readReflection(in uint clusterIndex, in vec3 posVSpace,
 	return color;
 	return color;
 }
 }
 
 
+//==============================================================================
+uint computeClusterIndex(in vec3 posVSpace)
+{
+#if TILE_SIZE == 64
+	// Compute tile idx
+	uint tileX = uint(gl_FragCoord.x) >> 6;
+	uint tileY = uint(gl_FragCoord.y) >> 6;
+
+	const uint TILE_COUNT_X = (WIDTH / TILE_SIZE);
+	uint tileIdx = tileY * TILE_COUNT_X + tileX;
+
+	// Calc split
+	float zVspace = -posVSpace.z;
+	float fk = sqrt(
+		(zVspace - u_nearClusterDivisorPad2.x) / u_nearClusterDivisorPad2.y);
+	uint k = uint(fk);
+
+	// Finally
+	const uint TILE_COUNT = TILE_COUNT_X * (HEIGHT / TILE_SIZE);
+	uint clusterIdx = tileIdx + k * TILE_COUNT;
+
+	return clusterIdx;
+#else
+#	error Not designed for this tile size
+#endif
+}
+
+//==============================================================================
+vec3 doImageReflections(in vec3 posVSpace, in vec3 r, in float lod)
+{
+	uint clusterIdx = computeClusterIndex(posVSpace);
+	return readReflection(clusterIdx, posVSpace, r, lod);
+}
+
 #endif
 #endif
 
 

+ 0 - 22
shaders/IsLp.frag.glsl

@@ -27,17 +27,6 @@ layout(location = 0) out vec3 out_color;
 
 
 #pragma anki include "shaders/LightFunctions.glsl"
 #pragma anki include "shaders/LightFunctions.glsl"
 
 
-#if IR == 1
-#define IMAGE_REFLECTIONS_SET 0
-#define IMAGE_REFLECTIONS_FIRST_SS_BINDING 5
-#define IMAGE_REFLECTIONS_TEX_BINDING 6
-#define IMAGE_REFLECTIONS_DEFAULT_COLOR vec3(0.0)
-#pragma anki include "shaders/ImageReflections.glsl"
-#undef IMAGE_REFLECTIONS_SET
-#undef IMAGE_REFLECTIONS_FIRST_SS_BINDING
-#undef IMAGE_REFLECTIONS_DEFAULT_COLOR
-#endif
-
 const uint TILE_COUNT = TILES_COUNT_X * TILES_COUNT_Y;
 const uint TILE_COUNT = TILES_COUNT_X * TILES_COUNT_Y;
 
 
 //==============================================================================
 //==============================================================================
@@ -160,14 +149,6 @@ void main()
 			* (att * spot * max(subsurface, lambert * shadow));
 			* (att * spot * max(subsurface, lambert * shadow));
 	}
 	}
 
 
-#if IR == 1
-	{
-		float reflLod = float(IR_MIPMAP_COUNT) * roughness;
-		vec3 refl = readReflection(clusterIndex, fragPos, normal, reflLod);
-		out_color += refl * (1.0 - roughness);
-	}
-#endif
-
 #if 0
 #if 0
 	if(pointLightsCount == 0)
 	if(pointLightsCount == 0)
 	{
 	{
@@ -188,8 +169,5 @@ void main()
 	{
 	{
 		out_color += vec3(1.0, 0.0, 0.0);
 		out_color += vec3(1.0, 0.0, 0.0);
 	}
 	}
-#if IR == 1
-	out_color = readReflection(clusterIndex, fragPos, normal, 0.0);
-#endif
 #endif
 #endif
 }
 }

+ 6 - 0
shaders/Pack.glsl

@@ -137,6 +137,12 @@ void readGBuffer(
 	normal = normalize(normal * 2.0 - 1.0);
 	normal = normalize(normal * 2.0 - 1.0);
 }
 }
 
 
+// Rear roughness from G-Buffer
+void readRoughnessFromGBuffer(in sampler2D rt1, in vec2 uv, out float r)
+{
+	r = textureLod(rt1, uv, 0.0).z;
+}
+
 // Read only normal from G buffer
 // Read only normal from G buffer
 void readNormalFromGBuffer(
 void readNormalFromGBuffer(
 	in sampler2D fai2,
 	in sampler2D fai2,

+ 82 - 0
shaders/Refl.frag.glsl

@@ -0,0 +1,82 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki type frag
+#pragma anki include "shaders/Pack.glsl"
+
+// Common
+layout(TEX_BINDING(0, 0)) uniform sampler2D u_depthRt;
+layout(TEX_BINDING(0, 1)) uniform sampler2D u_msRt1;
+layout(TEX_BINDING(0, 2)) uniform sampler2D u_msRt2;
+
+layout(std140, UBO_BINDING(0, 0)) uniform _blk0
+{
+	vec4 u_projectionParams;
+	mat4 u_projectionMat;
+};
+
+// IR
+#if IR_ENABLED
+#define IMAGE_REFLECTIONS_SET 0
+#define IMAGE_REFLECTIONS_FIRST_SS_BINDING 0
+#define IMAGE_REFLECTIONS_TEX_BINDING 4
+#pragma anki include "shaders/ImageReflections.glsl"
+#undef IMAGE_REFLECTIONS_SET
+#undef IMAGE_REFLECTIONS_FIRST_SS_BINDING
+#endif
+
+// SSLR
+#if SSLR_ENABLED
+layout(TEX_BINDING(0, 3)) uniform sampler2D u_isRt;
+
+#pragma anki include "shaders/Sslr.glsl"
+#endif
+
+// In/out
+layout(location = 0) in vec2 in_texCoord;
+layout(location = 0) out vec3 out_color;
+
+void main()
+{
+
+#if 0
+	#if IR == 1
+	{
+		float reflLod = float(IR_MIPMAP_COUNT) * roughness;
+		vec3 refl = readReflection(clusterIndex, fragPos, normal, reflLod);
+		out_color += refl * (1.0 - roughness);
+	}
+#endif
+
+// Don't bother for very rough surfaces
+	if(roughness > SSLR_START_ROUGHNESS)
+	{
+		contribution = 0.0;
+		return vec3(0.0);
+	}
+
+	// Decode the G-buffer
+	float depth = textureRt(u_msDepthRt, in_texCoord).r;
+	vec3 posVSpace;
+	posVSpace.z = u_projectionParams.z / (u_projectionParams.w + depth);
+	posVSpace.xy =
+		(2.0 * in_texCoord - 1.0) * u_projectionParams.xy * posVSpace.z;
+
+	float roughness;
+	readRoughnessFromGBuffer(u_rt1, in_texCoord, roughness);
+
+	vec3 normal;
+	readNormalFromGBuffer(u_rt2, in_texCoord, normal);
+
+	// First the SSLR
+#if SSLR_ENABLED
+
+#else
+#endif
+
+#endif
+
+	out_color = vec3(0.0, 0.0, 1.0);
+}

+ 24 - 68
shaders/PpsSslr.frag.glsl → shaders/Sslr.glsl

@@ -3,85 +3,39 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-// SSLR fragment shader
-#pragma anki type frag
+// SSLR functions and data
 #pragma anki include "shaders/Common.glsl"
 #pragma anki include "shaders/Common.glsl"
 #pragma anki include "shaders/LinearDepth.glsl"
 #pragma anki include "shaders/LinearDepth.glsl"
 #pragma anki include "shaders/Pack.glsl"
 #pragma anki include "shaders/Pack.glsl"
 
 
 const float ONE = 0.9;
 const float ONE = 0.9;
 
 
-layout(location = 0) in vec2 in_texCoords;
-
-layout(location = 0) out vec3 out_color;
-
-layout(std140, binding = 0) uniform _u0
-{
-	vec4 u_projectionParams;
-
-	/// The projection matrix
-	mat4 u_projectionMatrix;
-};
-
-layout(binding = 0) uniform sampler2D u_isRt;
-layout(binding = 1) uniform sampler2D u_msDepthRt;
-layout(binding = 2) uniform sampler2D u_msRt1;
-layout(binding = 3) uniform sampler2D u_msRt2;
-
+//==============================================================================
 // Returns the Z of the position in view space
 // Returns the Z of the position in view space
 float readZ(in vec2 uv)
 float readZ(in vec2 uv)
 {
 {
-	float depth = textureLod(u_msDepthRt, uv, 1.0).r;
+	float depth = textureLod(u_depthRt, uv, 1.0).r;
 	float z = u_projectionParams.z / (u_projectionParams.w + depth);
 	float z = u_projectionParams.z / (u_projectionParams.w + depth);
 	return z;
 	return z;
 }
 }
 
 
-// Read position in view space
-vec3 readPosition(in vec2 uv)
-{
-	vec3 fragPosVspace;
-	fragPosVspace.z = readZ(uv);
-
-	fragPosVspace.xy =
-		(2.0 * uv - 1.0) * u_projectionParams.xy * fragPosVspace.z;
-
-	return fragPosVspace;
-}
-
-vec3 project(vec3 p)
+//==============================================================================
+vec2 projectXy(in vec3 p)
 {
 {
-	vec4 a = u_projectionMatrix * vec4(p, 1.0);
-	return a.xyz / a.w;
-}
-
-vec2 projectXy(vec3 p)
-{
-	vec4 a = u_projectionMatrix * vec4(p, 1.0);
+	vec4 a = u_projectionMat * vec4(p, 1.0);
 	return a.xy / a.w;
 	return a.xy / a.w;
 }
 }
 
 
-void main()
+//==============================================================================
+vec3 doSslr(in vec3 r, in vec3 posVSpace, in vec2 uv, out float contribution)
 {
 {
-	vec3 normal;
-	vec3 specColor;
-	readNormalSpecularColorFromGBuffer(
-		u_msRt1, u_msRt2, in_texCoords, normal, specColor);
-
-	//out_color = vec3(0.5, 0.0, 0.0);
-	out_color = vec3(0.0);
-
-	if(length(specColor) < 0.5)
-	{
-		return;
-	}
-
-	vec3 p0 = readPosition(in_texCoords);
+	contribution = 0.5;
+	return vec3(1.0, 0.0, 1.0);
+#if 0
+	vec3 color = vec3(0.0);
+	vec3 p0 = posVSpace;
+	contribution = 1.0;
 
 
-	// Reflection direction
-	vec3 eye = normalize(p0);
-	vec3 r = reflect(eye, normal);
-
-#if 1
 	// Let p1 be the intersection of p0+r to the near plane, then
 	// Let p1 be the intersection of p0+r to the near plane, then
 	// p1 = p0 + t*r or
 	// p1 = p0 + t*r or
 	// p1.x = p0.x + t*r.x (1)
 	// p1.x = p0.x + t*r.x (1)
@@ -91,7 +45,7 @@ void main()
 	float t = -p0.z / (r.z + 0.0000001);
 	float t = -p0.z / (r.z + 0.0000001);
 	vec3 p1 = p0 + r * t;
 	vec3 p1 = p0 + r * t;
 
 
-	vec2 pp0 = in_texCoords * 2.0 - 1.0;
+	vec2 pp0 = uv * 2.0 - 1.0;
 	vec2 pp1 = projectXy(p1);
 	vec2 pp1 = projectXy(p1);
 
 
 	// Calculate the ray from p0 to p1 in 2D space and get the number of
 	// Calculate the ray from p0 to p1 in 2D space and get the number of
@@ -117,8 +71,8 @@ void main()
 		vec2 comp = abs(ndc);
 		vec2 comp = abs(ndc);
 		if(comp.x > ONE || comp.y > ONE)
 		if(comp.x > ONE || comp.y > ONE)
 		{
 		{
-			//out_color = vec3(1, 0.0, 1);
-			return;
+			//color = vec3(1, 0.0, 1);
+			return color;
 		}
 		}
 
 
 		// 'a' is ray that passes through the eye and into ndc
 		// 'a' is ray that passes through the eye and into ndc
@@ -141,7 +95,7 @@ void main()
 		float intersectionZ = a.z * k; // intersectionXYZ = a * k;
 		float intersectionZ = a.z * k; // intersectionXYZ = a * k;
 
 
 		vec2 texCoord = ndc * 0.5 + 0.5;
 		vec2 texCoord = ndc * 0.5 + 0.5;
-		float depth = readZ(texCoord);
+		float depth = readZ(u_depthRt, texCoord);
 
 
 		float diffDepth = depth - intersectionZ;
 		float diffDepth = depth - intersectionZ;
 
 
@@ -156,12 +110,14 @@ void main()
 			factor *= 1.0 - length(pp0);
 			factor *= 1.0 - length(pp0);
 			//factor *= specColor;
 			//factor *= specColor;
 
 
-			out_color = textureLod(u_isRt, texCoord, 0.0).rgb * factor;
+			color = textureLod(u_isRt, texCoord, 0.0).rgb * factor;
 
 
-			//out_color = vec3(1.0, 0.0, 1.0);
-			//out_color = vec3(1.0 - abs(pp0.xy), 0.0);
-			return;
+			//color = vec3(1.0, 0.0, 1.0);
+			//color = vec3(1.0 - abs(pp0.xy), 0.0);
+			return color;
 		}
 		}
 	}
 	}
+
+	return color;
 #endif
 #endif
 }
 }

+ 5 - 5
src/core/Config.cpp

@@ -43,10 +43,6 @@ Config::Config()
 	newOption("pps.ssao.renderingQuality", 0.3);
 	newOption("pps.ssao.renderingQuality", 0.3);
 	newOption("pps.ssao.blurringIterationsCount", 1);
 	newOption("pps.ssao.blurringIterationsCount", 1);
 
 
-	newOption("pps.sslr.enabled", true);
-	newOption("pps.sslr.renderingQuality", 0.2);
-	newOption("pps.sslr.blurringIterationsCount", 0);
-
 	newOption("pps.bl.enabled", true);
 	newOption("pps.bl.enabled", true);
 	newOption("pps.bl.blurringIterationsCount", 1);
 	newOption("pps.bl.blurringIterationsCount", 1);
 	newOption("pps.bl.sideBlurFactor", 1.0);
 	newOption("pps.bl.sideBlurFactor", 1.0);
@@ -58,9 +54,13 @@ Config::Config()
 	newOption("pps.gammaCorrection", true);
 	newOption("pps.gammaCorrection", true);
 
 
 	// Reflections
 	// Reflections
+	newOption("refl.renderingQuality", 0.5);
 	newOption("ir.enabled", true);
 	newOption("ir.enabled", true);
-	newOption("ir.rendererSize", 64);
+	newOption("ir.rendererSize", 128);
 	newOption("ir.cubemapTextureArraySize", 16);
 	newOption("ir.cubemapTextureArraySize", 16);
+	newOption("ir.clusterSizeZ", 16);
+	newOption("sslr.enabled", true);
+	newOption("sslr.startRoughnes", 0.2);
 
 
 	// Dbg
 	// Dbg
 	newOption("dbg.enabled", false);
 	newOption("dbg.enabled", false);

+ 38 - 14
src/renderer/Ir.cpp

@@ -6,7 +6,6 @@
 #include <anki/renderer/Ir.h>
 #include <anki/renderer/Ir.h>
 #include <anki/renderer/Is.h>
 #include <anki/renderer/Is.h>
 #include <anki/renderer/Pps.h>
 #include <anki/renderer/Pps.h>
-#include <anki/renderer/Clusterer.h>
 #include <anki/core/Config.h>
 #include <anki/core/Config.h>
 #include <anki/scene/SceneNode.h>
 #include <anki/scene/SceneNode.h>
 #include <anki/scene/Visibility.h>
 #include <anki/scene/Visibility.h>
@@ -187,14 +186,14 @@ Error Ir::init(const ConfigSet& initializer)
 	config.set("pps.enabled", true);
 	config.set("pps.enabled", true);
 	config.set("pps.bloom.enabled", true);
 	config.set("pps.bloom.enabled", true);
 	config.set("pps.ssao.enabled", false);
 	config.set("pps.ssao.enabled", false);
-	config.set("pps.sslr.enabled", false);
 	config.set("renderingQuality", 1.0);
 	config.set("renderingQuality", 1.0);
-	config.set("clusterSizeZ", 4); // XXX A bug if more. Fix it
+	config.set("clusterSizeZ", 4);
 	config.set("width", m_fbSize);
 	config.set("width", m_fbSize);
 	config.set("height", m_fbSize);
 	config.set("height", m_fbSize);
 	config.set("lodDistance", 10.0);
 	config.set("lodDistance", 10.0);
 	config.set("samples", 1);
 	config.set("samples", 1);
 	config.set("ir.enabled", false); // Very important to disable that
 	config.set("ir.enabled", false); // Very important to disable that
+	config.set("sslr.enabled", false);
 
 
 	ANKI_CHECK(m_nestedR.init(&m_r->getThreadPool(),
 	ANKI_CHECK(m_nestedR.init(&m_r->getThreadPool(),
 		&m_r->getResourceManager(), &m_r->getGrManager(), m_r->getAllocator(),
 		&m_r->getResourceManager(), &m_r->getGrManager(), m_r->getAllocator(),
@@ -214,10 +213,23 @@ Error Ir::init(const ConfigSet& initializer)
 	texinit.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 	texinit.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 
 
 	m_cubemapArr = getGrManager().newInstance<Texture>(texinit);
 	m_cubemapArr = getGrManager().newInstance<Texture>(texinit);
-
 	m_cubemapArrMipCount = computeMaxMipmapCount(m_fbSize, m_fbSize);
 	m_cubemapArrMipCount = computeMaxMipmapCount(m_fbSize, m_fbSize);
 
 
 	getGrManager().finish();
 	getGrManager().finish();
+
+	// Init the clusterer
+	F32 reflQuality = config.getNumber("refl.renderingQuality");
+	U width =
+		getAlignedRoundUp(Renderer::TILE_SIZE, m_r->getWidth() * reflQuality);
+	U height =
+		getAlignedRoundUp(Renderer::TILE_SIZE, m_r->getHeight() * reflQuality);
+
+	U tileCountX = width / Renderer::TILE_SIZE;
+	U tileCountY = height / Renderer::TILE_SIZE;
+	U clusterCountZ = config.getNumber("ir.clusterSizeZ");
+
+	m_clusterer.init(getAllocator(), tileCountX, tileCountY, clusterCountZ);
+
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
@@ -233,6 +245,11 @@ Error Ir::run(CommandBufferPtr cmdb)
 		ANKI_LOGW("Increase the ir.cubemapTextureArraySize");
 		ANKI_LOGW("Increase the ir.cubemapTextureArraySize");
 	}
 	}
 
 
+	//
+	// Prepare clusterer
+	//
+	m_clusterer.prepare(m_r->getThreadPool(), frc);
+
 	//
 	//
 	// Perform some initialization
 	// Perform some initialization
 	//
 	//
@@ -243,7 +260,8 @@ Error Ir::run(CommandBufferPtr cmdb)
 	ctx.m_alloc = getFrameAllocator();
 	ctx.m_alloc = getFrameAllocator();
 
 
 	// Allocate temp CPU mem
 	// Allocate temp CPU mem
-	ctx.m_clusterData.create(getFrameAllocator(), m_r->getClusterCount());
+	ctx.m_clusterData.create(getFrameAllocator(),
+		m_clusterer.getClusterCount());
 
 
 	//
 	//
 	// Render and populate probes GPU mem
 	// Render and populate probes GPU mem
@@ -252,15 +270,21 @@ Error Ir::run(CommandBufferPtr cmdb)
 	// Probes GPU mem
 	// Probes GPU mem
 	void* data = getGrManager().allocateFrameHostVisibleMemory(
 	void* data = getGrManager().allocateFrameHostVisibleMemory(
 		sizeof(IrShaderReflectionProbe) * visRez.getReflectionProbeCount()
 		sizeof(IrShaderReflectionProbe) * visRez.getReflectionProbeCount()
-		+ sizeof(Mat3x4),
+		+ sizeof(Mat3x4) + sizeof(Vec4),
 		BufferUsage::STORAGE, m_probesToken);
 		BufferUsage::STORAGE, m_probesToken);
 
 
 	Mat3x4* invViewRotation = static_cast<Mat3x4*>(data);
 	Mat3x4* invViewRotation = static_cast<Mat3x4*>(data);
 	*invViewRotation =
 	*invViewRotation =
 		Mat3x4(frc.getViewMatrix().getInverse().getRotationPart());
 		Mat3x4(frc.getViewMatrix().getInverse().getRotationPart());
 
 
+	Vec4* nearClusterDivisor = reinterpret_cast<Vec4*>(invViewRotation + 1);
+	nearClusterDivisor->x() = frc.getFrustum().getNear();
+	nearClusterDivisor->y() = m_clusterer.getDivisor();
+	nearClusterDivisor->z() = 0.0;
+	nearClusterDivisor->w() = 0.0;
+
 	SArray<IrShaderReflectionProbe> probes(
 	SArray<IrShaderReflectionProbe> probes(
-		reinterpret_cast<IrShaderReflectionProbe*>(invViewRotation + 1),
+		reinterpret_cast<IrShaderReflectionProbe*>(nearClusterDivisor + 1),
 		visRez.getReflectionProbeCount());
 		visRez.getReflectionProbeCount());
 
 
 	// Render some of the probes
 	// Render some of the probes
@@ -315,7 +339,7 @@ void Ir::binProbes(U32 threadId, PtrSize threadsCount, IrRunContext& ctx)
 	// Init clusterer test result for this thread
 	// Init clusterer test result for this thread
 	if(start < end)
 	if(start < end)
 	{
 	{
-		m_r->getClusterer().initTestResults(getFrameAllocator(),
+		m_clusterer.initTestResults(getFrameAllocator(),
 			task.m_clustererTestResult);
 			task.m_clustererTestResult);
 	}
 	}
 
 
@@ -339,11 +363,11 @@ void Ir::binProbes(U32 threadId, PtrSize threadsCount, IrRunContext& ctx)
 	if(who == 0)
 	if(who == 0)
 	{
 	{
 		void* mem = getGrManager().allocateFrameHostVisibleMemory(
 		void* mem = getGrManager().allocateFrameHostVisibleMemory(
-			m_r->getClusterCount() * sizeof(IrShaderCluster),
+			m_clusterer.getClusterCount() * sizeof(IrShaderCluster),
 			BufferUsage::STORAGE, m_clustersToken);
 			BufferUsage::STORAGE, m_clustersToken);
 
 
 		ctx.m_clusters = SArray<IrShaderCluster>(
 		ctx.m_clusters = SArray<IrShaderCluster>(
-			static_cast<IrShaderCluster*>(mem), m_r->getClusterCount());
+			static_cast<IrShaderCluster*>(mem), m_clusterer.getClusterCount());
 	}
 	}
 
 
 	// Use the same trick to allocate the indices
 	// Use the same trick to allocate the indices
@@ -376,7 +400,7 @@ void Ir::binProbes(U32 threadId, PtrSize threadsCount, IrRunContext& ctx)
 	ANKI_TRACE_START_EVENT(RENDER_IR);
 	ANKI_TRACE_START_EVENT(RENDER_IR);
 
 
 	ThreadPool::Task::choseStartEnd(threadId, threadsCount,
 	ThreadPool::Task::choseStartEnd(threadId, threadsCount,
-		m_r->getClusterCount(), start, end);
+		m_clusterer.getClusterCount(), start, end);
 
 
 	for(auto i = start; i < end; i++)
 	for(auto i = start; i < end; i++)
 	{
 	{
@@ -425,7 +449,7 @@ void Ir::binProbe(U probeIdx, IrRunContext& ctx, IrTaskContext& task) const
 		task.m_node->getComponent<ReflectionProbeComponent>();
 		task.m_node->getComponent<ReflectionProbeComponent>();
 
 
 	// Perform the expensive tests
 	// Perform the expensive tests
-	m_r->getClusterer().bin(sp.getSpatialCollisionShape(), sp.getAabb(),
+	m_clusterer.bin(sp.getSpatialCollisionShape(), sp.getAabb(),
 		task.m_clustererTestResult);
 		task.m_clustererTestResult);
 
 
 	// Bin to the correct tiles
 	// Bin to the correct tiles
@@ -437,8 +461,8 @@ void Ir::binProbe(U probeIdx, IrRunContext& ctx, IrTaskContext& task) const
 		U y = (*it)[1];
 		U y = (*it)[1];
 		U z = (*it)[2];
 		U z = (*it)[2];
 
 
-		U i =
-			m_r->getTileCountXY().x() * (z * m_r->getTileCountXY().y() + y) + x;
+		U i = m_clusterer.getClusterCountX()
+			* (z * m_clusterer.getClusterCountY() + y) + x;
 
 
 		auto& cluster = ctx.m_clusterData[i];
 		auto& cluster = ctx.m_clusterData[i];
 
 

+ 2 - 24
src/renderer/Is.cpp

@@ -7,7 +7,6 @@
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Ms.h>
 #include <anki/renderer/Ms.h>
 #include <anki/renderer/Pps.h>
 #include <anki/renderer/Pps.h>
-#include <anki/renderer/Ir.h>
 #include <anki/scene/Camera.h>
 #include <anki/scene/Camera.h>
 #include <anki/scene/Light.h>
 #include <anki/scene/Light.h>
 #include <anki/scene/Visibility.h>
 #include <anki/scene/Visibility.h>
@@ -249,9 +248,7 @@ Error Is::initInternal(const ConfigSet& config)
 		"#define MAX_SPOT_LIGHTS %u\n"
 		"#define MAX_SPOT_LIGHTS %u\n"
 		"#define MAX_LIGHT_INDICES %u\n"
 		"#define MAX_LIGHT_INDICES %u\n"
 		"#define GROUND_LIGHT %u\n"
 		"#define GROUND_LIGHT %u\n"
-		"#define POISSON %u\n"
-		"#define IR %u\n"
-		"#define IR_MIPMAP_COUNT %u\n",
+		"#define POISSON %u\n",
 		m_r->getTileCountXY().x(),
 		m_r->getTileCountXY().x(),
 		m_r->getTileCountXY().y(),
 		m_r->getTileCountXY().y(),
 		m_r->getClusterCount(),
 		m_r->getClusterCount(),
@@ -261,9 +258,7 @@ Error Is::initInternal(const ConfigSet& config)
 		m_maxSpotLights,
 		m_maxSpotLights,
 		m_maxLightIds,
 		m_maxLightIds,
 		m_groundLightEnabled,
 		m_groundLightEnabled,
-		m_sm.getPoissonEnabled(),
-		m_r->irEnabled(),
-		m_r->irEnabled() ? m_r->getIr().getCubemapArrayMipmapCount() : 0);
+		m_sm.getPoissonEnabled());
 
 
 	// point light
 	// point light
 	ANKI_CHECK(getResourceManager().loadResourceToCache(m_lightVert,
 	ANKI_CHECK(getResourceManager().loadResourceToCache(m_lightVert,
@@ -308,22 +303,12 @@ Error Is::initInternal(const ConfigSet& config)
 		init.m_textures[3].m_texture = m_r->getMs().getDepthRt();
 		init.m_textures[3].m_texture = m_r->getMs().getDepthRt();
 		init.m_textures[4].m_texture = m_sm.getSpotTextureArray();
 		init.m_textures[4].m_texture = m_sm.getSpotTextureArray();
 		init.m_textures[5].m_texture = m_sm.getOmniTextureArray();
 		init.m_textures[5].m_texture = m_sm.getOmniTextureArray();
-		if(m_r->irEnabled())
-		{
-			init.m_textures[6].m_texture = m_r->getIr().getCubemapArray();
-		}
 
 
 		init.m_storageBuffers[0].m_dynamic = true;
 		init.m_storageBuffers[0].m_dynamic = true;
 		init.m_storageBuffers[1].m_dynamic = true;
 		init.m_storageBuffers[1].m_dynamic = true;
 		init.m_storageBuffers[2].m_dynamic = true;
 		init.m_storageBuffers[2].m_dynamic = true;
 		init.m_storageBuffers[3].m_dynamic = true;
 		init.m_storageBuffers[3].m_dynamic = true;
 		init.m_storageBuffers[4].m_dynamic = true;
 		init.m_storageBuffers[4].m_dynamic = true;
-		if(m_r->irEnabled())
-		{
-			init.m_storageBuffers[5].m_dynamic = true;
-			init.m_storageBuffers[6].m_dynamic = true;
-			init.m_storageBuffers[7].m_dynamic = true;
-		}
 
 
 		m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
 		m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
 	}
 	}
@@ -767,13 +752,6 @@ void Is::setState(CommandBufferPtr& cmdb)
 	dyn.m_storageBuffers[2] = m_sLightsToken;
 	dyn.m_storageBuffers[2] = m_sLightsToken;
 	dyn.m_storageBuffers[3] = m_clustersToken;
 	dyn.m_storageBuffers[3] = m_clustersToken;
 	dyn.m_storageBuffers[4] = m_lightIdsToken;
 	dyn.m_storageBuffers[4] = m_lightIdsToken;
-	if(m_r->irEnabled())
-	{
-		dyn.m_storageBuffers[5] = m_r->getIr().getProbesToken();
-		dyn.m_storageBuffers[6] = m_r->getIr().getProbeIndicesToken();
-		dyn.m_storageBuffers[7] = m_r->getIr().getClustersToken();
-
-	}
 
 
 	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
 	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
 }
 }

+ 1 - 11
src/renderer/Pps.cpp

@@ -8,7 +8,6 @@
 #include <anki/renderer/Bloom.h>
 #include <anki/renderer/Bloom.h>
 #include <anki/renderer/Sslf.h>
 #include <anki/renderer/Sslf.h>
 #include <anki/renderer/Ssao.h>
 #include <anki/renderer/Ssao.h>
-#include <anki/renderer/Sslr.h>
 #include <anki/renderer/Tm.h>
 #include <anki/renderer/Tm.h>
 #include <anki/renderer/Is.h>
 #include <anki/renderer/Is.h>
 #include <anki/renderer/Ms.h>
 #include <anki/renderer/Ms.h>
@@ -60,9 +59,6 @@ Error Pps::initInternal(const ConfigSet& config)
 	m_ssao.reset(getAllocator().newInstance<Ssao>(m_r));
 	m_ssao.reset(getAllocator().newInstance<Ssao>(m_r));
 	ANKI_CHECK(m_ssao->init(config));
 	ANKI_CHECK(m_ssao->init(config));
 
 
-	m_sslr.reset(getAllocator().newInstance<Sslr>(m_r));
-	ANKI_CHECK(m_sslr->init(config));
-
 	m_tm.reset(getAllocator().newInstance<Tm>(m_r));
 	m_tm.reset(getAllocator().newInstance<Tm>(m_r));
 	ANKI_CHECK(m_tm->create(config));
 	ANKI_CHECK(m_tm->create(config));
 
 
@@ -179,13 +175,7 @@ void Pps::run(CommandBufferPtr& cmdb)
 		m_ssao->run(cmdb);
 		m_ssao->run(cmdb);
 	}
 	}
 
 
-	// Then SSLR because HDR depends on it
-	if(m_sslr->getEnabled())
-	{
-		m_sslr->run(cmdb);
-	}
-
-	m_r->getIs().generateMipmaps(cmdb);
+	m_r->getIs().generateMipmaps(cmdb); // XXX
 	m_tm->run(cmdb);
 	m_tm->run(cmdb);
 
 
 	if(m_bloom->getEnabled())
 	if(m_bloom->getEnabled())

+ 264 - 0
src/renderer/Refl.cpp

@@ -0,0 +1,264 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/renderer/Refl.h>
+#include <anki/renderer/Renderer.h>
+#include <anki/renderer/Ms.h>
+#include <anki/renderer/Ir.h>
+#include <anki/renderer/Is.h>
+#include <anki/misc/ConfigSet.h>
+#include <anki/scene/FrustumComponent.h>
+
+namespace anki {
+
+//==============================================================================
+// Misc                                                                        =
+//==============================================================================
+
+struct ReflUniforms
+{
+	Vec4 m_projectionParams;
+	Mat4 m_projectionMat;
+};
+
+//==============================================================================
+// Refl                                                                        =
+//==============================================================================
+
+//==============================================================================
+Refl::Refl(Renderer* r)
+	: RenderingPass(r)
+{}
+
+//==============================================================================
+Refl::~Refl()
+{}
+
+//==============================================================================
+Error Refl::init(const ConfigSet& config)
+{
+	Error err = initInternal(config);
+	if(err)
+	{
+		ANKI_LOGE("Failed to init reflections");
+	}
+
+	return err;
+}
+
+//==============================================================================
+Error Refl::initInternal(const ConfigSet& config)
+{
+	m_irEnabled = config.getNumber("ir.enabled");
+	m_sslrEnabled = config.getNumber("sslr.enabled");
+
+	m_enabled = m_irEnabled || m_sslrEnabled;
+	if(!m_enabled)
+	{
+		return ErrorCode::NONE;
+	}
+
+	// Size
+	const F32 quality = config.getNumber("refl.renderingQuality");
+
+	m_width = getAlignedRoundUp(Renderer::TILE_SIZE, quality * m_r->getWidth());
+	m_height =
+		getAlignedRoundUp(Renderer::TILE_SIZE, quality * m_r->getHeight());
+
+	// IR
+	if(m_irEnabled)
+	{
+		m_ir.reset(getAllocator().newInstance<Ir>(m_r));
+		ANKI_CHECK(m_ir->init(config));
+	}
+
+	// Continue
+	ANKI_CHECK(init1stPass(config));
+	ANKI_CHECK(init2ndPass());
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+Error Refl::init1stPass(const ConfigSet& config)
+{
+	// Create shader
+	StringAuto pps(getFrameAllocator());
+
+	pps.sprintf(
+		"#define WIDTH %u\n"
+		"#define HEIGHT %u\n"
+		"#define SSLR_ENABLED %u\n"
+		"#define IR_ENABLED %u\n"
+		"#define IR_MIPMAP_COUNT %u\n"
+		"#define TILE_SIZE %u\n"
+		"#define SSLR_START_ROUGHNESS %f\n",
+		m_width,
+		m_height,
+		U(m_sslrEnabled),
+		U(m_irEnabled),
+		(m_irEnabled) ? m_ir->getCubemapArrayMipmapCount() : 0,
+		Renderer::TILE_SIZE,
+		config.getNumber("sslr.startRoughnes"));
+
+	ANKI_CHECK(getResourceManager().loadResourceToCache(m_frag,
+		"shaders/Refl.frag.glsl", pps.toCString(), "r_refl_"));
+
+	// Create ppline
+	ColorStateInfo colorState;
+	colorState.m_attachmentCount = 1;
+	colorState.m_attachments[0].m_format = Is::RT_PIXEL_FORMAT;
+
+	m_r->createDrawQuadPipeline(m_frag->getGrShader(), colorState, m_ppline);
+
+	// Create uniform buffer
+	m_uniforms = getGrManager().newInstance<Buffer>(sizeof(ReflUniforms),
+		BufferUsageBit::UNIFORM, BufferAccessBit::CLIENT_WRITE);
+
+	// Create RC group
+	ResourceGroupInitializer rcInit;
+	rcInit.m_textures[0].m_texture = m_r->getMs().getDepthRt();
+	rcInit.m_textures[1].m_texture = m_r->getMs().getRt1();
+	rcInit.m_textures[2].m_texture = m_r->getMs().getRt2();
+
+	if(m_sslrEnabled)
+	{
+		rcInit.m_textures[3].m_texture = m_r->getIs().getRt();
+	}
+
+	if(m_irEnabled)
+	{
+		rcInit.m_textures[4].m_texture = m_ir->getCubemapArray();
+	}
+
+	rcInit.m_uniformBuffers[0].m_buffer = m_uniforms;
+
+	if(m_irEnabled)
+	{
+		rcInit.m_storageBuffers[0].m_dynamic = true;
+		rcInit.m_storageBuffers[1].m_dynamic = true;
+		rcInit.m_storageBuffers[2].m_dynamic = true;
+	}
+
+	m_rcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
+
+	// Create RT
+	m_r->createRenderTarget(m_width, m_height,
+		Is::RT_PIXEL_FORMAT, 1, SamplingFilter::LINEAR, 1, m_rt);
+
+	// Create FB
+	FramebufferInitializer fbInit;
+	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachments[0].m_texture = m_rt;
+	fbInit.m_colorAttachments[0].m_loadOperation =
+		AttachmentLoadOperation::DONT_CARE;
+	m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+Error Refl::init2ndPass()
+{
+	// Create RC group
+	ResourceGroupInitializer rcInit;
+	rcInit.m_textures[0].m_texture = m_rt;
+
+	m_blitRcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
+
+	// Shader
+	ANKI_CHECK(getResourceManager().loadResource(
+		"shaders/Blit.frag.glsl", m_blitFrag));
+
+	// Ppline
+	ColorStateInfo colorState;
+	colorState.m_attachmentCount = 1;
+	colorState.m_attachments[0].m_format = Is::RT_PIXEL_FORMAT;
+	colorState.m_attachments[0].m_srcBlendMethod = BlendMethod::ONE;
+	colorState.m_attachments[0].m_dstBlendMethod = BlendMethod::ONE;
+
+	m_r->createDrawQuadPipeline(m_blitFrag->getGrShader(), colorState,
+		m_blitPpline);
+
+	// Create FB
+	FramebufferInitializer fbInit;
+	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachments[0].m_texture = m_r->getIs().getRt();
+	fbInit.m_colorAttachments[0].m_loadOperation =
+		AttachmentLoadOperation::LOAD;
+	m_isFb = getGrManager().newInstance<Framebuffer>(fbInit);
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+Error Refl::run1(CommandBufferPtr cmdb)
+{
+	ANKI_ASSERT(m_enabled);
+	return m_ir->run(cmdb);
+}
+
+//==============================================================================
+void Refl::run2(CommandBufferPtr cmdb)
+{
+	ANKI_ASSERT(m_enabled);
+
+	// Compute the reflection
+	//
+	writeUniforms(cmdb);
+
+	cmdb->bindFramebuffer(m_fb);
+	cmdb->setViewport(0, 0, m_width, m_height);
+	cmdb->bindPipeline(m_ppline);
+
+	DynamicBufferInfo dyn;
+	DynamicBufferInfo* pdyn = nullptr;
+	if(m_irEnabled)
+	{
+		dyn.m_storageBuffers[0] = m_ir->getProbesToken();
+		dyn.m_storageBuffers[1] = m_ir->getProbeIndicesToken();
+		dyn.m_storageBuffers[2] = m_ir->getClustersToken();
+		pdyn = &dyn;
+	};
+	cmdb->bindResourceGroup(m_rcGroup, 0, pdyn);
+
+	m_r->drawQuad(cmdb);
+
+	// Write the reflection back to IS RT
+	//
+	cmdb->bindFramebuffer(m_isFb);
+	cmdb->bindPipeline(m_blitPpline);
+	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+	cmdb->bindResourceGroup(m_blitRcGroup, 0, nullptr);
+
+	m_r->drawQuad(cmdb);
+}
+
+//==============================================================================
+void Refl::writeUniforms(CommandBufferPtr cmdb)
+{
+	const FrustumComponent& frc = m_r->getActiveFrustumComponent();
+
+	if(m_uniformsUpdateTimestamp
+			< m_r->getProjectionParametersUpdateTimestamp()
+		|| m_uniformsUpdateTimestamp < frc.getTimestamp()
+		|| m_uniformsUpdateTimestamp == 1)
+	{
+		DynamicBufferToken token;
+		ReflUniforms* blk = static_cast<ReflUniforms*>(
+			getGrManager().allocateFrameHostVisibleMemory(
+			sizeof(ReflUniforms), BufferUsage::TRANSFER, token));
+
+		blk->m_projectionParams = m_r->getProjectionParameters();
+		blk->m_projectionMat = frc.getProjectionMatrix();
+
+		cmdb->writeBuffer(m_uniforms, 0, token);
+
+		m_uniformsUpdateTimestamp = getGlobalTimestamp();
+	}
+}
+
+} // end namespace anki
+

+ 13 - 11
src/renderer/Renderer.cpp

@@ -16,7 +16,7 @@
 #include <anki/renderer/Lf.h>
 #include <anki/renderer/Lf.h>
 #include <anki/renderer/Dbg.h>
 #include <anki/renderer/Dbg.h>
 #include <anki/renderer/Tiler.h>
 #include <anki/renderer/Tiler.h>
-#include <anki/renderer/Ir.h>
+#include <anki/renderer/Refl.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -104,13 +104,6 @@ Error Renderer::initInternal(const ConfigSet& config)
 		m_resources->loadResource("shaders/Quad.vert.glsl", m_drawQuadVert));
 		m_resources->loadResource("shaders/Quad.vert.glsl", m_drawQuadVert));
 
 
 	// Init the stages. Careful with the order!!!!!!!!!!
 	// Init the stages. Careful with the order!!!!!!!!!!
-	Bool irEnabled = config.getNumber("ir.enabled");
-	if(irEnabled)
-	{
-		m_ir.reset(m_alloc.newInstance<Ir>(this));
-		ANKI_CHECK(m_ir->init(config));
-	}
-
 	m_ms.reset(m_alloc.newInstance<Ms>(this));
 	m_ms.reset(m_alloc.newInstance<Ms>(this));
 	ANKI_CHECK(m_ms->init(config));
 	ANKI_CHECK(m_ms->init(config));
 
 
@@ -120,6 +113,9 @@ Error Renderer::initInternal(const ConfigSet& config)
 	m_is.reset(m_alloc.newInstance<Is>(this));
 	m_is.reset(m_alloc.newInstance<Is>(this));
 	ANKI_CHECK(m_is->init(config));
 	ANKI_CHECK(m_is->init(config));
 
 
+	m_refl.reset(m_alloc.newInstance<Refl>(this));
+	ANKI_CHECK(m_refl->init(config));
+
 	m_fs.reset(m_alloc.newInstance<Fs>(this));
 	m_fs.reset(m_alloc.newInstance<Fs>(this));
 	ANKI_CHECK(m_fs->init(config));
 	ANKI_CHECK(m_fs->init(config));
 
 
@@ -165,10 +161,10 @@ Error Renderer::render(SceneNode& frustumableNode, U frustumIdx,
 	ANKI_ASSERT(m_frc->getFrustum().getType() == Frustum::Type::PERSPECTIVE);
 	ANKI_ASSERT(m_frc->getFrustum().getType() == Frustum::Type::PERSPECTIVE);
 	m_clusterer.prepare(getThreadPool(), *m_frc);
 	m_clusterer.prepare(getThreadPool(), *m_frc);
 
 
-	// Run reflection passes
-	if(m_ir.isCreated())
+	// First part of reflections
+	if(m_refl->getEnabled())
 	{
 	{
-		ANKI_CHECK(m_ir->run(cmdb[0]));
+		ANKI_CHECK(m_refl->run1(cmdb[0]));
 	}
 	}
 
 
 	ANKI_TRACE_START_EVENT(RENDER_MS);
 	ANKI_TRACE_START_EVENT(RENDER_MS);
@@ -186,6 +182,12 @@ Error Renderer::render(SceneNode& frustumableNode, U frustumIdx,
 	ANKI_CHECK(m_fs->run(cmdb[1]));
 	ANKI_CHECK(m_fs->run(cmdb[1]));
 	m_lf->run(cmdb[1]);
 	m_lf->run(cmdb[1]);
 
 
+	// 2nd part of reflections
+	if(m_refl->getEnabled())
+	{
+		m_refl->run2(cmdb[1]);
+	}
+
 	if(m_pps->getEnabled())
 	if(m_pps->getEnabled())
 	{
 	{
 		m_pps->run(cmdb[1]);
 		m_pps->run(cmdb[1]);

+ 0 - 142
src/renderer/Sslr.cpp

@@ -1,142 +0,0 @@
-// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/renderer/Sslr.h>
-#include <anki/renderer/Ssao.h>
-#include <anki/renderer/Ms.h>
-#include <anki/renderer/Is.h>
-#include <anki/renderer/Pps.h>
-#include <anki/renderer/Renderer.h>
-#include <anki/misc/ConfigSet.h>
-
-namespace anki {
-
-//==============================================================================
-Error Sslr::initInternal(const ConfigSet& config)
-{
-	m_enabled = config.getNumber("pps.sslr.enabled");
-
-	if(!m_enabled)
-	{
-		return ErrorCode::NONE;
-	}
-
-	// Size
-	const F32 quality = config.getNumber("pps.sslr.renderingQuality");
-
-	m_width = quality * (F32)m_r->getWidth();
-	alignRoundUp(16, m_width);
-	m_height = quality * (F32)m_r->getHeight();
-	alignRoundUp(16, m_height);
-
-	// Programs
-	StringAuto pps(getAllocator());
-
-	pps.sprintf(
-		"#define WIDTH %u\n"
-		"#define HEIGHT %u\n",
-		m_width, m_height);
-
-	ANKI_CHECK(getResourceManager().loadResourceToCache(m_reflectionFrag,
-		"shaders/PpsSslr.frag.glsl", pps.toCString(), "r_"));
-
-	ColorStateInfo colorState;
-	colorState.m_attachmentCount = 1;
-	colorState.m_attachments[0].m_format = Is::RT_PIXEL_FORMAT;
-
-	m_r->createDrawQuadPipeline(
-		m_reflectionFrag->getGrShader(), colorState, m_reflectionPpline);
-
-	// Blit
-	ANKI_CHECK(getResourceManager().loadResource(
-		"shaders/Blit.frag.glsl", m_blitFrag));
-
-	colorState.m_attachmentCount = 1;
-	colorState.m_attachments[0].m_format = Is::RT_PIXEL_FORMAT;
-	colorState.m_attachments[0].m_srcBlendMethod = BlendMethod::ONE;
-	colorState.m_attachments[0].m_dstBlendMethod = BlendMethod::ONE;
-
-	m_r->createDrawQuadPipeline(
-		m_blitFrag->getGrShader(), colorState, m_blitPpline);
-
-	// Init FBOs
-	m_r->createRenderTarget(m_width, m_height,
-		Is::RT_PIXEL_FORMAT, 1, SamplingFilter::LINEAR, 1, m_rt);
-
-	// Create FB
-	FramebufferInitializer fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
-	fbInit.m_colorAttachments[0].m_texture = m_rt;
-	fbInit.m_colorAttachments[0].m_loadOperation =
-		AttachmentLoadOperation::DONT_CARE;
-	m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
-
-	// Create resource groups
-	ResourceGroupInitializer rcInit;
-	rcInit.m_textures[0].m_texture = m_r->getIs().getRt();
-	rcInit.m_textures[1].m_texture = m_r->getMs().getDepthRt();
-	rcInit.m_textures[2].m_texture = m_r->getMs().getRt1();
-	rcInit.m_textures[3].m_texture = m_r->getMs().getRt2();
-
-	rcInit.m_uniformBuffers[0].m_buffer =
-		m_r->getPps().getSsao().getUniformBuffer();
-
-	m_rcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
-
-	ResourceGroupInitializer rcInitBlit;
-	rcInitBlit.m_textures[0].m_texture = m_rt;
-
-	m_rcGroupBlit = getGrManager().newInstance<ResourceGroup>(rcInitBlit);
-
-	// Create IS FB
-	fbInit.m_colorAttachmentsCount = 1;
-	fbInit.m_colorAttachments[0].m_texture = m_r->getIs().getRt();
-	fbInit.m_colorAttachments[0].m_loadOperation =
-		AttachmentLoadOperation::LOAD;
-	m_isFb = getGrManager().newInstance<Framebuffer>(fbInit);
-
-	getGrManager().finish();
-	return ErrorCode::NONE;
-}
-
-//==============================================================================
-Error Sslr::init(const ConfigSet& config)
-{
-	Error err = initInternal(config);
-
-	if(err)
-	{
-		ANKI_LOGE("Failed to init PPS SSLR");
-	}
-
-	return err;
-}
-
-//==============================================================================
-void Sslr::run(CommandBufferPtr& cmdBuff)
-{
-	ANKI_ASSERT(m_enabled);
-
-	// Compute the reflection
-	//
-	cmdBuff->bindFramebuffer(m_fb);
-	cmdBuff->setViewport(0, 0, m_width, m_height);
-	cmdBuff->bindPipeline(m_reflectionPpline);
-	cmdBuff->bindResourceGroup(m_rcGroup, 0, nullptr);
-
-	m_r->drawQuad(cmdBuff);
-
-	// Write the reflection back to IS RT
-	//
-	cmdBuff->bindFramebuffer(m_isFb);
-	cmdBuff->bindPipeline(m_blitPpline);
-	cmdBuff->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
-	cmdBuff->bindResourceGroup(m_rcGroupBlit, 0, nullptr);
-
-	m_r->drawQuad(cmdBuff);
-}
-
-} // end namespace anki
-

+ 0 - 3
testapp/Main.cpp

@@ -494,9 +494,6 @@ Error initSubsystems(int argc, char* argv[])
 	config.set("pps.bloom.threshold", 2.0);
 	config.set("pps.bloom.threshold", 2.0);
 	config.set("pps.bloom.scale", 2.0);
 	config.set("pps.bloom.scale", 2.0);
 	config.set("pps.bloom.samples", 17);
 	config.set("pps.bloom.samples", 17);
-	config.set("pps.sslr.enabled", true);
-	config.set("pps.sslr.renderingQuality", 0.25);
-	config.set("pps.sslr.blurringIterationsCount", 0);
 	config.set("pps.ssao.blurringIterationsCount", 2);
 	config.set("pps.ssao.blurringIterationsCount", 2);
 	config.set("pps.ssao.enabled", true);
 	config.set("pps.ssao.enabled", true);
 	config.set("pps.ssao.renderingQuality", 0.35);
 	config.set("pps.ssao.renderingQuality", 0.35);