Branimir Karadžić 9 lat temu
rodzic
commit
5b3c9609cb
1 zmienionych plików z 541 dodań i 534 usunięć
  1. 541 534
      examples/31-reflectiveshadowmap/reflectiveshadowmap.cpp

+ 541 - 534
examples/31-reflectiveshadowmap/reflectiveshadowmap.cpp

@@ -24,7 +24,7 @@
 // 4.  Deferred "combine" pass.
 
 // Details:
-// 1.  G-Buffer:  
+// 1.  G-Buffer:
 // Typical G-Buffer with normals, color, depth.
 // 2.  RSM:
 // A typical shadow map, except it also outputs to a "RSM" buffer.
@@ -66,82 +66,92 @@
 #define SHADOW_MAP_DIM 512
 #define LIGHT_DIST 10.0f
 
+static const char * m_meshPaths[MESH_COUNT] =
+{
+	"meshes/cube.bin",
+	"meshes/orb.bin",
+	"meshes/column.bin",
+	"meshes/bunny.bin",
+	"meshes/tree.bin",
+	"meshes/hollowcube.bin"
+};
+
 // Vertex decl for our screen space quad (used in deferred rendering)
 struct PosTexCoord0Vertex
 {
-    float m_x;
-    float m_y;
-    float m_z;
-    float m_u;
-    float m_v;
-
-    static void init()
-    {
-        ms_decl
-            .begin()
-            .add(bgfx::Attrib::Position,  3, bgfx::AttribType::Float)
-            .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
-            .end();
-    }
-
-    static bgfx::VertexDecl ms_decl;
+	float m_x;
+	float m_y;
+	float m_z;
+	float m_u;
+	float m_v;
+
+	static void init()
+	{
+		ms_decl
+			.begin()
+			.add(bgfx::Attrib::Position,  3, bgfx::AttribType::Float)
+			.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
+			.end();
+	}
+
+	static bgfx::VertexDecl ms_decl;
 };
 bgfx::VertexDecl PosTexCoord0Vertex::ms_decl;
 
 // Utility function to draw a screen space quad for deferred rendering
 void screenSpaceQuad(float _textureWidth, float _textureHeight, float _texelHalf, bool _originBottomLeft, float _width = 1.0f, float _height = 1.0f)
 {
-    if (bgfx::checkAvailTransientVertexBuffer(3, PosTexCoord0Vertex::ms_decl) )
-    {
-        bgfx::TransientVertexBuffer vb;
-        bgfx::allocTransientVertexBuffer(&vb, 3, PosTexCoord0Vertex::ms_decl);
-        PosTexCoord0Vertex* vertex = (PosTexCoord0Vertex*)vb.data;
-
-        const float minx = -_width;
-        const float maxx =  _width;
-        const float miny = 0.0f;
-        const float maxy = _height*2.0f;
-
-        const float texelHalfW = _texelHalf/_textureWidth;
-        const float texelHalfH = _texelHalf/_textureHeight;
-        const float minu = -1.0f + texelHalfW;
-        const float maxu =  1.0f + texelHalfH;
-
-        const float zz = 0.0f;
-
-        float minv = texelHalfH;
-        float maxv = 2.0f + texelHalfH;
-
-        if (_originBottomLeft)
-        {
-            float temp = minv;
-            minv = maxv;
-            maxv = temp;
-
-            minv -= 1.0f;
-            maxv -= 1.0f;
-        }
-
-        vertex[0].m_x = minx;
-        vertex[0].m_y = miny;
-        vertex[0].m_z = zz;
-        vertex[0].m_u = minu;
-        vertex[0].m_v = minv;
-
-        vertex[1].m_x = maxx;
-        vertex[1].m_y = miny;
-        vertex[1].m_z = zz;
-        vertex[1].m_u = maxu;
-        vertex[1].m_v = minv;
-
-        vertex[2].m_x = maxx;
-        vertex[2].m_y = maxy;
-        vertex[2].m_z = zz;
-        vertex[2].m_u = maxu;
-        vertex[2].m_v = maxv;
-
-        bgfx::setVertexBuffer(&vb);
-    }
+	if (bgfx::checkAvailTransientVertexBuffer(3, PosTexCoord0Vertex::ms_decl) )
+	{
+		bgfx::TransientVertexBuffer vb;
+		bgfx::allocTransientVertexBuffer(&vb, 3, PosTexCoord0Vertex::ms_decl);
+		PosTexCoord0Vertex* vertex = (PosTexCoord0Vertex*)vb.data;
+
+		const float minx = -_width;
+		const float maxx =  _width;
+		const float miny = 0.0f;
+		const float maxy = _height*2.0f;
+
+		const float texelHalfW = _texelHalf/_textureWidth;
+		const float texelHalfH = _texelHalf/_textureHeight;
+		const float minu = -1.0f + texelHalfW;
+		const float maxu =  1.0f + texelHalfH;
+
+		const float zz = 0.0f;
+
+		float minv = texelHalfH;
+		float maxv = 2.0f + texelHalfH;
+
+		if (_originBottomLeft)
+		{
+			float temp = minv;
+			minv = maxv;
+			maxv = temp;
+
+			minv -= 1.0f;
+			maxv -= 1.0f;
+		}
+
+		vertex[0].m_x = minx;
+		vertex[0].m_y = miny;
+		vertex[0].m_z = zz;
+		vertex[0].m_u = minu;
+		vertex[0].m_v = minv;
+
+		vertex[1].m_x = maxx;
+		vertex[1].m_y = miny;
+		vertex[1].m_z = zz;
+		vertex[1].m_u = maxu;
+		vertex[1].m_v = minv;
+
+		vertex[2].m_x = maxx;
+		vertex[2].m_y = maxy;
+		vertex[2].m_z = zz;
+		vertex[2].m_u = maxu;
+		vertex[2].m_v = maxv;
+
+		bgfx::setVertexBuffer(&vb);
+	}
 }
 
 class ExampleReflectiveShadowMap : public entry::AppI
@@ -162,203 +172,205 @@ class ExampleReflectiveShadowMap : public entry::AppI
 		// Enable debug text.
 		bgfx::setDebug(m_debug);
 
-        // Labeling for renderdoc captures, etc
-        bgfx::setViewName(RENDER_PASS_GBUFFER,      "gbuffer"     );     
-        bgfx::setViewName(RENDER_PASS_SHADOW_MAP,   "shadow map"  );
-        bgfx::setViewName(RENDER_PASS_LIGHT_BUFFER, "light buffer");
-        bgfx::setViewName(RENDER_PASS_COMBINE,      "post combine");
+		// Labeling for renderdoc captures, etc
+		bgfx::setViewName(RENDER_PASS_GBUFFER,      "gbuffer"     );
+		bgfx::setViewName(RENDER_PASS_SHADOW_MAP,   "shadow map"  );
+		bgfx::setViewName(RENDER_PASS_LIGHT_BUFFER, "light buffer");
+		bgfx::setViewName(RENDER_PASS_COMBINE,      "post combine");
 
 		// Set up screen clears
 		bgfx::setViewClear(RENDER_PASS_GBUFFER
-			, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-			, 0
-			, 1.0f
-			, 0
-			);
-
-        bgfx::setViewClear(RENDER_PASS_LIGHT_BUFFER
-            , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-            , 0
-            , 1.0f
-            , 0
-            );
-
-        bgfx::setViewClear(RENDER_PASS_SHADOW_MAP
-            , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-            , 0
-            , 1.0f
-            , 0
-            );
-
-        // Create uniforms
-        u_tint          = bgfx::createUniform("u_tint",          bgfx::UniformType::Vec4);  // Tint for when you click on items
-        u_lightDir      = bgfx::createUniform("u_lightDir",      bgfx::UniformType::Vec4);  // Single directional light for entire scene
-        u_sphereInfo    = bgfx::createUniform("u_sphereInfo",    bgfx::UniformType::Vec4);  // Info for RSM
-        u_invMvp        = bgfx::createUniform("u_invMvp",        bgfx::UniformType::Mat4);  // Matrix needed in light buffer
-        u_invMvpShadow  = bgfx::createUniform("u_invMvpShadow",  bgfx::UniformType::Mat4);  // Matrix needed in light buffer
-        u_lightMtx      = bgfx::createUniform("u_lightMtx",      bgfx::UniformType::Mat4);  // Matrix needed to use shadow map (world to shadow space)
-        u_shadowDimsInv = bgfx::createUniform("u_shadowDimsInv", bgfx::UniformType::Vec4);  // Used in PCF
-        u_rsmAmount     = bgfx::createUniform("u_rsmAmount",     bgfx::UniformType::Vec4);  // How much RSM to use vs directional light
-
-        // Create texture sampler uniforms (used when we bind textures)
-        s_normal    = bgfx::createUniform("s_normal",    bgfx::UniformType::Int1);  // Normal gbuffer
-        s_depth     = bgfx::createUniform("s_depth",     bgfx::UniformType::Int1);  // Normal gbuffer
-        s_color     = bgfx::createUniform("s_color",     bgfx::UniformType::Int1);  // Color (albedo) gbuffer
-        s_light     = bgfx::createUniform("s_light",     bgfx::UniformType::Int1);  // Light buffer
-        s_shadowMap = bgfx::createUniform("s_shadowMap", bgfx::UniformType::Int1);  // Shadow map
-        s_rsm       = bgfx::createUniform("s_rsm",       bgfx::UniformType::Int1);  // Reflective shadow map
-        
+				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+				, 0
+				, 1.0f
+				, 0
+				);
+
+		bgfx::setViewClear(RENDER_PASS_LIGHT_BUFFER
+				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+				, 0
+				, 1.0f
+				, 0
+				);
+
+		bgfx::setViewClear(RENDER_PASS_SHADOW_MAP
+				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+				, 0
+				, 1.0f
+				, 0
+				);
+
+		// Create uniforms
+		u_tint          = bgfx::createUniform("u_tint",          bgfx::UniformType::Vec4);  // Tint for when you click on items
+		u_lightDir      = bgfx::createUniform("u_lightDir",      bgfx::UniformType::Vec4);  // Single directional light for entire scene
+		u_sphereInfo    = bgfx::createUniform("u_sphereInfo",    bgfx::UniformType::Vec4);  // Info for RSM
+		u_invMvp        = bgfx::createUniform("u_invMvp",        bgfx::UniformType::Mat4);  // Matrix needed in light buffer
+		u_invMvpShadow  = bgfx::createUniform("u_invMvpShadow",  bgfx::UniformType::Mat4);  // Matrix needed in light buffer
+		u_lightMtx      = bgfx::createUniform("u_lightMtx",      bgfx::UniformType::Mat4);  // Matrix needed to use shadow map (world to shadow space)
+		u_shadowDimsInv = bgfx::createUniform("u_shadowDimsInv", bgfx::UniformType::Vec4);  // Used in PCF
+		u_rsmAmount     = bgfx::createUniform("u_rsmAmount",     bgfx::UniformType::Vec4);  // How much RSM to use vs directional light
+
+		// Create texture sampler uniforms (used when we bind textures)
+		s_normal    = bgfx::createUniform("s_normal",    bgfx::UniformType::Int1);  // Normal gbuffer
+		s_depth     = bgfx::createUniform("s_depth",     bgfx::UniformType::Int1);  // Normal gbuffer
+		s_color     = bgfx::createUniform("s_color",     bgfx::UniformType::Int1);  // Color (albedo) gbuffer
+		s_light     = bgfx::createUniform("s_light",     bgfx::UniformType::Int1);  // Light buffer
+		s_shadowMap = bgfx::createUniform("s_shadowMap", bgfx::UniformType::Int1);  // Shadow map
+		s_rsm       = bgfx::createUniform("s_rsm",       bgfx::UniformType::Int1);  // Reflective shadow map
+
 		// Create program from shaders.
 		m_gbufferProgram = loadProgram("vs_rsm_gbuffer", "fs_rsm_gbuffer");  // Gbuffer
-        m_shadowProgram  = loadProgram("vs_rsm_shadow",  "fs_rsm_shadow"  ); // Drawing shadow map
-        m_lightProgram   = loadProgram("vs_rsm_lbuffer", "fs_rsm_lbuffer");  // Light buffer
-        m_combineProgram = loadProgram("vs_rsm_combine", "fs_rsm_combine");  // Combiner
-
-        // Load some meshes
-        for (uint32_t i = 0; i < MESH_COUNT; i++) {
-            m_meshes[i] = meshLoad(m_meshPaths[i]);
-        }
-
-        // Randomly create some models
-        bx::RngMwc mwc;  // Random number generator
-        for (Model & m : m_models) {
-            uint32_t r = mwc.gen() % 256;
-            uint32_t g = mwc.gen() % 256;
-            uint32_t b = mwc.gen() % 256;
-            m.mesh = 1+mwc.gen()%(MESH_COUNT-1);
-            m.color[0] = r/255.0f;
-            m.color[1] = g/255.0f;
-            m.color[2] = b/255.0f;
-            m.color[3] = 1.0f;
-            m.position[0] = (((mwc.gen() % 256)) - 128.0f)/20.0f;
-            m.position[1] = 0;
-            m.position[2] = (((mwc.gen() % 256)) - 128.0f)/20.0f;
-        }
-
-        // Load ground.  We'll just use the cube since I don't have a ground model right now
-        m_ground = meshLoad("meshes/cube.bin");
-
-        // Light sphere
-        m_lightSphere = meshLoad("meshes/unit_sphere.bin");
-
-        const uint32_t samplerFlags = 0
-            | BGFX_TEXTURE_RT
-            | BGFX_TEXTURE_MIN_POINT
-            | BGFX_TEXTURE_MAG_POINT
-            | BGFX_TEXTURE_MIP_POINT
-            | BGFX_TEXTURE_U_CLAMP
-            | BGFX_TEXTURE_V_CLAMP
-            ;
-
-        // Make gbuffer and related textures
-        m_gbufferTex[GBUFFER_RT_NORMAL] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
-        m_gbufferTex[GBUFFER_RT_COLOR]  = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
-        m_gbufferTex[GBUFFER_RT_DEPTH]  = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::D24,   samplerFlags);
-        m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_gbufferTex), m_gbufferTex, true);
-
-        // Make light buffer
-        m_lightBufferTex = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
-        bgfx::TextureHandle lightBufferRTs[] =  {
-            m_lightBufferTex
-        };
-        m_lightBuffer = bgfx::createFrameBuffer(BX_COUNTOF(lightBufferRTs), lightBufferRTs, true);
-
-        // Make shadow buffer
-        const uint32_t rsmFlags = 0
-            | BGFX_TEXTURE_RT
-            | BGFX_TEXTURE_MIN_POINT
-            | BGFX_TEXTURE_MAG_POINT
-            | BGFX_TEXTURE_MIP_POINT
-            | BGFX_TEXTURE_U_CLAMP
-            | BGFX_TEXTURE_V_CLAMP
-            ;
-
-        // Reflective shadow map
-        m_shadowBufferTex[SHADOW_RT_RSM] = bgfx::createTexture2D(
-            SHADOW_MAP_DIM
-            , SHADOW_MAP_DIM
-            , 1
-            , bgfx::TextureFormat::BGRA8,
-            rsmFlags
-            );
-       
-        // Typical shadow map
-        m_shadowBufferTex[SHADOW_RT_DEPTH] = bgfx::createTexture2D(
-            SHADOW_MAP_DIM
-            , SHADOW_MAP_DIM
-            , 1
-            , bgfx::TextureFormat::D16,
-            BGFX_TEXTURE_RT/* | BGFX_TEXTURE_COMPARE_LEQUAL*/
-            );  // Note I'm not setting BGFX_TEXTURE_COMPARE_LEQUAL.  Why?
-        // Normally a PCF shadow map such as this requires a compare.  However, this sample also
-        // reads from this texture in the lighting pass, and only uses the PCF capabilites in the
-        // combine pass, so the flag is disabled by default.
-        
-        m_shadowBuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_shadowBufferTex), m_shadowBufferTex, true);
-
-        // Vertex decl
-        PosTexCoord0Vertex::init();
-
-        // Init camera
-        cameraCreate();
-        float camPos[] = {0.0f, 1.5f, 0.0f};
-        cameraSetPosition(camPos);
-        cameraSetVerticalAngle(-0.3f);
-
-        // Init directional light
-        updateLightDir();
-    
-        // Get renderer capabilities info.
-        m_caps = bgfx::getCaps();
-        const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
-        m_texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
-
-        imguiCreate();
-    }
+		m_shadowProgram  = loadProgram("vs_rsm_shadow",  "fs_rsm_shadow"  ); // Drawing shadow map
+		m_lightProgram   = loadProgram("vs_rsm_lbuffer", "fs_rsm_lbuffer");  // Light buffer
+		m_combineProgram = loadProgram("vs_rsm_combine", "fs_rsm_combine");  // Combiner
+
+		// Load some meshes
+		for (uint32_t i = 0; i < MESH_COUNT; i++) {
+			m_meshes[i] = meshLoad(m_meshPaths[i]);
+		}
+
+		// Randomly create some models
+		bx::RngMwc mwc;  // Random number generator
+		for (Model & m : m_models) {
+			uint32_t r = mwc.gen() % 256;
+			uint32_t g = mwc.gen() % 256;
+			uint32_t b = mwc.gen() % 256;
+			m.mesh = 1+mwc.gen()%(MESH_COUNT-1);
+			m.color[0] = r/255.0f;
+			m.color[1] = g/255.0f;
+			m.color[2] = b/255.0f;
+			m.color[3] = 1.0f;
+			m.position[0] = (((mwc.gen() % 256)) - 128.0f)/20.0f;
+			m.position[1] = 0;
+			m.position[2] = (((mwc.gen() % 256)) - 128.0f)/20.0f;
+		}
+
+		// Load ground.  We'll just use the cube since I don't have a ground model right now
+		m_ground = meshLoad("meshes/cube.bin");
+
+		// Light sphere
+		m_lightSphere = meshLoad("meshes/unit_sphere.bin");
+
+		const uint32_t samplerFlags = 0
+			| BGFX_TEXTURE_RT
+			| BGFX_TEXTURE_MIN_POINT
+			| BGFX_TEXTURE_MAG_POINT
+			| BGFX_TEXTURE_MIP_POINT
+			| BGFX_TEXTURE_U_CLAMP
+			| BGFX_TEXTURE_V_CLAMP
+			;
+
+		// Make gbuffer and related textures
+		m_gbufferTex[GBUFFER_RT_NORMAL] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
+		m_gbufferTex[GBUFFER_RT_COLOR]  = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
+		m_gbufferTex[GBUFFER_RT_DEPTH]  = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::D24,   samplerFlags);
+		m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_gbufferTex), m_gbufferTex, true);
+
+		// Make light buffer
+		m_lightBufferTex = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
+		bgfx::TextureHandle lightBufferRTs[] =  {
+			m_lightBufferTex
+		};
+		m_lightBuffer = bgfx::createFrameBuffer(BX_COUNTOF(lightBufferRTs), lightBufferRTs, true);
+
+		// Make shadow buffer
+		const uint32_t rsmFlags = 0
+			| BGFX_TEXTURE_RT
+			| BGFX_TEXTURE_MIN_POINT
+			| BGFX_TEXTURE_MAG_POINT
+			| BGFX_TEXTURE_MIP_POINT
+			| BGFX_TEXTURE_U_CLAMP
+			| BGFX_TEXTURE_V_CLAMP
+			;
+
+		// Reflective shadow map
+		m_shadowBufferTex[SHADOW_RT_RSM] = bgfx::createTexture2D(
+				SHADOW_MAP_DIM
+				, SHADOW_MAP_DIM
+				, 1
+				, bgfx::TextureFormat::BGRA8,
+				rsmFlags
+				);
+
+		// Typical shadow map
+		m_shadowBufferTex[SHADOW_RT_DEPTH] = bgfx::createTexture2D(
+				SHADOW_MAP_DIM
+				, SHADOW_MAP_DIM
+				, 1
+				, bgfx::TextureFormat::D16,
+				BGFX_TEXTURE_RT/* | BGFX_TEXTURE_COMPARE_LEQUAL*/
+				);  // Note I'm not setting BGFX_TEXTURE_COMPARE_LEQUAL.  Why?
+		// Normally a PCF shadow map such as this requires a compare.  However, this sample also
+		// reads from this texture in the lighting pass, and only uses the PCF capabilites in the
+		// combine pass, so the flag is disabled by default.
+
+		m_shadowBuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_shadowBufferTex), m_shadowBufferTex, true);
+
+		// Vertex decl
+		PosTexCoord0Vertex::init();
+
+		// Init camera
+		cameraCreate();
+		float camPos[] = {0.0f, 1.5f, 0.0f};
+		cameraSetPosition(camPos);
+		cameraSetVerticalAngle(-0.3f);
+
+		// Init directional light
+		updateLightDir();
+
+		// Get renderer capabilities info.
+		m_caps = bgfx::getCaps();
+		const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
+		m_texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
+
+		imguiCreate();
+	}
 
 	int shutdown() BX_OVERRIDE
 	{
-        for (uint32_t i = 0; i < MESH_COUNT; i++) {
-            meshUnload(m_meshes[i]);
-        }
-        meshUnload(m_ground);
-        meshUnload(m_lightSphere);
+		for (uint32_t i = 0; i < MESH_COUNT; i++)
+		{
+			meshUnload(m_meshes[i]);
+		}
+
+		meshUnload(m_ground);
+		meshUnload(m_lightSphere);
 
 		// Cleanup.
 		bgfx::destroyProgram(m_gbufferProgram);
-        bgfx::destroyProgram(m_lightProgram);
-        bgfx::destroyProgram(m_combineProgram);
-        bgfx::destroyProgram(m_shadowProgram);
+		bgfx::destroyProgram(m_lightProgram);
+		bgfx::destroyProgram(m_combineProgram);
+		bgfx::destroyProgram(m_shadowProgram);
 
 		bgfx::destroyUniform(u_tint);
-        bgfx::destroyUniform(u_lightDir);
-        bgfx::destroyUniform(u_sphereInfo);
-        bgfx::destroyUniform(u_invMvp);
-        bgfx::destroyUniform(u_invMvpShadow);
-        bgfx::destroyUniform(u_lightMtx);
-        bgfx::destroyUniform(u_shadowDimsInv);
-        bgfx::destroyUniform(u_rsmAmount);
-        bgfx::destroyUniform(s_normal);
-        bgfx::destroyUniform(s_depth);
-        bgfx::destroyUniform(s_light);
-        bgfx::destroyUniform(s_color);
-        bgfx::destroyUniform(s_shadowMap);
-        bgfx::destroyUniform(s_rsm);
-
-        bgfx::destroyFrameBuffer(m_gbuffer);
-        bgfx::destroyFrameBuffer(m_lightBuffer);
-        bgfx::destroyFrameBuffer(m_shadowBuffer);
-
-        for (uint32_t i = 0; i < BX_COUNTOF(m_gbufferTex); i++)
-            bgfx::destroyTexture(m_gbufferTex[i]);
-
-        bgfx::destroyTexture(m_lightBufferTex);
-        for (uint32_t i = 0; i < BX_COUNTOF(m_shadowBufferTex); i++)
-            bgfx::destroyTexture(m_shadowBufferTex[i]);
-
-        cameraDestroy();
-
-        imguiDestroy();
+		bgfx::destroyUniform(u_lightDir);
+		bgfx::destroyUniform(u_sphereInfo);
+		bgfx::destroyUniform(u_invMvp);
+		bgfx::destroyUniform(u_invMvpShadow);
+		bgfx::destroyUniform(u_lightMtx);
+		bgfx::destroyUniform(u_shadowDimsInv);
+		bgfx::destroyUniform(u_rsmAmount);
+		bgfx::destroyUniform(s_normal);
+		bgfx::destroyUniform(s_depth);
+		bgfx::destroyUniform(s_light);
+		bgfx::destroyUniform(s_color);
+		bgfx::destroyUniform(s_shadowMap);
+		bgfx::destroyUniform(s_rsm);
+
+		bgfx::destroyFrameBuffer(m_gbuffer);
+		bgfx::destroyFrameBuffer(m_lightBuffer);
+		bgfx::destroyFrameBuffer(m_shadowBuffer);
+
+		for (uint32_t i = 0; i < BX_COUNTOF(m_gbufferTex); i++)
+			bgfx::destroyTexture(m_gbufferTex[i]);
+
+		bgfx::destroyTexture(m_lightBufferTex);
+		for (uint32_t i = 0; i < BX_COUNTOF(m_shadowBufferTex); i++)
+			bgfx::destroyTexture(m_shadowBufferTex[i]);
+
+		cameraDestroy();
+
+		imguiDestroy();
 
 		// Shutdown bgfx.
 		bgfx::shutdown();
@@ -370,14 +382,14 @@ class ExampleReflectiveShadowMap : public entry::AppI
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
-            // Update frame timer
-            int64_t now = bx::getHPCounter();
-            static int64_t last = now;
-            const int64_t frameTime = now - last;
-            last = now;
-            const double freq = double(bx::getHPFrequency());
-            const double toMs = 1000.0 / freq;
-            const float deltaTime = float(frameTime/freq);
+			// Update frame timer
+			int64_t now = bx::getHPCounter();
+			static int64_t last = now;
+			const int64_t frameTime = now - last;
+			last = now;
+			const double freq = double(bx::getHPFrequency());
+			const double toMs = 1000.0 / freq;
+			const float deltaTime = float(frameTime/freq);
 
 			// Use debug font to print information about this example.
 			bgfx::dbgTextClear();
@@ -385,163 +397,163 @@ class ExampleReflectiveShadowMap : public entry::AppI
 			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: GI via reflective shadow map.");
 			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
 
-            // Update camera
-            cameraUpdate(deltaTime*0.15f, m_mouseState);
+			// Update camera
+			cameraUpdate(deltaTime*0.15f, m_mouseState);
 
-            // Set up matrices for gbuffer
+			// Set up matrices for gbuffer
 			float view[16];
 			cameraGetViewMtx(view);
 
 			float proj[16];
 			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f);
 
-            bgfx::setViewRect(RENDER_PASS_GBUFFER, 0, 0, uint16_t(m_width), uint16_t(m_height));
-            bgfx::setViewTransform(RENDER_PASS_GBUFFER, view, proj);
-            // Make sure when we draw it goes into gbuffer and not backbuffer
-            bgfx::setViewFrameBuffer(RENDER_PASS_GBUFFER, m_gbuffer);
-            // Draw everything into g-buffer
-            drawAllModels(RENDER_PASS_GBUFFER, m_gbufferProgram);
-            
-            // Draw shadow map
-            
-            // Set up transforms for shadow map
-            float smView[16], smProj[16], lightEye[3], lightAt[3];
-            lightEye[0] = m_lightDir[0]*LIGHT_DIST;
-            lightEye[1] = m_lightDir[1]*LIGHT_DIST;
-            lightEye[2] = m_lightDir[2]*LIGHT_DIST;
-
-            lightAt[0] = 0.0f;
-            lightAt[1] = 0.0f;
-            lightAt[2] = 0.0f;
-
-            bx::mtxLookAt(smView, lightEye, lightAt);
-            const float area = 10.0f;
-            bgfx::RendererType::Enum renderer = bgfx::getRendererType();
-            bool flipV = false
-                || renderer == bgfx::RendererType::OpenGL
-                || renderer == bgfx::RendererType::OpenGLES
-                ;
-            bx::mtxOrtho(smProj, -area, area, -area, area, -100.0f, 100.0f, 0.0f, flipV);
-            bgfx::setViewTransform(RENDER_PASS_SHADOW_MAP, smView, smProj);
-            bgfx::setViewFrameBuffer(RENDER_PASS_SHADOW_MAP, m_shadowBuffer);
-            bgfx::setViewRect(RENDER_PASS_SHADOW_MAP, 0, 0, SHADOW_MAP_DIM, SHADOW_MAP_DIM);
-
-            drawAllModels(RENDER_PASS_SHADOW_MAP, m_shadowProgram);
-            
-            // Next draw light buffer
-
-            // Set up matrices for light buffer
-            bgfx::setViewRect(RENDER_PASS_LIGHT_BUFFER, 0, 0, uint16_t(m_width), uint16_t(m_height));
-            bgfx::setViewTransform(RENDER_PASS_LIGHT_BUFFER, view, proj);  // Notice, same view and proj as gbuffer
-            // Set drawing into light buffer
-            bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_BUFFER, m_lightBuffer);
-
-            // Inverse view projection is needed in shader so set that up
-            float vp[16], invMvp[16];
-            bx::mtxMul(vp, view, proj);
-            bx::mtxInverse(invMvp, vp);
-
-            // Light matrix used in combine pass and inverse used in light pass
-            float lightMtx[16]; // World space to light space (shadow map space)
-            bx::mtxMul(lightMtx, smView, smProj);
-            float invMvpShadow[16];
-            bx::mtxInverse(invMvpShadow, lightMtx);
-
-            // Draw some lights (these should really be instanced but for this example they aren't...)
-            const unsigned MAX_SPHERE = 32;
-            for (uint32_t i = 0; i < MAX_SPHERE; i++) {
-                for (uint32_t j = 0; j < MAX_SPHERE; j++) {
-                    // These are used in the fragment shader
-                    bgfx::setTexture(0, s_normal, m_gbuffer, GBUFFER_RT_NORMAL);  // Normal for lighting calculations
-                    bgfx::setTexture(1, s_depth,  m_gbuffer, GBUFFER_RT_DEPTH);   // Depth to reconstruct world position
-
-                    // Thse are used in the vert shader
-                    bgfx::setTexture(2, s_shadowMap, m_shadowBuffer, SHADOW_RT_DEPTH);  // Used to place sphere
-                    bgfx::setTexture(3, s_rsm,       m_shadowBuffer, SHADOW_RT_RSM);    // Used to scale/color sphere
-
-                    bgfx::setUniform(u_invMvp, invMvp);
-                    bgfx::setUniform(u_invMvpShadow, invMvpShadow);
-                    float sphereInfo[4];
-                    sphereInfo[0] = ((float)i/(MAX_SPHERE-1));
-                    sphereInfo[1] = ((float)j/(MAX_SPHERE-1));
-                    sphereInfo[2] = m_vplRadius;
-                    sphereInfo[3] = 0.0;  // Unused
-                    bgfx::setUniform(u_sphereInfo, sphereInfo);
-
-                    const uint64_t lightDrawState = 0
-                        | BGFX_STATE_RGB_WRITE
-                        | BGFX_STATE_BLEND_ADD   // <===  Overlapping lights contribute more
-                        | BGFX_STATE_ALPHA_WRITE
-                        | BGFX_STATE_CULL_CW     // <===  If we go into the lights, there will be problems, so we draw the far back face.
-                        ;
-
-                    meshSubmit(
-                        m_lightSphere,
-                        RENDER_PASS_LIGHT_BUFFER,
-                        m_lightProgram,
-                        NULL,
-                        lightDrawState
-                        );
-                }
-            }
-            
-            // Draw combine pass
-
-            // Texture inputs for combine pass
-            bgfx::setTexture(0, s_normal, m_gbuffer, GBUFFER_RT_NORMAL);
-            bgfx::setTexture(1, s_color, m_gbuffer, GBUFFER_RT_COLOR);  
-            bgfx::setTexture(2, s_light, m_lightBuffer, 0);
-            bgfx::setTexture(3, s_depth, m_gbuffer, GBUFFER_RT_DEPTH);
-            bgfx::setTexture(4, s_shadowMap, m_shadowBuffer, SHADOW_RT_DEPTH, BGFX_TEXTURE_COMPARE_LEQUAL);
-
-            // Uniforms for combine pass
-
-            bgfx::setUniform(u_lightDir, m_lightDir);
-            bgfx::setUniform(u_invMvp, invMvp);
-            bgfx::setUniform(u_lightMtx, lightMtx);
-            const float invDim[4] = {1.0f/SHADOW_MAP_DIM, 0.0f, 0.0f, 0.0f};
-            bgfx::setUniform(u_shadowDimsInv, invDim);
-            float rsmAmount[4] = {m_rsmAmount,m_rsmAmount,m_rsmAmount,m_rsmAmount};
-            bgfx::setUniform(u_rsmAmount, rsmAmount);
-
-            // Set up state for combine pass
-            // point of this is to avoid doing depth test, which is in the default state
-            bgfx::setState(0
-                | BGFX_STATE_RGB_WRITE
-                | BGFX_STATE_ALPHA_WRITE
-                );
-
-            // Set up transform matrix for fullscreen quad
-            float orthoProj[16];
-            bx::mtxOrtho(orthoProj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
-            bgfx::setViewTransform(RENDER_PASS_COMBINE,   NULL, orthoProj);
-            bgfx::setViewRect(RENDER_PASS_COMBINE, 0, 0, m_width, m_height);
-            // Bind vertex buffer and draw quad
-            screenSpaceQuad( (float)m_width, (float)m_height, m_texelHalf, m_caps->originBottomLeft);
-            bgfx::submit(RENDER_PASS_COMBINE, m_combineProgram);
-
-            // Draw UI
-            imguiBeginFrame(m_mouseState.m_mx
-                , m_mouseState.m_my
-                , (m_mouseState.m_buttons[entry::MouseButton::Left] ? IMGUI_MBUT_LEFT : 0)
-                | (m_mouseState.m_buttons[entry::MouseButton::Right] ? IMGUI_MBUT_RIGHT : 0)
-                | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
-                , m_mouseState.m_mz
-                , m_width
-                , m_height
-                );
-
-            imguiBeginArea("RSM:", 10, 100, 300, 400);
-
-            imguiSlider("rsm amount", m_rsmAmount, 0.0f, 0.7f, 0.01f);
-            imguiSlider("vpl radius", m_vplRadius, 0.25f, 20.0f, 0.1f);
-            imguiSlider("light azimuth", m_lightAzimuth, 0.0f, 360.0f, 0.01f);
-            imguiSlider("light elevation", m_lightElevation, 35.0f, 90.0f, 0.01f);
-            
-            imguiEndArea();
-            imguiEndFrame();
-
-            updateLightDir();
+			bgfx::setViewRect(RENDER_PASS_GBUFFER, 0, 0, uint16_t(m_width), uint16_t(m_height));
+			bgfx::setViewTransform(RENDER_PASS_GBUFFER, view, proj);
+			// Make sure when we draw it goes into gbuffer and not backbuffer
+			bgfx::setViewFrameBuffer(RENDER_PASS_GBUFFER, m_gbuffer);
+			// Draw everything into g-buffer
+			drawAllModels(RENDER_PASS_GBUFFER, m_gbufferProgram);
+
+			// Draw shadow map
+
+			// Set up transforms for shadow map
+			float smView[16], smProj[16], lightEye[3], lightAt[3];
+			lightEye[0] = m_lightDir[0]*LIGHT_DIST;
+			lightEye[1] = m_lightDir[1]*LIGHT_DIST;
+			lightEye[2] = m_lightDir[2]*LIGHT_DIST;
+
+			lightAt[0] = 0.0f;
+			lightAt[1] = 0.0f;
+			lightAt[2] = 0.0f;
+
+			bx::mtxLookAt(smView, lightEye, lightAt);
+			const float area = 10.0f;
+			bgfx::RendererType::Enum renderer = bgfx::getRendererType();
+			bool flipV = false
+				|| renderer == bgfx::RendererType::OpenGL
+				|| renderer == bgfx::RendererType::OpenGLES
+				;
+			bx::mtxOrtho(smProj, -area, area, -area, area, -100.0f, 100.0f, 0.0f, flipV);
+			bgfx::setViewTransform(RENDER_PASS_SHADOW_MAP, smView, smProj);
+			bgfx::setViewFrameBuffer(RENDER_PASS_SHADOW_MAP, m_shadowBuffer);
+			bgfx::setViewRect(RENDER_PASS_SHADOW_MAP, 0, 0, SHADOW_MAP_DIM, SHADOW_MAP_DIM);
+
+			drawAllModels(RENDER_PASS_SHADOW_MAP, m_shadowProgram);
+
+			// Next draw light buffer
+
+			// Set up matrices for light buffer
+			bgfx::setViewRect(RENDER_PASS_LIGHT_BUFFER, 0, 0, uint16_t(m_width), uint16_t(m_height));
+			bgfx::setViewTransform(RENDER_PASS_LIGHT_BUFFER, view, proj);  // Notice, same view and proj as gbuffer
+			// Set drawing into light buffer
+			bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_BUFFER, m_lightBuffer);
+
+			// Inverse view projection is needed in shader so set that up
+			float vp[16], invMvp[16];
+			bx::mtxMul(vp, view, proj);
+			bx::mtxInverse(invMvp, vp);
+
+			// Light matrix used in combine pass and inverse used in light pass
+			float lightMtx[16]; // World space to light space (shadow map space)
+			bx::mtxMul(lightMtx, smView, smProj);
+			float invMvpShadow[16];
+			bx::mtxInverse(invMvpShadow, lightMtx);
+
+			// Draw some lights (these should really be instanced but for this example they aren't...)
+			const unsigned MAX_SPHERE = 32;
+			for (uint32_t i = 0; i < MAX_SPHERE; i++) {
+				for (uint32_t j = 0; j < MAX_SPHERE; j++) {
+					// These are used in the fragment shader
+					bgfx::setTexture(0, s_normal, m_gbuffer, GBUFFER_RT_NORMAL);  // Normal for lighting calculations
+					bgfx::setTexture(1, s_depth,  m_gbuffer, GBUFFER_RT_DEPTH);   // Depth to reconstruct world position
+
+					// Thse are used in the vert shader
+					bgfx::setTexture(2, s_shadowMap, m_shadowBuffer, SHADOW_RT_DEPTH);  // Used to place sphere
+					bgfx::setTexture(3, s_rsm,       m_shadowBuffer, SHADOW_RT_RSM);    // Used to scale/color sphere
+
+					bgfx::setUniform(u_invMvp, invMvp);
+					bgfx::setUniform(u_invMvpShadow, invMvpShadow);
+					float sphereInfo[4];
+					sphereInfo[0] = ((float)i/(MAX_SPHERE-1));
+					sphereInfo[1] = ((float)j/(MAX_SPHERE-1));
+					sphereInfo[2] = m_vplRadius;
+					sphereInfo[3] = 0.0;  // Unused
+					bgfx::setUniform(u_sphereInfo, sphereInfo);
+
+					const uint64_t lightDrawState = 0
+						| BGFX_STATE_RGB_WRITE
+						| BGFX_STATE_BLEND_ADD   // <===  Overlapping lights contribute more
+						| BGFX_STATE_ALPHA_WRITE
+						| BGFX_STATE_CULL_CW     // <===  If we go into the lights, there will be problems, so we draw the far back face.
+						;
+
+					meshSubmit(
+							m_lightSphere,
+							RENDER_PASS_LIGHT_BUFFER,
+							m_lightProgram,
+							NULL,
+							lightDrawState
+							);
+				}
+			}
+
+			// Draw combine pass
+
+			// Texture inputs for combine pass
+			bgfx::setTexture(0, s_normal, m_gbuffer, GBUFFER_RT_NORMAL);
+			bgfx::setTexture(1, s_color, m_gbuffer, GBUFFER_RT_COLOR);
+			bgfx::setTexture(2, s_light, m_lightBuffer, 0);
+			bgfx::setTexture(3, s_depth, m_gbuffer, GBUFFER_RT_DEPTH);
+			bgfx::setTexture(4, s_shadowMap, m_shadowBuffer, SHADOW_RT_DEPTH, BGFX_TEXTURE_COMPARE_LEQUAL);
+
+			// Uniforms for combine pass
+
+			bgfx::setUniform(u_lightDir, m_lightDir);
+			bgfx::setUniform(u_invMvp, invMvp);
+			bgfx::setUniform(u_lightMtx, lightMtx);
+			const float invDim[4] = {1.0f/SHADOW_MAP_DIM, 0.0f, 0.0f, 0.0f};
+			bgfx::setUniform(u_shadowDimsInv, invDim);
+			float rsmAmount[4] = {m_rsmAmount,m_rsmAmount,m_rsmAmount,m_rsmAmount};
+			bgfx::setUniform(u_rsmAmount, rsmAmount);
+
+			// Set up state for combine pass
+			// point of this is to avoid doing depth test, which is in the default state
+			bgfx::setState(0
+					| BGFX_STATE_RGB_WRITE
+					| BGFX_STATE_ALPHA_WRITE
+					);
+
+			// Set up transform matrix for fullscreen quad
+			float orthoProj[16];
+			bx::mtxOrtho(orthoProj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
+			bgfx::setViewTransform(RENDER_PASS_COMBINE,   NULL, orthoProj);
+			bgfx::setViewRect(RENDER_PASS_COMBINE, 0, 0, m_width, m_height);
+			// Bind vertex buffer and draw quad
+			screenSpaceQuad( (float)m_width, (float)m_height, m_texelHalf, m_caps->originBottomLeft);
+			bgfx::submit(RENDER_PASS_COMBINE, m_combineProgram);
+
+			// Draw UI
+			imguiBeginFrame(m_mouseState.m_mx
+					, m_mouseState.m_my
+					, (m_mouseState.m_buttons[entry::MouseButton::Left] ? IMGUI_MBUT_LEFT : 0)
+					| (m_mouseState.m_buttons[entry::MouseButton::Right] ? IMGUI_MBUT_RIGHT : 0)
+					| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
+					, m_mouseState.m_mz
+					, m_width
+					, m_height
+					);
+
+			imguiBeginArea("RSM:", 10, 100, 300, 400);
+
+			imguiSlider("rsm amount", m_rsmAmount, 0.0f, 0.7f, 0.01f);
+			imguiSlider("vpl radius", m_vplRadius, 0.25f, 20.0f, 0.1f);
+			imguiSlider("light azimuth", m_lightAzimuth, 0.0f, 360.0f, 0.01f);
+			imguiSlider("light elevation", m_lightElevation, 35.0f, 90.0f, 0.01f);
+
+			imguiEndArea();
+			imguiEndFrame();
+
+			updateLightDir();
 
 			// Advance to next frame. Rendering thread will be kicked to
 			// process submitted rendering primitives.
@@ -553,137 +565,132 @@ class ExampleReflectiveShadowMap : public entry::AppI
 		return false;
 	}
 
-    void drawAllModels(uint8_t _pass, bgfx::ProgramHandle _program) {
-        for (const Model & m : m_models) {
-            // Set up transform matrix for each model
-            float scale = m_meshScale[m.mesh];
-            float mtx[16];
-            bx::mtxSRT(mtx
-                , scale
-                , scale
-                , scale
-                , 0.0f
-                , 0.0f
-                , 0.0f
-                , m.position[0]
-                , m.position[1]
-                , m.position[2]
-                );
-            
-            // Submit mesh to gbuffer
-            bgfx::setUniform(u_tint, m.color);
-            meshSubmit(m_meshes[m.mesh], _pass, _program, mtx);
-        }
-
-        // Draw ground
-        const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-        bgfx::setUniform(u_tint, white);
-        float mtxScale[16];
-        float scale = 10.0;
-        bx::mtxScale(mtxScale
-            , scale
-            , scale
-            , scale
-            );
-        float mtxTrans[16];
-        bx::mtxTranslate(mtxTrans
-            , 0.0f
-            , -10.0f
-            , 0.0f
-            );
-        float mtx[16];
-        bx::mtxMul(mtx, mtxScale, mtxTrans);
-        meshSubmit(m_ground, _pass, _program, mtx);
-    }
-
-    void updateLightDir () {
-        float el = m_lightElevation * (bx::pi/180.0f);
-        float az = m_lightAzimuth * (bx::pi/180.0f);
-        m_lightDir[0] = cos(el)*cos(az);
-        m_lightDir[2] = cos(el)*sin(az);
-        m_lightDir[1] = sin(el);
-        m_lightDir[3] = 0.0f;
-    }
+	void drawAllModels(uint8_t _pass, bgfx::ProgramHandle _program)
+	{
+		for (const Model & m : m_models)
+		{
+			// Set up transform matrix for each model
+			float scale = m_meshScale[m.mesh];
+			float mtx[16];
+			bx::mtxSRT(mtx
+					, scale
+					, scale
+					, scale
+					, 0.0f
+					, 0.0f
+					, 0.0f
+					, m.position[0]
+					, m.position[1]
+					, m.position[2]
+					);
+
+			// Submit mesh to gbuffer
+			bgfx::setUniform(u_tint, m.color);
+			meshSubmit(m_meshes[m.mesh], _pass, _program, mtx);
+		}
+
+		// Draw ground
+		const float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+		bgfx::setUniform(u_tint, white);
+		float mtxScale[16];
+		float scale = 10.0;
+		bx::mtxScale(mtxScale
+				, scale
+				, scale
+				, scale
+				);
+		float mtxTrans[16];
+		bx::mtxTranslate(mtxTrans
+				, 0.0f
+				, -10.0f
+				, 0.0f
+				);
+		float mtx[16];
+		bx::mtxMul(mtx, mtxScale, mtxTrans);
+		meshSubmit(m_ground, _pass, _program, mtx);
+	}
+
+	void updateLightDir()
+	{
+		float el = m_lightElevation * (bx::pi/180.0f);
+		float az = m_lightAzimuth * (bx::pi/180.0f);
+		m_lightDir[0] = cos(el)*cos(az);
+		m_lightDir[2] = cos(el)*sin(az);
+		m_lightDir[1] = sin(el);
+		m_lightDir[3] = 0.0f;
+	}
 
 	uint32_t m_width;
 	uint32_t m_height;
 	uint32_t m_debug;
 	uint32_t m_reset;
 
-    entry::MouseState m_mouseState;
-	
-    Mesh* m_ground;
-    Mesh* m_lightSphere; // Unit sphere
-    
-    // Resource handles
+	entry::MouseState m_mouseState;
+
+	Mesh* m_ground;
+	Mesh* m_lightSphere; // Unit sphere
+
+	// Resource handles
 	bgfx::ProgramHandle m_gbufferProgram;
-    bgfx::ProgramHandle m_shadowProgram;
-    bgfx::ProgramHandle m_lightProgram;
-    bgfx::ProgramHandle m_combineProgram;
-    bgfx::FrameBufferHandle m_gbuffer;
-    bgfx::FrameBufferHandle m_lightBuffer;
-    bgfx::FrameBufferHandle m_shadowBuffer;
-
-    // Shader uniforms
-    bgfx::UniformHandle u_tint;
-    bgfx::UniformHandle u_invMvp;
-    bgfx::UniformHandle u_invMvpShadow;
-    bgfx::UniformHandle u_lightMtx;
-    bgfx::UniformHandle u_lightDir;
-    bgfx::UniformHandle u_sphereInfo;
-    bgfx::UniformHandle u_shadowDimsInv;
-    bgfx::UniformHandle u_rsmAmount;
-
-    // Uniforms to identify texture samples
-    bgfx::UniformHandle s_normal;
-    bgfx::UniformHandle s_depth;
-    bgfx::UniformHandle s_color;
-    bgfx::UniformHandle s_light;
-    bgfx::UniformHandle s_shadowMap;
-    bgfx::UniformHandle s_rsm;
-
-    // Various render targets
-    bgfx::TextureHandle m_gbufferTex[3];
-    bgfx::TextureHandle m_lightBufferTex;
-    bgfx::TextureHandle m_shadowBufferTex[2];
-
-    uint32_t m_reading = 0;
-    uint32_t m_currFrame = UINT32_MAX;
-
-    // UI 
-    bool m_cameraSpin = false;
-
-    struct Model {
-        uint32_t mesh; // Index of mesh in m_meshes
-        float color[4];
-        float position[3];
-    };
-
-    Model m_models[MODEL_COUNT];
-
-    const char * m_meshPaths[MESH_COUNT] = {
-        "meshes/cube.bin"
-        ,"meshes/orb.bin"
-        ,"meshes/column.bin"
-        ,"meshes/bunny.bin"
-        ,"meshes/tree.bin"
-        ,"meshes/hollowcube.bin"
-    };
-
-    // Light position;
-    float m_lightDir[4];
-    float m_lightElevation = 35.0f;
-    float m_lightAzimuth = 215.0f;
-
-    
-    float m_rsmAmount = 0.25f; // Amount of rsm
-    float m_vplRadius = 3.0f;  // Radius of virtual point light
-
-    const float m_meshScale[MESH_COUNT] = {0.25f, 0.5f, 0.05f, 0.5f, 0.05f, 0.05f};
-    const bgfx::Caps* m_caps;
-    Mesh * m_meshes[MESH_COUNT];
-    
-    float m_texelHalf = 0.0f;  // Texel offset for dx9
+	bgfx::ProgramHandle m_shadowProgram;
+	bgfx::ProgramHandle m_lightProgram;
+	bgfx::ProgramHandle m_combineProgram;
+	bgfx::FrameBufferHandle m_gbuffer;
+	bgfx::FrameBufferHandle m_lightBuffer;
+	bgfx::FrameBufferHandle m_shadowBuffer;
+
+	// Shader uniforms
+	bgfx::UniformHandle u_tint;
+	bgfx::UniformHandle u_invMvp;
+	bgfx::UniformHandle u_invMvpShadow;
+	bgfx::UniformHandle u_lightMtx;
+	bgfx::UniformHandle u_lightDir;
+	bgfx::UniformHandle u_sphereInfo;
+	bgfx::UniformHandle u_shadowDimsInv;
+	bgfx::UniformHandle u_rsmAmount;
+
+	// Uniforms to identify texture samples
+	bgfx::UniformHandle s_normal;
+	bgfx::UniformHandle s_depth;
+	bgfx::UniformHandle s_color;
+	bgfx::UniformHandle s_light;
+	bgfx::UniformHandle s_shadowMap;
+	bgfx::UniformHandle s_rsm;
+
+	// Various render targets
+	bgfx::TextureHandle m_gbufferTex[3];
+	bgfx::TextureHandle m_lightBufferTex;
+	bgfx::TextureHandle m_shadowBufferTex[2];
+
+	uint32_t m_reading = 0;
+	uint32_t m_currFrame = UINT32_MAX;
+
+	// UI
+	bool m_cameraSpin = false;
+
+	struct Model
+	{
+		uint32_t mesh; // Index of mesh in m_meshes
+		float color[4];
+		float position[3];
+	};
+
+	Model m_models[MODEL_COUNT];
+
+	// Light position;
+	float m_lightDir[4];
+	float m_lightElevation = 35.0f;
+	float m_lightAzimuth = 215.0f;
+
+
+	float m_rsmAmount = 0.25f; // Amount of rsm
+	float m_vplRadius = 3.0f;  // Radius of virtual point light
+
+	const float m_meshScale[MESH_COUNT] = {0.25f, 0.5f, 0.05f, 0.5f, 0.05f, 0.05f};
+	const bgfx::Caps* m_caps;
+	Mesh * m_meshes[MESH_COUNT];
+
+	float m_texelHalf = 0.0f;  // Texel offset for dx9
 };
 
 ENTRY_IMPLEMENT_MAIN(ExampleReflectiveShadowMap);