Browse Source

Refactoring App. Optimizing fog

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
0f906560d2

+ 8 - 0
include/anki/AnKi.h

@@ -7,5 +7,13 @@
 
 
 #include <anki/Util.h>
 #include <anki/Util.h>
 #include <anki/Math.h>
 #include <anki/Math.h>
+#include <anki/Collision.h>
 #include <anki/Scene.h>
 #include <anki/Scene.h>
 #include <anki/Event.h>
 #include <anki/Event.h>
+#include <anki/Renderer.h>
+#include <anki/Script.h>
+#include <anki/Input.h>
+#include <anki/Resource.h>
+#include <anki/Physics.h>
+#include <anki/Gr.h>
+#include <anki/Core.h>

+ 9 - 0
include/anki/Core.h

@@ -0,0 +1,9 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/core/App.h>
+#include <anki/core/Config.h>

+ 8 - 0
include/anki/Input.h

@@ -0,0 +1,8 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/input/Input.h>

+ 10 - 0
include/anki/Physics.h

@@ -0,0 +1,10 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+/// @defgroup physics Physics subsystem
+
+#include <anki/physics/PhysicsWorld.h>

+ 1 - 0
include/anki/Renderer.h

@@ -9,5 +9,6 @@
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Pps.h>
 #include <anki/renderer/Pps.h>
 #include <anki/renderer/Dbg.h>
 #include <anki/renderer/Dbg.h>
+#include <anki/renderer/Volumetric.h>
 
 
 /// @defgroup renderer Renderering system
 /// @defgroup renderer Renderering system

+ 1 - 0
include/anki/Resource.h

@@ -16,3 +16,4 @@
 /// @ingroup resource
 /// @ingroup resource
 
 
 #include <anki/resource/ResourceManager.h>
 #include <anki/resource/ResourceManager.h>
+#include <anki/resource/Script.h>

+ 8 - 0
include/anki/Script.h

@@ -0,0 +1,8 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/script/ScriptManager.h>

+ 9 - 10
include/anki/core/App.h

@@ -40,12 +40,8 @@ class App
 	friend class GrManagerInterfaceImpl;
 	friend class GrManagerInterfaceImpl;
 
 
 public:
 public:
-	/// User callback of main loop
-	using UserMainLoopCallback = Error (*)(
-		App& app, void* userData, Bool& quit);
-
 	App();
 	App();
-	~App();
+	virtual ~App();
 
 
 	ANKI_USE_RESULT Error create(const ConfigSet& config,
 	ANKI_USE_RESULT Error create(const ConfigSet& config,
 		AllocAlignedCallback allocCb,
 		AllocAlignedCallback allocCb,
@@ -97,11 +93,14 @@ public:
 	}
 	}
 
 
 	/// Run the main loop.
 	/// Run the main loop.
-	/// @param callback The user callback to run along with the other main loop
-	///                 code.
-	/// @param userData The data to pass to the user callback.
-	ANKI_USE_RESULT Error mainLoop(
-		UserMainLoopCallback callback, void* userData);
+	ANKI_USE_RESULT Error mainLoop();
+
+	/// The user code to run along with the other main loop code.
+	virtual ANKI_USE_RESULT Error userMainLoop(Bool& quit)
+	{
+		// Do nothing
+		return ErrorCode::NONE;
+	}
 
 
 	Input& getInput()
 	Input& getInput()
 	{
 	{

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

@@ -28,6 +28,7 @@ class Tiler;
 class Ir;
 class Ir;
 class Upsample;
 class Upsample;
 class DownscaleBlur;
 class DownscaleBlur;
+class Volumetric;
 
 
 class RenderingContext;
 class RenderingContext;
 
 

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

@@ -21,12 +21,6 @@ public:
 	/// Load the color grading texture.
 	/// Load the color grading texture.
 	Error loadColorGradingTexture(CString filename);
 	Error loadColorGradingTexture(CString filename);
 
 
-	void setFog(const Vec3& color, F32 factor)
-	{
-		m_fogColor = color;
-		m_fogFactor = factor;
-	}
-
 anki_internal:
 anki_internal:
 	static const PixelFormat RT_PIXEL_FORMAT;
 	static const PixelFormat RT_PIXEL_FORMAT;
 
 
@@ -55,9 +49,6 @@ private:
 
 
 	TextureResourcePtr m_lut; ///< Color grading lookup texture.
 	TextureResourcePtr m_lut; ///< Color grading lookup texture.
 
 
-	Vec3 m_fogColor = Vec3(1.0);
-	F32 m_fogFactor = 1.0;
-
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& config);
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& config);
 };
 };
 /// @}
 /// @}

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

@@ -134,6 +134,11 @@ public:
 		return *m_fs;
 		return *m_fs;
 	}
 	}
 
 
+	Volumetric& getVolumetric()
+	{
+		return *m_vol;
+	}
+
 	Tm& getTm()
 	Tm& getTm()
 	{
 	{
 		return *m_tm;
 		return *m_tm;
@@ -390,6 +395,7 @@ private:
 	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<Fs> m_fs; ///< Forward shading.
 	UniquePtr<Fs> m_fs; ///< Forward shading.
+	UniquePtr<Volumetric> m_vol; ///< Volumetric effects.
 	UniquePtr<Lf> m_lf; ///< Forward shading lens flares.
 	UniquePtr<Lf> m_lf; ///< Forward shading lens flares.
 	UniquePtr<Upsample> m_upsample;
 	UniquePtr<Upsample> m_upsample;
 	UniquePtr<Tiler> m_tiler;
 	UniquePtr<Tiler> m_tiler;

+ 48 - 0
include/anki/renderer/Volumetric.h

@@ -0,0 +1,48 @@
+// Copyright (C) 2009-2016, 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
+{
+
+/// @addtogroup renderer
+/// @{
+
+/// Volumetric effects.
+class Volumetric : public RenderingPass
+{
+public:
+	void setFog(const Vec3& color, F32 factor)
+	{
+		m_fogColor = color;
+		m_fogFactor = factor;
+	}
+
+anki_internal:
+	Volumetric(Renderer* r)
+		: RenderingPass(r)
+	{
+	}
+
+	~Volumetric();
+
+	ANKI_USE_RESULT Error init(const ConfigSet& config);
+
+	void run(RenderingContext& ctx);
+
+private:
+	ShaderResourcePtr m_frag;
+	ResourceGroupPtr m_rcGroup;
+	PipelinePtr m_ppline;
+
+	Vec3 m_fogColor = Vec3(1.0);
+	F32 m_fogFactor = 1.0;
+};
+/// @}
+
+} // end namespace anki

+ 2 - 4
shaders/FsCommonFrag.glsl

@@ -5,18 +5,16 @@
 // Common code for all fragment shaders of BS
 // Common code for all fragment shaders of BS
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
 #include "shaders/MsFsCommon.glsl"
 #include "shaders/MsFsCommon.glsl"
-#include "shaders/LinearDepth.glsl"
+#include "shaders/Functions.glsl"
 #include "shaders/Clusterer.glsl"
 #include "shaders/Clusterer.glsl"
 
 
 // Global resources
 // Global resources
 layout(TEX_BINDING(1, 0)) uniform sampler2D anki_msDepthRt;
 layout(TEX_BINDING(1, 0)) uniform sampler2D anki_msDepthRt;
 #define LIGHT_SET 1
 #define LIGHT_SET 1
+#define LIGHT_UBO_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_TEX_BINDING 1
 #define LIGHT_TEX_BINDING 1
 #include "shaders/LightResources.glsl"
 #include "shaders/LightResources.glsl"
-#undef LIGHT_SET
-#undef LIGHT_SS_BINDING
-#undef LIGHT_TEX_BINDING
 
 
 #define anki_u_time u_lightingUniforms.rendererSizeTimePad1.z
 #define anki_u_time u_lightingUniforms.rendererSizeTimePad1.z
 #define RENDERER_SIZE (u_lightingUniforms.rendererSizeTimePad1.xy * 0.5)
 #define RENDERER_SIZE (u_lightingUniforms.rendererSizeTimePad1.xy * 0.5)

+ 1 - 0
shaders/FsCommonVert.glsl

@@ -10,6 +10,7 @@
 #define LIGHT_SET 1
 #define LIGHT_SET 1
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_TEX_BINDING 1
 #define LIGHT_TEX_BINDING 1
+#define LIGHT_UBO_BINDING 0
 #include "shaders/LightResources.glsl"
 #include "shaders/LightResources.glsl"
 #undef LIGHT_SET
 #undef LIGHT_SET
 #undef LIGHT_SS_BINDING
 #undef LIGHT_SS_BINDING

+ 14 - 0
shaders/Functions.glsl

@@ -32,4 +32,18 @@ float dither(in float col, in float C)
 	return col;
 	return col;
 }
 }
 
 
+//==============================================================================
+// Convert to linear depth
+float linearizeDepth(in float depth, in float zNear, in float zFar)
+{
+	return (2.0 * zNear) / (zFar + zNear - depth * (zFar - zNear));
+}
+
+//==============================================================================
+// This is the optimal linearizeDepth where a=(f+n)/2n and b=(n-f)/2n
+float linearizeDepthOptimal(in float depth, in float a, in float b)
+{
+	return 1.0 / (a + depth * b);
+}
+
 #endif
 #endif

+ 2 - 0
shaders/Is.frag.glsl

@@ -9,11 +9,13 @@
 
 
 #define LIGHT_SET 0
 #define LIGHT_SET 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
+#define LIGHT_UBO_BINDING 0
 #define LIGHT_TEX_BINDING 4
 #define LIGHT_TEX_BINDING 4
 #include "shaders/LightResources.glsl"
 #include "shaders/LightResources.glsl"
 #undef LIGHT_SET
 #undef LIGHT_SET
 #undef LIGHT_SS_BINDING
 #undef LIGHT_SS_BINDING
 #undef LIGHT_TEX_BINDING
 #undef LIGHT_TEX_BINDING
+#undef LIGHT_UBO_BINDING
 
 
 layout(binding = 0) uniform sampler2D u_msRt0;
 layout(binding = 0) uniform sampler2D u_msRt0;
 layout(binding = 1) uniform sampler2D u_msRt1;
 layout(binding = 1) uniform sampler2D u_msRt1;

+ 1 - 2
shaders/Is.vert.glsl

@@ -5,9 +5,8 @@
 
 
 #define LIGHT_SET 0
 #define LIGHT_SET 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
+#define LIGHT_UBO_BINDING 0
 #include "shaders/LightResources.glsl"
 #include "shaders/LightResources.glsl"
-#undef LIGHT_SET
-#undef LIGHT_SS_BINDING
 
 
 layout(location = 0) out vec2 out_texCoord;
 layout(location = 0) out vec2 out_texCoord;
 layout(location = 1) flat out int out_instanceId;
 layout(location = 1) flat out int out_instanceId;

+ 7 - 8
shaders/LightResources.glsl

@@ -49,40 +49,39 @@ struct ReflectionProbe
 	vec4 cubemapIndexPad3;
 	vec4 cubemapIndexPad3;
 };
 };
 
 
-layout(std140,
-	row_major,
-	SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING)) readonly buffer _s0
+layout(
+	std140, row_major, UBO_BINDING(LIGHT_SET, LIGHT_UBO_BINDING)) uniform ubo0_
 {
 {
 	LightingUniforms u_lightingUniforms;
 	LightingUniforms u_lightingUniforms;
 };
 };
 
 
 #ifdef FRAGMENT_SHADER
 #ifdef FRAGMENT_SHADER
 
 
-layout(std140, SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 1)) readonly buffer _s1
+layout(std140, SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 0)) readonly buffer _s1
 {
 {
 	PointLight u_pointLights[];
 	PointLight u_pointLights[];
 };
 };
 
 
-layout(SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 2),
+layout(SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 1),
 	std140,
 	std140,
 	row_major) readonly buffer _s2
 	row_major) readonly buffer _s2
 {
 {
 	SpotLight u_spotLights[];
 	SpotLight u_spotLights[];
 };
 };
 
 
-layout(SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 3), std430) readonly buffer _s3
+layout(SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 2), std430) readonly buffer _s3
 {
 {
 	uint u_clusters[];
 	uint u_clusters[];
 };
 };
 
 
-layout(std430, SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 4)) readonly buffer _s4
+layout(std430, SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 3)) readonly buffer _s4
 {
 {
 	uint u_lightIndices[];
 	uint u_lightIndices[];
 };
 };
 
 
 layout(std140,
 layout(std140,
 	row_major,
 	row_major,
-	SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 5)) readonly buffer _s5
+	SS_BINDING(LIGHT_SET, LIGHT_SS_BINDING + 4)) readonly buffer _s5
 {
 {
 	ReflectionProbe u_reflectionProbes[];
 	ReflectionProbe u_reflectionProbes[];
 };
 };

+ 0 - 16
shaders/LinearDepth.glsl

@@ -1,16 +0,0 @@
-// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-// Convert to linear depth
-float linearizeDepth(in float depth, in float zNear, in float zFar)
-{
-	return (2.0 * zNear) / (zFar + zNear - depth * (zFar - zNear));
-}
-
-// This is the optimal linearizeDepth where a=(f+n)/2n and b=(n-f)/2n
-float linearizeDepthOptimal(in float depth, in float a, in float b)
-{
-	return 1.0 / (a + depth * b);
-}

+ 1 - 1
shaders/NearDepthUpscale.frag.glsl

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
-#include "shaders/LinearDepth.glsl"
+#include "shaders/Functions.glsl"
 
 
 layout(location = 0) in vec2 in_uv;
 layout(location = 0) in vec2 in_uv;
 
 

+ 3 - 28
shaders/Pps.frag.glsl

@@ -5,13 +5,12 @@
 
 
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
 #include "shaders/Tonemapping.glsl"
 #include "shaders/Tonemapping.glsl"
-#include "shaders/LinearDepth.glsl"
+#include "shaders/Functions.glsl"
 
 
 layout(binding = 0) uniform sampler2D u_isRt;
 layout(binding = 0) uniform sampler2D u_isRt;
 layout(binding = 1) uniform sampler2D u_ppsSsaoRt;
 layout(binding = 1) uniform sampler2D u_ppsSsaoRt;
 layout(binding = 2) uniform sampler2D u_ppsBloomLfRt;
 layout(binding = 2) uniform sampler2D u_ppsBloomLfRt;
 layout(binding = 3) uniform sampler3D u_lut;
 layout(binding = 3) uniform sampler3D u_lut;
-layout(binding = 5) uniform sampler2D u_msDepthRt;
 
 
 struct Luminance
 struct Luminance
 {
 {
@@ -23,17 +22,6 @@ layout(std140, SS_BINDING(0, 0)) readonly buffer s0_
 	Luminance u_luminance;
 	Luminance u_luminance;
 };
 };
 
 
-struct Uniforms
-{
-	vec4 nearFarPad2;
-	vec4 fogColorFogFactor;
-};
-
-layout(std140, UBO_BINDING(0, 0)) uniform ubo0_
-{
-	Uniforms u_uniforms;
-};
-
 layout(location = 0) in vec2 in_uv;
 layout(location = 0) in vec2 in_uv;
 layout(location = 0) out vec3 out_color;
 layout(location = 0) out vec3 out_color;
 
 
@@ -121,19 +109,6 @@ vec3 colorGrading(in vec3 color)
 	return textureLod(u_lut, lutCoords, 0.0).rgb;
 	return textureLod(u_lut, lutCoords, 0.0).rgb;
 }
 }
 
 
-//==============================================================================
-vec3 fog(vec3 colorIn, vec2 uv)
-{
-	float depth = textureLod(u_msDepthRt, uv, 1.0).r;
-
-	float linearDepth = linearizeDepth(
-		depth, u_uniforms.nearFarPad2.x, u_uniforms.nearFarPad2.y);
-
-	linearDepth = pow(linearDepth, 1.0);
-	float t = linearDepth * u_uniforms.fogColorFogFactor.w;
-	return colorIn * (1.0 - t) + u_uniforms.fogColorFogFactor.rgb * t;
-}
-
 //==============================================================================
 //==============================================================================
 void main()
 void main()
 {
 {
@@ -150,8 +125,8 @@ void main()
 
 
 	out_color = tonemap(out_color, u_luminance.averageLuminancePad3.x, 0.0);
 	out_color = tonemap(out_color, u_luminance.averageLuminancePad3.x, 0.0);
 
 
-#if 1
-	out_color = fog(out_color, in_uv);
+#if 0
+	out_color += fog(in_uv);
 #endif
 #endif
 
 
 #if BLOOM_ENABLED
 #if BLOOM_ENABLED

+ 2 - 2
shaders/Ssao.frag.glsl

@@ -6,7 +6,7 @@
 // SSAO fragment shader
 // SSAO fragment shader
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
 #include "shaders/Pack.glsl"
 #include "shaders/Pack.glsl"
-#include "shaders/LinearDepth.glsl"
+#include "shaders/Functions.glsl"
 #include "shaders/RendererCommonUniforms.glsl"
 #include "shaders/RendererCommonUniforms.glsl"
 
 
 const vec3 KERNEL[KERNEL_SIZE] = KERNEL_ARRAY; // This will be appended in C++
 const vec3 KERNEL[KERNEL_SIZE] = KERNEL_ARRAY; // This will be appended in C++
@@ -15,7 +15,7 @@ const vec3 KERNEL[KERNEL_SIZE] = KERNEL_ARRAY; // This will be appended in C++
 const float RADIUS = 1.1;
 const float RADIUS = 1.1;
 
 
 // Initial is 1.0 but the bigger it is the more darker the SSAO factor gets
 // Initial is 1.0 but the bigger it is the more darker the SSAO factor gets
-const float DARKNESS_MULTIPLIER = 2.5;
+const float DARKNESS_MULTIPLIER = 1.5;
 
 
 // The algorithm will chose the number of samples depending on the distance
 // The algorithm will chose the number of samples depending on the distance
 const float MAX_DISTANCE = 40.0;
 const float MAX_DISTANCE = 40.0;

+ 1 - 1
shaders/Sslr.glsl

@@ -5,7 +5,7 @@
 
 
 // SSLR functions and data
 // SSLR functions and data
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
-#include "shaders/LinearDepth.glsl"
+#include "shaders/Functions.glsl"
 #include "shaders/Pack.glsl"
 #include "shaders/Pack.glsl"
 
 
 const float ONE = 0.9;
 const float ONE = 0.9;

+ 37 - 0
shaders/Volumetric.frag.glsl

@@ -0,0 +1,37 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include "shaders/Common.glsl"
+#include "shaders/Functions.glsl"
+
+layout(location = 0) in vec2 in_uv;
+
+layout(binding = 0) uniform sampler2D u_msDepthRt;
+
+layout(std140, UBO_BINDING(0, 0)) uniform ubo0_
+{
+	vec4 u_linearizePad2;
+	vec4 u_fogColorFogFactor;
+};
+
+layout(location = 0) out vec3 out_color;
+
+//==============================================================================
+vec3 fog(vec2 uv)
+{
+	float depth = textureLod(u_msDepthRt, uv, 1.0).r;
+
+	float linearDepth =
+		linearizeDepthOptimal(depth, u_linearizePad2.x, u_linearizePad2.y);
+
+	float t = linearDepth * u_fogColorFogFactor.w;
+	return dither(u_fogColorFogFactor.rgb * t, 4.0);
+}
+
+//==============================================================================
+void main()
+{
+	out_color = fog(in_uv);
+}

+ 2 - 2
src/core/App.cpp

@@ -380,7 +380,7 @@ Error App::initDirs()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error App::mainLoop(UserMainLoopCallback callback, void* userData)
+Error App::mainLoop()
 {
 {
 	ANKI_LOGI("Entering main loop");
 	ANKI_LOGI("Entering main loop");
 	Bool quit = false;
 	Bool quit = false;
@@ -401,7 +401,7 @@ Error App::mainLoop(UserMainLoopCallback callback, void* userData)
 		ANKI_CHECK(m_input->handleEvents());
 		ANKI_CHECK(m_input->handleEvents());
 
 
 		// User update
 		// User update
-		ANKI_CHECK(callback(*this, userData, quit));
+		ANKI_CHECK(userMainLoop(quit));
 
 
 		ANKI_CHECK(m_scene->update(prevUpdateTime, crntTime, *m_renderer));
 		ANKI_CHECK(m_scene->update(prevUpdateTime, crntTime, *m_renderer));
 
 

+ 8 - 6
src/renderer/Fs.cpp

@@ -56,11 +56,12 @@ Error Fs::init(const ConfigSet&)
 			init.m_textures[2].m_texture = m_r->getSm().getOmniTextureArray();
 			init.m_textures[2].m_texture = m_r->getSm().getOmniTextureArray();
 		}
 		}
 
 
+		init.m_uniformBuffers[0].m_dynamic = true;
+
 		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;
 
 
 		m_globalResources = getGrManager().newInstance<ResourceGroup>(init);
 		m_globalResources = getGrManager().newInstance<ResourceGroup>(init);
 	}
 	}
@@ -73,11 +74,12 @@ Error Fs::init(const ConfigSet&)
 void Fs::prepareBuildCommandBuffers(RenderingContext& ctx)
 void Fs::prepareBuildCommandBuffers(RenderingContext& ctx)
 {
 {
 	DynamicBufferInfo& dyn = ctx.m_fs.m_set1DynInfo;
 	DynamicBufferInfo& dyn = ctx.m_fs.m_set1DynInfo;
-	dyn.m_storageBuffers[0] = m_r->getIs().getCommonVarsToken();
-	dyn.m_storageBuffers[1] = m_r->getIs().getPointLightsToken();
-	dyn.m_storageBuffers[2] = m_r->getIs().getSpotLightsToken();
-	dyn.m_storageBuffers[3] = m_r->getIs().getClustersToken();
-	dyn.m_storageBuffers[4] = m_r->getIs().getLightIndicesToken();
+	dyn.m_uniformBuffers[0] = m_r->getIs().getCommonVarsToken();
+
+	dyn.m_storageBuffers[0] = m_r->getIs().getPointLightsToken();
+	dyn.m_storageBuffers[1] = m_r->getIs().getSpotLightsToken();
+	dyn.m_storageBuffers[2] = m_r->getIs().getClustersToken();
+	dyn.m_storageBuffers[3] = m_r->getIs().getLightIndicesToken();
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 14 - 12
src/renderer/Is.cpp

@@ -454,12 +454,13 @@ Error Is::initInternal(const ConfigSet& config)
 				m_r->getIr().getIntegrationLutSampler();
 				m_r->getIr().getIntegrationLutSampler();
 		}
 		}
 
 
+		init.m_uniformBuffers[0].m_dynamic = true;
+
 		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;
-		init.m_storageBuffers[5].m_dynamic = true;
 
 
 		m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
 		m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
 	}
 	}
@@ -662,7 +663,7 @@ void Is::binLights(U32 threadId, PtrSize threadsCount, TaskCommonData& task)
 				MoveComponent& move = snode.getComponent<MoveComponent>();
 				MoveComponent& move = snode.getComponent<MoveComponent>();
 				LightComponent& light = snode.getComponent<LightComponent>();
 				LightComponent& light = snode.getComponent<LightComponent>();
 				SpatialComponent& sp = snode.getComponent<SpatialComponent>();
 				SpatialComponent& sp = snode.getComponent<SpatialComponent>();
-				const FrustumComponent* frc = 
+				const FrustumComponent* frc =
 					snode.tryGetComponent<FrustumComponent>();
 					snode.tryGetComponent<FrustumComponent>();
 
 
 				I pos = writeSpotLight(light, move, frc, cammove, camfrc, task);
 				I pos = writeSpotLight(light, move, frc, cammove, camfrc, task);
@@ -715,8 +716,8 @@ void Is::binLights(U32 threadId, PtrSize threadsCount, TaskCommonData& task)
 				continue;
 				continue;
 			}
 			}
 
 
-			// Check if the previous cluster contains the same lights as this 
-			// one and if yes then merge them. This will avoid allocating new 
+			// Check if the previous cluster contains the same lights as this
+			// one and if yes then merge them. This will avoid allocating new
 			// IDs (and thrashing GPU caches).
 			// IDs (and thrashing GPU caches).
 			cluster.sortLightIds();
 			cluster.sortLightIds();
 			if(i != start)
 			if(i != start)
@@ -756,7 +757,7 @@ void Is::binLights(U32 threadId, PtrSize threadsCount, TaskCommonData& task)
 
 
 					for(U i = 0; i < countS; ++i)
 					for(U i = 0; i < countS; ++i)
 					{
 					{
-						task.m_lightIds[offset++] = 
+						task.m_lightIds[offset++] =
 							cluster.m_spotIds[i].getIndex();
 							cluster.m_spotIds[i].getIndex();
 					}
 					}
 				}
 				}
@@ -971,12 +972,13 @@ void Is::setState(CommandBufferPtr& cmdb)
 	cmdb->bindPipeline(m_lightPpline);
 	cmdb->bindPipeline(m_lightPpline);
 
 
 	DynamicBufferInfo dyn;
 	DynamicBufferInfo dyn;
-	dyn.m_storageBuffers[0] = m_commonVarsToken;
-	dyn.m_storageBuffers[1] = m_pLightsToken;
-	dyn.m_storageBuffers[2] = m_sLightsToken;
-	dyn.m_storageBuffers[3] = m_clustersToken;
-	dyn.m_storageBuffers[4] = m_lightIdsToken;
-	dyn.m_storageBuffers[5] = m_probesToken;
+	dyn.m_uniformBuffers[0] = m_commonVarsToken;
+
+	dyn.m_storageBuffers[0] = m_pLightsToken;
+	dyn.m_storageBuffers[1] = m_sLightsToken;
+	dyn.m_storageBuffers[2] = m_clustersToken;
+	dyn.m_storageBuffers[3] = m_lightIdsToken;
+	dyn.m_storageBuffers[4] = m_probesToken;
 
 
 	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
 	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
 }
 }
@@ -994,7 +996,7 @@ void Is::updateCommonBlock(const FrustumComponent& fr)
 	ShaderCommonUniforms* blk = static_cast<ShaderCommonUniforms*>(
 	ShaderCommonUniforms* blk = static_cast<ShaderCommonUniforms*>(
 		getGrManager().allocateFrameHostVisibleMemory(
 		getGrManager().allocateFrameHostVisibleMemory(
 			sizeof(ShaderCommonUniforms),
 			sizeof(ShaderCommonUniforms),
-			BufferUsage::STORAGE,
+			BufferUsage::UNIFORM,
 			m_commonVarsToken));
 			m_commonVarsToken));
 
 
 	// Start writing
 	// Start writing

+ 1 - 32
src/renderer/Pps.cpp

@@ -20,19 +20,6 @@
 namespace anki
 namespace anki
 {
 {
 
 
-//==============================================================================
-// Misc                                                                        =
-//==============================================================================
-struct Uniforms
-{
-	Vec4 m_nearFarPad2;
-	Vec4 m_fogColorFogFactor;
-};
-
-//==============================================================================
-// Pps                                                                         =
-//==============================================================================
-
 //==============================================================================
 //==============================================================================
 const PixelFormat Pps::RT_PIXEL_FORMAT(
 const PixelFormat Pps::RT_PIXEL_FORMAT(
 	ComponentFormat::R8G8B8, TransformFormat::UNORM);
 	ComponentFormat::R8G8B8, TransformFormat::UNORM);
@@ -112,11 +99,8 @@ Error Pps::initInternal(const ConfigSet& config)
 
 
 	rcInit.m_textures[3].m_texture = m_lut->getGrTexture();
 	rcInit.m_textures[3].m_texture = m_lut->getGrTexture();
 
 
-	rcInit.m_textures[5].m_texture = m_r->getMs().getDepthRt();
-
 	rcInit.m_storageBuffers[0].m_buffer =
 	rcInit.m_storageBuffers[0].m_buffer =
 		m_r->getTm().getAverageLuminanceBuffer();
 		m_r->getTm().getAverageLuminanceBuffer();
-	rcInit.m_uniformBuffers[0].m_dynamic = true;
 
 
 	m_rcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
 	m_rcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
 
 
@@ -157,25 +141,10 @@ void Pps::run(RenderingContext& ctx)
 		m_r->getOutputFramebuffer(fb, width, height);
 		m_r->getOutputFramebuffer(fb, width, height);
 	}
 	}
 
 
-	// Update uniforms
-	DynamicBufferInfo dyn;
-	{
-		DynamicBufferToken token;
-		Uniforms* unis = static_cast<Uniforms*>(
-			getGrManager().allocateFrameHostVisibleMemory(
-				sizeof(*unis), BufferUsage::UNIFORM, dyn.m_uniformBuffers[0]));
-
-		unis->m_fogColorFogFactor = Vec4(m_fogColor, m_fogFactor);
-
-		const FrustumComponent& frc = *ctx.m_frustumComponent;
-		unis->m_nearFarPad2 = Vec4(
-			frc.getFrustum().getNear(), frc.getFrustum().getFar(), 0.0, 0.0);
-	}
-
 	cmdb->beginRenderPass(fb);
 	cmdb->beginRenderPass(fb);
 	cmdb->setViewport(0, 0, width, height);
 	cmdb->setViewport(0, 0, width, height);
 	cmdb->bindPipeline(m_ppline);
 	cmdb->bindPipeline(m_ppline);
-	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
+	cmdb->bindResourceGroup(m_rcGroup, 0, nullptr);
 	m_r->drawQuad(cmdb);
 	m_r->drawQuad(cmdb);
 	cmdb->endRenderPass();
 	cmdb->endRenderPass();
 }
 }

+ 5 - 0
src/renderer/Renderer.cpp

@@ -24,6 +24,7 @@
 #include <anki/renderer/Tiler.h>
 #include <anki/renderer/Tiler.h>
 #include <anki/renderer/Upsample.h>
 #include <anki/renderer/Upsample.h>
 #include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/DownscaleBlur.h>
+#include <anki/renderer/Volumetric.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -160,6 +161,9 @@ Error Renderer::initInternal(const ConfigSet& 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));
 
 
+	m_vol.reset(m_alloc.newInstance<Volumetric>(this));
+	ANKI_CHECK(m_vol->init(config));
+
 	m_lf.reset(m_alloc.newInstance<Lf>(this));
 	m_lf.reset(m_alloc.newInstance<Lf>(this));
 	ANKI_CHECK(m_lf->init(config));
 	ANKI_CHECK(m_lf->init(config));
 
 
@@ -262,6 +266,7 @@ Error Renderer::render(RenderingContext& ctx)
 	ANKI_CHECK(buildCommandBuffersFs(ctx));
 	ANKI_CHECK(buildCommandBuffersFs(ctx));
 	m_fs->run(ctx);
 	m_fs->run(ctx);
 	m_lf->run(ctx);
 	m_lf->run(ctx);
+	m_vol->run(ctx);
 	cmdb->endRenderPass();
 	cmdb->endRenderPass();
 
 
 	m_upsample->run(ctx);
 	m_upsample->run(ctx);

+ 67 - 0
src/renderer/Volumetric.cpp

@@ -0,0 +1,67 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/renderer/Volumetric.h>
+#include <anki/renderer/Renderer.h>
+#include <anki/renderer/Ms.h>
+#include <anki/scene/FrustumComponent.h>
+
+namespace anki
+{
+
+//==============================================================================
+Volumetric::~Volumetric()
+{
+}
+
+//==============================================================================
+Error Volumetric::init(const ConfigSet& config)
+{
+	// Create frag shader
+	ANKI_CHECK(getResourceManager().loadResource(
+		"shaders/Volumetric.frag.glsl", m_frag));
+
+	// Create ppline
+	ColorStateInfo colorState;
+	colorState.m_attachmentCount = 1;
+	colorState.m_attachments[0].m_srcBlendMethod = BlendMethod::ONE;
+	colorState.m_attachments[0].m_dstBlendMethod = BlendMethod::ONE;
+
+	m_r->createDrawQuadPipeline(m_frag->getGrShader(), colorState, m_ppline);
+
+	// Create the resource group
+	ResourceGroupInitInfo rcInit;
+	rcInit.m_textures[0].m_texture = m_r->getMs().getDepthRt();
+	rcInit.m_uniformBuffers[0].m_dynamic = true;
+
+	m_rcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+void Volumetric::run(RenderingContext& ctx)
+{
+	const Frustum& frc = ctx.m_frustumComponent->getFrustum();
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
+	// Update uniforms
+	DynamicBufferInfo dyn;
+	Vec4* uniforms =
+		static_cast<Vec4*>(getGrManager().allocateFrameHostVisibleMemory(
+			sizeof(Vec4) * 2, BufferUsage::UNIFORM, dyn.m_uniformBuffers[0]));
+
+	computeLinearizeDepthOptimal(
+		frc.getNear(), frc.getFar(), uniforms[0].x(), uniforms[0].y());
+
+	uniforms[1] = Vec4(m_fogColor, m_fogFactor);
+
+	// Draw
+	cmdb->bindPipeline(m_ppline);
+	cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
+	m_r->drawQuad(cmdb);
+}
+
+} // end namespace anki

+ 35 - 283
testapp/Main.cpp

@@ -6,84 +6,59 @@
 #undef ANKI_BUILD
 #undef ANKI_BUILD
 #endif
 #endif
 
 
-#include "anki/input/Input.h"
-#include "anki/Math.h"
-#include "anki/Renderer.h"
-#include "anki/core/App.h"
-#include "anki/resource/Mesh.h"
-#include "anki/resource/Material.h"
-#include "anki/script/ScriptManager.h"
-#include "anki/core/StdinListener.h"
-#include "anki/resource/Model.h"
-#include "anki/resource/Script.h"
-#include "anki/util/Logger.h"
-#include "anki/Util.h"
-#include "anki/resource/Skin.h"
-#include "anki/event/EventManager.h"
-#include "anki/event/MainRendererPpsHdrEvent.h"
-#include "anki/resource/Material.h"
-#include "anki/core/Timestamp.h"
-#include "anki/core/NativeWindow.h"
-#include "anki/Scene.h"
-#include "anki/event/LightEvent.h"
-#include "anki/event/AnimationEvent.h"
-#include "anki/event/JitterMoveEvent.h"
-#include "anki/core/Config.h"
-#include "anki/physics/PhysicsWorld.h"
-#include "anki/scene/LensFlareComponent.h"
-#include "anki/scene/PlayerNode.h"
-#include "anki/scene/PlayerControllerComponent.h"
-#include "anki/Gr.h"
+#include "anki/AnKi.h"
 
 
 using namespace anki;
 using namespace anki;
 
 
-App* app;
-
-ModelNode* horse;
-PerspectiveCamera* cam;
-
 #define PLAYER 0
 #define PLAYER 0
 #define MOUSE 1
 #define MOUSE 1
 
 
-Bool profile = false;
+class MyApp : public App
+{
+public:
+	PerspectiveCamera* m_cam = nullptr;
+	Bool m_profile = false;
+
+	Error init();
+	Error userMainLoop(Bool& quit) override;
+};
+
+MyApp* app = nullptr;
 
 
 //==============================================================================
 //==============================================================================
-Error init()
+Error MyApp::init()
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	ANKI_LOGI("Other init...");
 	ANKI_LOGI("Other init...");
 
 
-	SpotLight* spot;
-	PointLight* point;
-	MoveComponent* move;
-	LightComponent* lightc;
-
 	SceneGraph& scene = app->getSceneGraph();
 	SceneGraph& scene = app->getSceneGraph();
 	MainRenderer& renderer = app->getMainRenderer();
 	MainRenderer& renderer = app->getMainRenderer();
 	ResourceManager& resources = app->getResourceManager();
 	ResourceManager& resources = app->getResourceManager();
 
 
 	scene.setAmbientColor(Vec4(1.0) * 0.0);
 	scene.setAmbientColor(Vec4(1.0) * 0.0);
-	renderer.getOffscreenRenderer().getPps().setFog(Vec3(1.0, 0.9, 0.9), 0.7);
+	renderer.getOffscreenRenderer().getVolumetric().setFog(
+		Vec3(1.0, 0.9, 0.9), 0.7);
 
 
 	if(getenv("PROFILE"))
 	if(getenv("PROFILE"))
 	{
 	{
-		profile = true;
+		m_profile = true;
 		app->setTimerTick(0.0);
 		app->setTimerTick(0.0);
 	}
 	}
 
 
 	// camera
 	// camera
-	err = scene.newSceneNode<PerspectiveCamera>("main-camera", cam);
+	err = scene.newSceneNode<PerspectiveCamera>("main-camera", m_cam);
 	if(err)
 	if(err)
 		return err;
 		return err;
 	const F32 ang = 55.0;
 	const F32 ang = 55.0;
-	cam->setAll(renderer.getAspectRatio() * toRad(ang), toRad(ang), 0.2, 300.0);
-	scene.setActiveCamera(cam);
+	m_cam->setAll(
+		renderer.getAspectRatio() * toRad(ang), toRad(ang), 0.2, 300.0);
+	scene.setActiveCamera(m_cam);
 
 
-	cam->getComponent<MoveComponent>().setLocalTransform(Transform(
+	m_cam->getComponent<MoveComponent>().setLocalTransform(Transform(
 		Vec4(0.0), Mat3x4(Euler(toRad(0.0), toRad(180.0), toRad(0.0))), 1.0));
 		Vec4(0.0), Mat3x4(Euler(toRad(0.0), toRad(180.0), toRad(0.0))), 1.0));
 
 
 #if !PLAYER
 #if !PLAYER
-	cam->getComponent<MoveComponent>().setLocalTransform(Transform(
+	m_cam->getComponent<MoveComponent>().setLocalTransform(Transform(
 		// Vec4(147.392776, -10.132728, 16.607138, 0.0),
 		// Vec4(147.392776, -10.132728, 16.607138, 0.0),
 		Vec4(98.994728, -10.601542, 16.376123, 0),
 		Vec4(98.994728, -10.601542, 16.376123, 0),
 		Mat3x4(Euler(toRad(0.0), toRad(-90.0), toRad(0.0))),
 		Mat3x4(Euler(toRad(0.0), toRad(-90.0), toRad(0.0))),
@@ -91,174 +66,6 @@ Error init()
 		1.0));
 		1.0));
 #endif
 #endif
 
 
-#if 0
-	{
-		ReflectionProbe* refl;
-		scene.newSceneNode<ReflectionProbe>("refl", refl, 68.0f);
-		move = refl->tryGetComponent<MoveComponent>();
-		move->setLocalOrigin(Vec4(0.0, 10, 0, 0));
-
-		ReflectionProxy* proxy;
-		scene.newSceneNode<ReflectionProxy>("proxy", proxy, 100.0, 15.0, 10.0);
-		move = proxy->tryGetComponent<MoveComponent>();
-		move->setLocalOrigin(Vec4(0.0, 12, -15, 0));
-	}
-#endif
-
-#if 0
-	PointLight* plight;
-	scene.newSceneNode<PointLight>("spot0", plight);
-
-	lightc = plight->tryGetComponent<LightComponent>();
-	lightc->setDiffuseColor(Vec4(0.0, 30.0, 0.0, 1.0));
-	lightc->setSpecularColor(Vec4(1.2));
-	lightc->setDistance(5.0);
-
-	move = plight->tryGetComponent<MoveComponent>();
-	move->setLocalTransform(Transform(Vec4(0.0, 0.0, 0.0, 0.0),
-		Mat3x4::getIdentity(), 1.0));
-#endif
-#if 0
-	SpotLight* light;
-	scene.newSceneNode<SpotLight>("spot0", light);
-
-	lightc = light->tryGetComponent<LightComponent>();
-	lightc->setOuterAngle(toRad(45.0));
-	lightc->setInnerAngle(toRad(15.0));
-	lightc->setDiffuseColor(Vec4(0.0, 30.0, 0.0, 1.0));
-	lightc->setSpecularColor(Vec4(1.2));
-	lightc->setDistance(5.0);
-
-	move = light->tryGetComponent<MoveComponent>();
-	move->setLocalTransform(Transform(Vec4(0.0, 0.5, 0.0, 0.0),
-		Mat3x4::getIdentity(), 1.0));
-#endif
-
-#if 0
-	err = scene.newSceneNode<SpotLight>("spot1", spot);
-	if(err) return err;
-	spot->setOuterAngle(toRad(45.0));
-	spot->setInnerAngle(toRad(15.0));
-	spot->setLocalTransform(Transform(Vec4(5.3, 4.3, 3.0, 0.0),
-		Mat3x4::getIdentity(), 1.0));
-	spot->setDiffuseColor(Vec4(3.0, 0.0, 0.0, 0.0));
-	spot->setSpecularColor(Vec4(3.0, 3.0, 0.0, 0.0));
-	spot->setDistance(30.0);
-	spot->setShadowEnabled(true);
-#endif
-
-#if 0
-	// Vase point lights
-	F32 x = 8.5;
-	F32 y = 2.25;
-	F32 z = 2.49;
-	Array<Vec3, 4> vaseLightPos = {{Vec3(x, y, -z - 1.4), Vec3(x, y, z),
-		Vec3(-x - 2.3, y, z), Vec3(-x - 2.3, y, -z - 1.4)}};
-	for(U i = 0; i < vaseLightPos.getSize(); i++)
-	{
-		Vec4 lightPos = vaseLightPos[i].xyz0();
-
-		PointLight* point;
-		err = scene.newSceneNode<PointLight>(
-			("vase_plight" + std::to_string(i)).c_str(), point);
-		if(err) return err;
-
-		point->setRadius(2.0);
-		point->setLocalOrigin(lightPos);
-		point->setDiffuseColor(Vec4(3.0, 0.2, 0.0, 0.0));
-		point->setSpecularColor(Vec4(1.0, 1.0, 0.0, 0.0));
-
-		//if(i == 0)
-		{
-		point->loadLensFlare("textures/lens_flare/flares0.ankitex");
-		LensFlareComponent& lf = point->getComponent<LensFlareComponent>();
-		lf.setFirstFlareSize(Vec2(0.5, 0.2));
-		lf.setColorMultiplier(Vec4(1.0, 1.0, 1.0, 0.6));
-		}
-
-		LightEvent* event;
-		err = scene.getEventManager().newEvent(event, 0.0, 0.8, point);
-		if(err) return err;
-		event->setRadiusMultiplier(0.2);
-		event->setIntensityMultiplier(Vec4(-1.2, 0.0, 0.0, 0.0));
-		event->setSpecularIntensityMultiplier(Vec4(0.1, 0.1, 0.0, 0.0));
-		event->setReanimate(true);
-
-		JitterMoveEvent* mevent;
-		scene.getEventManager().newEvent(mevent, 0.0, 2.0, point);
-		mevent->setPositionLimits(
-			Vec4(-0.5, 0.0, -0.5, 0), Vec4(0.5, 0.0, 0.5, 0));
-		mevent->setReanimate(true);
-
-		ParticleEmitter* pe;
-		/**/
-
-		if(i == 0)
-		{
-			err = scene.newSceneNode<ParticleEmitter>(
-				"pefire", pe, "particles/fire.ankipart");
-			if(err) return err;
-			pe->setLocalOrigin(lightPos);
-
-			err = scene.newSceneNode<ParticleEmitter>(
-				"pesmoke", pe, "particles/smoke.ankipart");
-			if(err) return err;
-			pe->setLocalOrigin(lightPos);
-		}
-		else
-		{
-			InstanceNode* instance;
-			err = scene.newSceneNode<InstanceNode>(
-				("pefire_inst" + std::to_string(i)).c_str(), instance);
-			if(err) return err;
-
-			instance->setLocalOrigin(lightPos);
-
-			SceneNode& sn = scene.findSceneNode("pefire");
-			sn.addChild(instance);
-
-			err = scene.newSceneNode<InstanceNode>(
-				("pesmoke_inst" + std::to_string(i)).c_str(), instance);
-			if(err) return err;
-
-			instance->setLocalOrigin(lightPos);
-
-			scene.findSceneNode("pesmoke").addChild(instance);
-		}
-
-		/*{
-			scene.newSceneNode(pe, ("pesparks" + std::to_string(i)).c_str(),
-				"particles/sparks.ankipart");
-			pe->setLocalOrigin(lightPos);
-		}*/
-	}
-#endif
-
-#if 0
-	// horse
-	err = scene.newSceneNode<ModelNode>("horse", horse,
-		"models/horse/horse.ankimdl");
-	if(err) return err;
-	horse->getComponent<MoveComponent>().setLocalTransform(
-		Transform(Vec4(0, 3, 0, 0.0), Mat3x4::getIdentity(), 0.5));
-#endif
-
-	if(0)
-	{
-		err = scene.newSceneNode<PointLight>("plight0", point);
-		if(err)
-			return err;
-
-		lightc = point->tryGetComponent<LightComponent>();
-		lightc->setDistance(2.2);
-		lightc->setDiffuseColor(Vec4(1.0));
-		lightc->setSpecularColor(Vec4(0.6, 0.6, 0.3, 1.0));
-
-		move = point->tryGetComponent<MoveComponent>();
-		move->setLocalOrigin(Vec4(3.0, 2.0, 0.2, 0.0));
-		move->setLocalRotation(Mat3x4(Axisang(toRad(90.0), Vec3(0, 1, 0))));
-	}
-
 	{
 	{
 		ScriptResourcePtr script;
 		ScriptResourcePtr script;
 
 
@@ -276,67 +83,20 @@ Error init()
 			.loadColorGradingTexture("textures/adis/dungeon.ankitex");
 			.loadColorGradingTexture("textures/adis/dungeon.ankitex");
 	}
 	}
 
 
-/*{
-	SceneNode* node = scene.tryFindSceneNode("Point_026");
-	LightEvent* event = scene.getEventManager().newEvent<LightEvent>(
-		0.0f, 50.0f, node);
-	event->setIntensityMultiplier(Vec4(1.5));
-	event->setFrequency(3.0, 0.1);
-}*/
-
 #if PLAYER
 #if PLAYER
 	PlayerNode* pnode;
 	PlayerNode* pnode;
 	scene.newSceneNode<PlayerNode>(
 	scene.newSceneNode<PlayerNode>(
 		"player", pnode, Vec4(147.392776, -11.132728, 16.607138, 0.0));
 		"player", pnode, Vec4(147.392776, -11.132728, 16.607138, 0.0));
 
 
-	pnode->addChild(cam);
+	pnode->addChild(m_cam);
 
 
 #endif
 #endif
 
 
-#if 0
-	{
-		ModelNode* fog;
-		scene.newSceneNode<ModelNode>("fog", fog,
-			"models/fog/volumetric_fog_box.ankimdl");
-		MoveComponent& move = fog->getComponent<MoveComponent>();
-		//move.setLocalOrigin(Vec4(10.0, -19.0, 0.0, 0.0));
-		move.setLocalOrigin(Vec4(10.0, -26.5, 0.0, 0.0));
-		move.setLocalScale(100.0);
-	}
-#endif
-
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-#if 0
-/// The func pools the stdinListener for string in the console, if
-/// there are any it executes them with scriptingEngine
-void execStdinScpripts()
-{
-	while(1)
-	{
-		std::string cmd = StdinListenerSingleton::get().getLine();
-
-		if(cmd.length() < 1)
-		{
-			break;
-		}
-
-		try
-		{
-			ScriptManagerSingleton::get().evalString(cmd.c_str());
-		}
-		catch(Exception& e)
-		{
-			ANKI_LOGE(e.what());
-		}
-	}
-}
-#endif
-
-//==============================================================================
-Error mainLoopExtra(App& app, void*, Bool& quit)
+Error MyApp::userMainLoop(Bool& quit)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	F32 dist = 0.1;
 	F32 dist = 0.1;
@@ -345,9 +105,9 @@ Error mainLoopExtra(App& app, void*, Bool& quit)
 	F32 mouseSensivity = 9.0;
 	F32 mouseSensivity = 9.0;
 	quit = false;
 	quit = false;
 
 
-	SceneGraph& scene = app.getSceneGraph();
-	Input& in = app.getInput();
-	MainRenderer& renderer = app.getMainRenderer();
+	SceneGraph& scene = getSceneGraph();
+	Input& in = getInput();
+	MainRenderer& renderer = getMainRenderer();
 
 
 	if(in.getKey(KeyCode::ESCAPE))
 	if(in.getKey(KeyCode::ESCAPE))
 	{
 	{
@@ -468,7 +228,7 @@ Error mainLoopExtra(App& app, void*, Bool& quit)
 #endif
 #endif
 
 
 #if !PLAYER && MOUSE
 #if !PLAYER && MOUSE
-	if(in.getMousePosition() != Vec2(0.0) && !profile)
+	if(in.getMousePosition() != Vec2(0.0) && !m_profile)
 	{
 	{
 		// printf("%f %f\n", in.getMousePosition().x(),
 		// printf("%f %f\n", in.getMousePosition().x(),
 		// in.getMousePosition().y());
 		// in.getMousePosition().y());
@@ -481,9 +241,7 @@ Error mainLoopExtra(App& app, void*, Bool& quit)
 	}
 	}
 #endif
 #endif
 
 
-	// execStdinScpripts();
-
-	if(profile && app.getGlobalTimestamp() == 500)
+	if(m_profile && getGlobalTimestamp() == 500)
 	{
 	{
 		quit = true;
 		quit = true;
 		return err;
 		return err;
@@ -493,7 +251,7 @@ Error mainLoopExtra(App& app, void*, Bool& quit)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error initSubsystems(int argc, char* argv[])
+Error init(int argc, char* argv[])
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 
 
@@ -546,10 +304,9 @@ Error initSubsystems(int argc, char* argv[])
 	// config.set("maxTextureSize", 256);
 	// config.set("maxTextureSize", 256);
 	// config.set("lodDistance", 3.0);
 	// config.set("lodDistance", 3.0);
 
 
-	app = new App;
-	err = app->create(config, allocAligned, nullptr);
-	if(err)
-		return err;
+	app = new MyApp;
+	ANKI_CHECK(app->create(config, allocAligned, nullptr));
+	ANKI_CHECK(app->init());
 
 
 // Input
 // Input
 #if MOUSE
 #if MOUSE
@@ -566,16 +323,11 @@ int main(int argc, char* argv[])
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 
 
-	err = initSubsystems(argc, argv);
-
-	if(!err)
-	{
-		err = init();
-	}
+	err = init(argc, argv);
 
 
 	if(!err)
 	if(!err)
 	{
 	{
-		err = app->mainLoop(mainLoopExtra, nullptr);
+		err = app->mainLoop();
 	}
 	}
 
 
 	if(err)
 	if(err)