فهرست منبع

Renderer work

Panagiotis Christopoulos Charitos 10 سال پیش
والد
کامیت
2875a862f8

+ 2 - 2
include/anki/misc/ConfigSet.h

@@ -27,7 +27,7 @@ public:
 		}
 		else
 		{
-			ANKI_LOGE("Option not found");
+			ANKI_LOGE("Option not found: %s", name);
 			return 0.0;
 		}
 	}
@@ -42,7 +42,7 @@ public:
 		}
 		else
 		{
-			ANKI_LOGE("Option not found");
+			ANKI_LOGE("Option not found: %s", name);
 		}
 	}
 

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

@@ -33,7 +33,7 @@ public:
 	~Bloom();
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
-	ANKI_USE_RESULT Error run(CommandBufferHandle& jobs);
+	void run(CommandBufferHandle& jobs);
 
 	U32 getBlurringIterationsCount() const
 	{

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

@@ -14,6 +14,8 @@ namespace anki {
 class Fs;
 class Tm;
 class Bloom;
+class Lf;
+class Sslf;
 
 // Render target formats
 const U MS_COLOR_ATTACHMENTS_COUNT = 2;

+ 5 - 0
include/anki/renderer/Is.h

@@ -50,6 +50,11 @@ public:
 	{
 		return m_rt;
 	}
+
+	void generateMipmaps(CommandBufferHandle& cmdb)
+	{
+		m_rt.generateMipmaps(cmdb);
+	}
 	/// @}
 
 private:

+ 6 - 28
include/anki/renderer/Lf.h

@@ -29,27 +29,14 @@ public:
 
 	~Lf();
 
-	const TextureHandle& _getRt() const
-	{
-		return m_rt;
-	}
+	ANKI_USE_RESULT Error init(const ConfigSet& config);
 
-	TextureHandle& _getRt()
-	{
-		return m_rt;
-	}
+	void runOcclusionTests(CommandBufferHandle& cmdb);
 
-	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
-
-	ANKI_USE_RESULT Error runOcclusionTests(CommandBufferHandle& cmdb);
-
-	ANKI_USE_RESULT Error run(CommandBufferHandle& jobs);
+	void run(CommandBufferHandle& cmdb);
 	/// @}
 
 private:
-	TextureHandle m_rt;
-	FramebufferHandle m_fb;
-
 	// Occlusion query
 	Array<BufferHandle, 3> m_positionsVertBuff;
 	BufferHandle m_mvpBuff;
@@ -57,25 +44,16 @@ private:
 	ShaderResourcePointer m_occlusionFrag;
 	PipelineHandle m_occlusionPpline;
 
-	// Pseudo flares
-	ShaderResourcePointer m_pseudoFrag;
-	PipelineHandle m_pseudoPpline;
-	TextureResourcePointer m_lensDirtTex;
-	U8 m_maxSpritesPerFlare;
-	U8 m_maxFlares;
-
 	// Sprite billboards
 	ShaderResourcePointer m_realVert;
 	ShaderResourcePointer m_realFrag;
 	PipelineHandle m_realPpline;
 	Array<BufferHandle, 3> m_flareDataBuff;
 	U32 m_flareSize;
+	U8 m_maxSpritesPerFlare;
+	U8 m_maxFlares;
+	
 
-	// Final HDR blit
-	ShaderResourcePointer m_blitFrag;
-	PipelineHandle m_blitPpline;
-
-	ANKI_USE_RESULT Error initPseudo(const ConfigSet& config);
 	ANKI_USE_RESULT Error initSprite(const ConfigSet& config);
 	ANKI_USE_RESULT Error initOcclusion(const ConfigSet& config);
 

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

@@ -42,6 +42,8 @@ public:
 	{
 		return m_planes[1].m_fb;
 	}
+
+	void generateMipmaps(CommandBufferHandle& cmdb);
 	/// @}
 
 private:

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

@@ -12,7 +12,6 @@
 #include "anki/resource/Resource.h"
 #include "anki/renderer/Ssao.h"
 #include "anki/renderer/Bl.h"
-#include "anki/renderer/Lf.h"
 #include "anki/renderer/Sslr.h"
 
 namespace anki {
@@ -57,15 +56,6 @@ public:
 		return m_bl;
 	}
 
-	const Lf& getLf() const
-	{
-		return m_lf;
-	}
-	Lf& getLf()
-	{
-		return m_lf;
-	}
-
 	const Sslr& getSslr() const
 	{
 		return m_sslr;
@@ -103,9 +93,9 @@ public:
 private:
 	Tm* m_tm = nullptr;
 	Bloom* m_bloom;
+	Sslf* m_sslf;
 	Ssao m_ssao;
 	Bl m_bl;
-	Lf m_lf;
 	Sslr m_sslr;
 
 	FramebufferHandle m_fb;

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

@@ -282,6 +282,7 @@ private:
 	Is m_is; ///< Illumination rendering stage
 	Pps m_pps; ///< Postprocessing rendering stage
 	Fs* m_fs = nullptr; ///< Forward shading.
+	Lf* m_lf = nullptr; ///< Forward shading lens flares.
 	Dbg m_dbg; ///< Debug stage
 	Tiler m_tiler;
 	/// @}

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

@@ -37,8 +37,6 @@ private:
 	ShaderResourcePointer m_frag;
 	PipelineHandle m_ppline;
 	TextureResourcePointer m_lensDirtTex;
-	U8 m_maxSpritesPerFlare;
-	U8 m_maxFlares;
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& config);
 };

+ 1 - 1
shaders/PpsLfOcclusion.frag.glsl → shaders/LfOcclusion.frag.glsl

@@ -3,7 +3,7 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-// PPS LF occlusion frag shader
+// LF occlusion frag shader
 
 #pragma anki type frag
 #pragma anki include "shaders/Common.glsl"

+ 4 - 2
shaders/PpsLfOcclusion.vert.glsl → shaders/LfOcclusion.vert.glsl

@@ -3,8 +3,10 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-// PPS LF occlusion vert shader
+// LF occlusion vert shader
+
 #pragma anki type vert
+#pragma anki include "shaders/Common.glsl"
 
 layout(std140) uniform _block
 {
@@ -22,6 +24,6 @@ out gl_PerVertex
 void main()
 {
 	gl_Position = u_mvp * vec4(in_position, 1.0);
-	gl_PointSize = 8.0;
+	gl_PointSize = 16.0;
 }
 

+ 1 - 1
shaders/PpsLfSpritePass.frag.glsl → shaders/LfSpritePass.frag.glsl

@@ -3,7 +3,7 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-// PPS LF sprites frag shader
+// LF sprites frag shader
 
 #pragma anki type frag
 #pragma anki include "shaders/Common.glsl"

+ 3 - 1
shaders/PpsLfSpritePass.vert.glsl → shaders/LfSpritePass.vert.glsl

@@ -3,8 +3,10 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-// PPS LF sprites vert shader
+// LF sprites vert shader
+
 #pragma anki type vert
+#pragma anki include "shaders/Common.glsl"
 
 // Per flare information
 struct Flare

+ 10 - 48
shaders/Pps.frag.glsl

@@ -12,6 +12,7 @@ layout(binding = 0) uniform lowp sampler2D u_isRt;
 layout(binding = 1) uniform lowp sampler2D u_ppsSsaoRt;
 layout(binding = 2) uniform lowp sampler2D u_ppsBloomLfRt;
 layout(binding = 3) uniform lowp sampler3D u_lut;
+layout(binding = 4) uniform lowp sampler2D u_ppsSslfRt;
 
 layout(std140, binding = 0) readonly buffer _blk
 {
@@ -105,59 +106,13 @@ vec3 colorGrading(in vec3 color)
 	return textureLod(u_lut, lutCoords, 0.0).rgb;
 }
 
-#if 0
-//==============================================================================
-// Uncharted 2 tonemap operator
-// @param l Luminance
-float uncharted2TonemapOperator(in float l)
-{
-	const float A = 0.15;
-	const float B = 0.50;
-	const float C = 0.10;
-	const float D = 0.20;
-	const float E = 0.02;
-	const float F = 0.30;
-
-	return ((l * (A * l + C * B) + D * E) / (l * (A * l + B) + D * F)) - E / F;
-}
-
-//==============================================================================
-vec3 tonemap(in vec3 color)
-{
-	const float KEY = 0.08;
-	const float WHITE = 11.2;
-	const float SATURATION = 1.0;
-
-	const mat3 RGB2XYZ = mat3(
-		0.4124564, 0.3575761, 0.1804375, 
-		0.2126729, 0.7151522, 0.0721750, 
-		0.0193339, 0.1191920, 0.9503041);
-
-	float L = dot(vec3(0.30, 0.59, 0.11), color);
-
-	float avgLum = u_averageLuminancePad3.x;
-	float l = (KEY / avgLum) * L;
-
-#if 0
-	// Reinhart operator
-	float ld = l * (1.0 + l / (WHITE * WHITE)) / (1.0 + l);
-#else
-	// Uncharted 2 operator
-	float ld = uncharted2TonemapOperator(l) / uncharted2TonemapOperator(WHITE);
-#endif
-
-	return pow(color / l, vec3(SATURATION)) * ld;
-}
-#endif
-
 //==============================================================================
 void main()
 {
 #if SHARPEN_ENABLED
 	out_color = sharpen(u_isRt, in_texCoords);
 #else
-	out_color = textureRt(u_isRt, in_texCoords).rgb;
-	out_color = tonemap(out_color, u_averageLuminancePad3.x, 0.0);
+	out_color = textureLod(u_isRt, in_texCoords, 0.0).rgb;
 #endif
 
 #if SSAO_ENABLED
@@ -165,17 +120,24 @@ void main()
 	out_color *= ssao;
 #endif
 
+	out_color = tonemap(out_color, u_averageLuminancePad3.x, 0.0);
+
 #if BLOOM_ENABLED
 	vec3 bloom = textureRt(u_ppsBloomLfRt, in_texCoords).rgb;
 	out_color += bloom;
 #endif
 
+#if SSLF_ENABLED
+	vec3 sslf = textureRt(u_ppsSslfRt, in_texCoords).rgb;
+	out_color += sslf;
+#endif
+
 	out_color = colorGrading(out_color);
 
 #if 0
 	if(out_color.x != 0.0000001)
 	{
-		out_color = hdr;
+		out_color = vec3(mip);
 	}
 #endif
 }

+ 0 - 0
shaders/PpsLfPseudoPass.frag.glsl → shaders/PpsSslf.frag.glsl


+ 4 - 3
src/core/Config.cpp

@@ -31,6 +31,9 @@ Config::Config()
 	newOption("is.maxSpotTexLights", 8);
 	newOption("is.maxLightsPerTile", 16);
 
+	newOption("lf.maxSpritesPerFlare", 8);
+	newOption("lf.maxFlares", 16);
+
 	// Pps
 	newOption("pps.bloom.enabled", true);
 	newOption("pps.bloom.renderingQuality", 0.5);
@@ -52,9 +55,7 @@ Config::Config()
 	newOption("pps.bl.blurringIterationsCount", 1);
 	newOption("pps.bl.sideBlurFactor", 1.0);
 
-	newOption("pps.lf.enabled", true);
-	newOption("pps.lf.maxSpritesPerFlare", 8);
-	newOption("pps.lf.maxFlares", 16);
+	newOption("pps.sslf.enabled", true);
 
 	newOption("pps.enabled", true);
 	newOption("pps.sharpen", true);

+ 1 - 3
src/renderer/Bloom.cpp

@@ -131,7 +131,7 @@ Error Bloom::init(const ConfigSet& initializer)
 }
 
 //==============================================================================
-Error Bloom::run(CommandBufferHandle& cmdb)
+void Bloom::run(CommandBufferHandle& cmdb)
 {
 	ANKI_ASSERT(m_enabled);
 
@@ -178,8 +178,6 @@ Error Bloom::run(CommandBufferHandle& cmdb)
 
 	// For the next stage it should be LINEAR though
 	//vblurFai.setFiltering(Texture::TFrustumType::LINEAR);
-
-	return ErrorCode::NONE;
 }
 
 //==============================================================================

+ 0 - 2
src/renderer/Is.cpp

@@ -463,8 +463,6 @@ Error Is::lightPass(CommandBufferHandle& cmdBuff)
 
 	cmdBuff.drawArrays(GL_TRIANGLE_STRIP, 4, m_r->getTilesCountXY());
 
-	m_rt.generateMipmaps(cmdBuff);
-
 	return err;
 }
 

+ 11 - 107
src/renderer/Lf.cpp

@@ -50,51 +50,27 @@ Error Lf::init(const ConfigSet& config)
 }
 
 //==============================================================================
-Error Lf::initPseudo(const ConfigSet& config)
+Error Lf::initSprite(const ConfigSet& config)
 {
-	m_maxSpritesPerFlare = config.get("pps.lf.maxSpritesPerFlare");
-	m_maxFlares = config.get("pps.lf.maxFlares");
+	m_maxSpritesPerFlare = config.get("lf.maxSpritesPerFlare");
+	m_maxFlares = config.get("lf.maxFlares");
 
 	if(m_maxSpritesPerFlare < 1 || m_maxFlares < 1)
 	{
 		ANKI_LOGE("Incorrect m_maxSpritesPerFlare or m_maxFlares");
 		return ErrorCode::USER_DATA;
 	}
-
-	// Load program 1
-	StringAuto pps(getAllocator());
-
-	pps.sprintf(
-		"#define TEX_DIMENSIONS vec2(%u.0, %u.0)\n", 
-		m_r->getPps().getBloom().getWidth(),
-		m_r->getPps().getBloom().getHeight());
-
-	ANKI_CHECK(m_pseudoFrag.loadToCache(&getResourceManager(), 
-		"shaders/PpsLfPseudoPass.frag.glsl", pps.toCString(), "r_"));
-
-	ANKI_CHECK(m_r->createDrawQuadPipeline(
-		m_pseudoFrag->getGrShader(), m_pseudoPpline));
-
-	// Textures
-	ANKI_CHECK(m_lensDirtTex.load(
-		"engine_data/lens_dirt.ankitex", &getResourceManager()));
-
-	return ErrorCode::NONE;
-}
-
-//==============================================================================
-Error Lf::initSprite(const ConfigSet& config)
-{
+	
 	// Load program + ppline
 	StringAuto pps(getAllocator());
 
 	pps.sprintf("#define MAX_SPRITES %u\n", m_maxSpritesPerFlare);
 
 	ANKI_CHECK(m_realVert.loadToCache(&getResourceManager(), 
-		"shaders/PpsLfSpritePass.vert.glsl", pps.toCString(), "r_"));
+		"shaders/LfSpritePass.vert.glsl", pps.toCString(), "r_"));
 
 	ANKI_CHECK(m_realFrag.loadToCache(&getResourceManager(), 
-		"shaders/PpsLfSpritePass.frag.glsl", pps.toCString(), "r_"));
+		"shaders/LfSpritePass.frag.glsl", pps.toCString(), "r_"));
 
 	PipelineHandle::Initializer init;
 	init.m_shaders[U(ShaderType::VERTEX)] = m_realVert->getGrShader();
@@ -136,10 +112,10 @@ Error Lf::initOcclusion(const ConfigSet& config)
 		nullptr, sizeof(Mat4), GL_DYNAMIC_STORAGE_BIT));
 
 	// Shaders
-	ANKI_CHECK(m_occlusionVert.load("shaders/PpsLfOcclusion.vert.glsl",
+	ANKI_CHECK(m_occlusionVert.load("shaders/LfOcclusion.vert.glsl",
 		&getResourceManager()));
 
-	ANKI_CHECK(m_occlusionFrag.load("shaders/PpsLfOcclusion.frag.glsl",
+	ANKI_CHECK(m_occlusionFrag.load("shaders/LfOcclusion.frag.glsl",
 		&getResourceManager()));
 
 	PipelineHandle::Initializer init;
@@ -154,45 +130,15 @@ Error Lf::initOcclusion(const ConfigSet& config)
 //==============================================================================
 Error Lf::initInternal(const ConfigSet& config)
 {
-	m_enabled = config.get("pps.lf.enabled") 
-		&& config.get("pps.bloom.enabled");
-	if(!m_enabled)
-	{
-		return ErrorCode::NONE;
-	}
-
-	ANKI_CHECK(initPseudo(config));
 	ANKI_CHECK(initSprite(config));
 	ANKI_CHECK(initOcclusion(config));
 
-	// Create the render target
-	ANKI_CHECK(m_r->createRenderTarget(m_r->getPps().getBloom().getWidth(), 
-		m_r->getPps().getBloom().getHeight(), 
-		PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM), 
-		1, SamplingFilter::LINEAR, 1, m_rt));
-
-	FramebufferHandle::Initializer fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
-	fbInit.m_colorAttachments[0].m_texture = m_rt;
-	fbInit.m_colorAttachments[0].m_loadOperation = 
-		AttachmentLoadOperation::DONT_CARE;
-	ANKI_CHECK(m_fb.create(&getGrManager(), fbInit));
-
-	// Blit
-	ANKI_CHECK(
-		m_blitFrag.load("shaders/Blit.frag.glsl", &getResourceManager()));
-
-	ANKI_CHECK(m_r->createDrawQuadPipeline(
-		m_blitFrag->getGrShader(), m_blitPpline));
-
 	return ErrorCode::NONE;
 }
 
 //==============================================================================
-Error Lf::runOcclusionTests(CommandBufferHandle& cmdb)
+void Lf::runOcclusionTests(CommandBufferHandle& cmdb)
 {
-	ANKI_ASSERT(m_enabled);
-
 	// Retrieve some things
 	SceneGraph& scene = m_r->getSceneGraph();
 	Camera& cam = scene.getActiveCamera();
@@ -258,38 +204,11 @@ Error Lf::runOcclusionTests(CommandBufferHandle& cmdb)
 		cmdb.setDepthWriteMask(true);
 		cmdb.enableDepthTest(false);
 	}
-
-	return ErrorCode::NONE;
 }
 
 //==============================================================================
-Error Lf::run(CommandBufferHandle& cmdb)
+void Lf::run(CommandBufferHandle& cmdb)
 {
-	ANKI_ASSERT(m_enabled);
-	Error err = ErrorCode::NONE;
-
-	//
-	// First pass
-	//
-
-	// Set the common state
-	m_fb.bind(cmdb);
-	cmdb.setViewport(0, 0, m_r->getPps().getBloom().getWidth(), 
-		m_r->getPps().getBloom().getHeight());
-
-	m_pseudoPpline.bind(cmdb);
-
-	Array<TextureHandle, 2> tarr = {{
-		m_r->getPps().getBloom().getRt(), 
-		m_lensDirtTex->getGlTexture()}};
-	cmdb.bindTextures(0, tarr.begin(), tarr.getSize());
-
-	m_r->drawQuad(cmdb);
-
-	//
-	// Rest of the passes
-	//
-
 	// Retrieve some things
 	SceneGraph& scene = m_r->getSceneGraph();
 	Camera& cam = scene.getActiveCamera();
@@ -385,24 +304,9 @@ Error Lf::run(CommandBufferHandle& cmdb)
 
 		ANKI_ASSERT(
 			reinterpret_cast<U8*>(sprites) <= spritesInitialPtr + bufferSize);
-	}
-	else
-	{
-		// No flares
 
-		cmdb.enableBlend(true);
-		cmdb.setBlendFunctions(GL_ONE, GL_ONE);
+		cmdb.enableBlend(false);
 	}
-
-	// Blit the HDR RT back to LF RT
-	//
-	m_r->getPps().getBloom().getRt().bind(cmdb, 0);
-	m_blitPpline.bind(cmdb);
-	m_r->drawQuad(cmdb);
-
-	cmdb.enableBlend(false);
-
-	return err;
 }
 
 } // end namespace anki

+ 8 - 3
src/renderer/Ms.cpp

@@ -25,7 +25,7 @@ Error Ms::createRt(U32 index, U32 samples)
 
 	ANKI_CHECK(m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(),
 		PixelFormat(ComponentFormat::D24, TransformFormat::FLOAT),
-		samples, SamplingFilter::NEAREST, 1, plane.m_depthRt));
+		samples, SamplingFilter::NEAREST, 4, plane.m_depthRt));
 
 	ANKI_CHECK(m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), 
 		PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM),
@@ -139,11 +139,16 @@ Error Ms::run(CommandBufferHandle& cmdb)
 		ANKI_ASSERT(0 && "TODO");
 	}
 
-	m_planes[planeId].m_depthRt.generateMipmaps(cmdb);
-
 	cmdb.enableDepthTest(false);
 
 	return ErrorCode::NONE;
 }
 
+//==============================================================================
+void Ms::generateMipmaps(CommandBufferHandle& cmdb)
+{
+	U planeId = (m_r->getSamples() == 1) ? 1 : 0;
+	m_planes[planeId].m_depthRt.generateMipmaps(cmdb);
+}
+
 } // end namespace anki

+ 23 - 10
src/renderer/Pps.cpp

@@ -6,8 +6,10 @@
 #include "anki/renderer/Pps.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Bloom.h"
+#include "anki/renderer/Sslf.h"
 #include "anki/renderer/Ssao.h"
 #include "anki/renderer/Tm.h"
+#include "anki/renderer/Is.h"
 #include "anki/util/Logger.h"
 #include "anki/misc/ConfigSet.h"
 
@@ -18,7 +20,6 @@ Pps::Pps(Renderer* r)
 :	RenderingPass(r), 
 	m_ssao(r), 
 	m_bl(r), 
-	m_lf(r),
 	m_sslr(r)
 {}
 
@@ -30,6 +31,12 @@ Pps::~Pps()
 		getAllocator().deleteInstance(m_tm);
 		m_tm = nullptr;
 	}
+
+	if(m_bloom)
+	{
+		getAllocator().deleteInstance(m_bloom);
+		m_bloom = nullptr;
+	}
 }
 
 //==============================================================================
@@ -51,7 +58,9 @@ Error Pps::initInternal(const ConfigSet& config)
 	m_bloom = getAllocator().newInstance<Bloom>(m_r);
 	ANKI_CHECK(m_bloom->init(config));
 
-	ANKI_CHECK(m_lf.init(config));
+	m_sslf = getAllocator().newInstance<Sslf>(m_r);
+	ANKI_CHECK(m_sslf->init(config));
+
 	ANKI_CHECK(m_sslr.init(config));
 
 	// FBO
@@ -74,12 +83,14 @@ Error Pps::initInternal(const ConfigSet& config)
 	pps.sprintf(
 		"#define SSAO_ENABLED %u\n"
 		"#define BLOOM_ENABLED %u\n"
+		"#define SSLF_ENABLED %u\n"
 		"#define SHARPEN_ENABLED %u\n"
 		"#define GAMMA_CORRECTION_ENABLED %u\n"
 		"#define FBO_WIDTH %u\n"
 		"#define FBO_HEIGHT %u\n",
 		m_ssao.getEnabled(), 
-		m_bloom->getEnabled(), 
+		m_bloom->getEnabled(),
+		m_sslf->getEnabled(),
 		U(config.get("pps.sharpen")),
 		U(config.get("pps.gammaCorrection")),
 		m_r->getWidth(),
@@ -131,16 +142,17 @@ Error Pps::run(CommandBufferHandle& cmdb)
 		ANKI_CHECK(m_sslr.run(cmdb));
 	}
 
+	m_r->getIs().generateMipmaps(cmdb);
 	m_tm->run(cmdb);
 
 	if(m_bloom->getEnabled())
 	{
-		ANKI_CHECK(m_bloom->run(cmdb));
+		m_bloom->run(cmdb);
 	}
 
-	if(m_lf.getEnabled())
+	if(m_sslf->getEnabled())
 	{
-		ANKI_CHECK(m_lf.run(cmdb));
+		m_sslf->run(cmdb);
 	}
 
 	Bool drawToDefaultFbo = 
@@ -170,13 +182,14 @@ Error Pps::run(CommandBufferHandle& cmdb)
 		m_ssao._getRt().bind(cmdb, 1);
 	}
 
-	if(m_lf.getEnabled())
+	if(m_bloom->getEnabled())
 	{
-		m_lf._getRt().bind(cmdb, 2);
+		m_bloom->getRt().bind(cmdb, 2);
 	}
-	else if(m_bloom->getEnabled())
+
+	if(m_sslf->getEnabled())
 	{
-		m_bloom->getRt().bind(cmdb, 2);
+		m_sslf->getRt().bind(cmdb, 4);
 	}
 
 	m_lut->getGlTexture().bind(cmdb, 3);

+ 22 - 7
src/renderer/Renderer.cpp

@@ -10,6 +10,8 @@
 #include "anki/misc/ConfigSet.h"
 
 #include "anki/renderer/Fs.h"
+#include "anki/renderer/Lf.h"
+#include "anki/renderer/Is.h"
 
 namespace anki {
 
@@ -26,6 +28,16 @@ Renderer::Renderer()
 Renderer::~Renderer()
 {
 	m_shadersPrependedSource.destroy(m_alloc);
+
+	if(m_fs)
+	{
+		m_alloc.deleteInstance(m_fs);
+	}
+
+	if(m_lf)
+	{
+		m_alloc.deleteInstance(m_lf);
+	}
 }
 
 //==============================================================================
@@ -128,6 +140,10 @@ Error Renderer::initInternal(const ConfigSet& config)
 	
 	m_fs = m_alloc.newInstance<Fs>(this);
 	ANKI_CHECK(m_fs->init(config));
+
+	m_lf = m_alloc.newInstance<Lf>(this);
+	ANKI_CHECK(m_lf->init(config));
+
 	ANKI_CHECK(m_pps.init(config));
 	ANKI_CHECK(m_dbg.init(config));
 
@@ -162,22 +178,21 @@ Error Renderer::render(SceneGraph& scene,
 
 	ANKI_COUNTER_START_TIMER(RENDERER_MS_TIME);
 	ANKI_CHECK(m_ms.run(cmdBuff[0]));
-	
 	ANKI_COUNTER_STOP_TIMER_INC(RENDERER_MS_TIME);
 
+	m_lf->runOcclusionTests(cmdBuff[0]);
+
+	m_ms.generateMipmaps(cmdBuff[0]);
+
 	m_tiler.runMinMax(m_ms._getDepthRt(), cmdBuff[0]);
 	cmdBuff[0].flush();
 
-	if(m_pps.getEnabled() && m_pps.getLf().getEnabled())
-	{
-		ANKI_CHECK(m_pps.getLf().runOcclusionTests(cmdBuff[1]));
-	}
-
 	ANKI_COUNTER_START_TIMER(RENDERER_IS_TIME);
 	ANKI_CHECK(m_is.run(cmdBuff[1]));
 	ANKI_COUNTER_STOP_TIMER_INC(RENDERER_IS_TIME);
 
-	ANKI_CHECK(m_fs->run(cmdBuff[1])); 
+	ANKI_CHECK(m_fs->run(cmdBuff[1]));
+	m_lf->run(cmdBuff[1]);
 
 	ANKI_COUNTER_START_TIMER(RENDERER_PPS_TIME);
 	if(m_pps.getEnabled())

+ 11 - 1
src/renderer/Sslf.cpp

@@ -7,6 +7,7 @@
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Pps.h"
 #include "anki/renderer/Bloom.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -25,6 +26,12 @@ Error Sslf::init(const ConfigSet& config)
 //==============================================================================
 Error Sslf::initInternal(const ConfigSet& config)
 {
+	m_enabled = config.get("pps.sslf.enabled");
+	if(!m_enabled)
+	{
+		return ErrorCode::NONE;
+	}
+
 	// Load program 1
 	StringAuto pps(getAllocator());
 
@@ -34,7 +41,7 @@ Error Sslf::initInternal(const ConfigSet& config)
 		m_r->getPps().getBloom().getHeight());
 
 	ANKI_CHECK(m_frag.loadToCache(&getResourceManager(), 
-		"shaders/PpsLfPseudoPass.frag.glsl", pps.toCString(), "r_"));
+		"shaders/PpsSslf.frag.glsl", pps.toCString(), "r_"));
 
 	ANKI_CHECK(m_r->createDrawQuadPipeline(m_frag->getGrShader(), m_ppline));
 
@@ -61,6 +68,9 @@ Error Sslf::initInternal(const ConfigSet& config)
 //==============================================================================
 void Sslf::run(CommandBufferHandle& cmdb)
 {
+	ANKI_ASSERT(m_enabled);
+	
+	// Draw to the SSLF FB
 	m_fb.bind(cmdb);
 	cmdb.setViewport(0, 0, m_r->getPps().getBloom().getWidth(), 
 		m_r->getPps().getBloom().getHeight());

+ 3 - 3
testapp/Main.cpp

@@ -496,8 +496,8 @@ Error initSubsystems(int argc, char* argv[])
 	config.set("pps.bloom.threshold", 2.0);
 	config.set("pps.bloom.scale", 2.0);
 	config.set("pps.bloom.samples", 17);
-	config.set("pps.sslr.enabled", false);
-	config.set("pps.sslr.renderingQuality", 0.5);
+	config.set("pps.sslr.enabled", true);
+	config.set("pps.sslr.renderingQuality", 0.25);
 	config.set("pps.sslr.blurringIterationsCount", 1);
 	config.set("pps.ssao.blurringIterationsCount", 2);
 	config.set("pps.ssao.enabled", true);
@@ -505,7 +505,7 @@ Error initSubsystems(int argc, char* argv[])
 	config.set("pps.bl.enabled", true);
 	config.set("pps.bl.blurringIterationsCount", 2);
 	config.set("pps.bl.sideBlurFactor", 1.0);
-	config.set("pps.lf.enabled", true);
+	config.set("pps.sslf.enabled", true);
 	config.set("pps.sharpen", false);
 	config.set("renderingQuality", 1.0);
 	config.set("width", 1280);

+ 29 - 3
tools/scene/Exporter.cpp

@@ -13,7 +13,7 @@
 static const char* XML_HEADER = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
 
 //==============================================================================
-static aiColor3D srgbToLinear(const aiColor3D& in)
+static aiColor3D srgbToLinear(aiColor3D in)
 {
 	const float p = 1.0 / 2.4;
 	aiColor3D out;
@@ -24,6 +24,32 @@ static aiColor3D srgbToLinear(const aiColor3D& in)
 	return out;
 }
 
+//==============================================================================
+/// Convert from sRGB to linear and preserve energy
+static aiColor3D computeLightColor(aiColor3D in)
+{
+	float energy = std::max(std::max(in[0], in[1]), in[2]);
+
+	if(energy > 1.0)
+	{
+		in[0] /= energy;
+		in[1] /= energy;
+		in[2] /= energy;
+	}
+	else
+	{
+		energy = 1.0;
+	}
+
+	in = srgbToLinear(in);
+
+	in[0] *= energy;
+	in[1] *= energy;
+	in[2] *= energy;
+	
+	return in;
+}
+
 //==============================================================================
 static std::string getMaterialName(const aiMaterial& mtl, bool instanced)
 {
@@ -640,14 +666,14 @@ void Exporter::exportLight(const aiLight& light)
 	file << "lcomp = node:getSceneNodeBase():getLightComponent()\n";
 
 	// Colors
-	aiColor3D linear = srgbToLinear(light.mColorDiffuse);
+	aiColor3D linear = computeLightColor(light.mColorDiffuse);
 	file << "lcomp:setDiffuseColor(Vec4.new("
 		<< linear[0] << ", " 
 		<< linear[1] << ", " 
 		<< linear[2] << ", "
 		<< "1))\n";
 
-	linear = srgbToLinear(light.mColorSpecular);
+	linear = computeLightColor(light.mColorSpecular);
 	file << "lcomp:setSpecularColor(Vec4.new("
 		<< linear[0] << ", " 
 		<< linear[1] << ", "