Browse Source

Fixed 21-deferred for Emscripten.

Branimir Karadžić 10 years ago
parent
commit
46eba42ba0
3 changed files with 513 additions and 448 deletions
  1. 508 443
      examples/21-deferred/deferred.cpp
  2. 4 4
      examples/common/camera.cpp
  3. 1 1
      examples/common/camera.h

+ 508 - 443
examples/21-deferred/deferred.cpp

@@ -15,6 +15,7 @@
 #define RENDER_PASS_DEBUG_LIGHTS_ID   3
 #define RENDER_PASS_DEBUG_LIGHTS_ID   3
 #define RENDER_PASS_DEBUG_GBUFFER_ID  4
 #define RENDER_PASS_DEBUG_GBUFFER_ID  4
 
 
+static float s_texelHalf = 0.0f;
 static bool s_originBottomLeft = false;
 static bool s_originBottomLeft = false;
 
 
 inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far)
 inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far)
@@ -217,516 +218,580 @@ void screenSpaceQuad(float _textureWidth, float _textureHeight, float _texelHalf
 	}
 	}
 }
 }
 
 
-int _main_(int /*_argc*/, char** /*_argv*/)
+class Deferred : public entry::AppI
 {
 {
-	uint32_t width = 1280;
-	uint32_t height = 720;
-	uint32_t debug = BGFX_DEBUG_TEXT;
-	uint32_t reset = BGFX_RESET_VSYNC;
-
-	bgfx::init();
-	bgfx::reset(width, height, reset);
-
-	// Enable debug text.
-	bgfx::setDebug(debug);
-
-	// Set clear color palette for index 0
-	bgfx::setClearColor(0, UINT32_C(0x00000000) );
-
-	// Set clear color palette for index 1
-	bgfx::setClearColor(1, UINT32_C(0x303030ff) );
-
-	// Set geometry pass view clear state.
-	bgfx::setViewClear(RENDER_PASS_GEOMETRY_ID
-		, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-		, 1.0f
-		, 0
-		, 1
-		);
-
-	// Set light pass view clear state.
-	bgfx::setViewClear(RENDER_PASS_LIGHT_ID
-		, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-		, 1.0f
-		, 0
-		, 0
-		);
-
-	// Create vertex stream declaration.
-	PosNormalTangentTexcoordVertex::init();
-	PosTexCoord0Vertex::init();
-	DebugVertex::init();
-
-	calcTangents(s_cubeVertices
-		, BX_COUNTOF(s_cubeVertices)
-		, PosNormalTangentTexcoordVertex::ms_decl
-		, s_cubeIndices
-		, BX_COUNTOF(s_cubeIndices)
-		);
-
-	// Create static vertex buffer.
-	bgfx::VertexBufferHandle vbh = bgfx::createVertexBuffer(
-		  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
-		, PosNormalTangentTexcoordVertex::ms_decl
-		);
-
-	// Create static index buffer.
-	bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );
-
-	// Create texture sampler uniforms.
-	bgfx::UniformHandle s_texColor  = bgfx::createUniform("s_texColor",  bgfx::UniformType::Int1);
-	bgfx::UniformHandle s_texNormal = bgfx::createUniform("s_texNormal", bgfx::UniformType::Int1);
-
-	bgfx::UniformHandle s_albedo = bgfx::createUniform("s_albedo", bgfx::UniformType::Int1);
-	bgfx::UniformHandle s_normal = bgfx::createUniform("s_normal", bgfx::UniformType::Int1);
-	bgfx::UniformHandle s_depth  = bgfx::createUniform("s_depth",  bgfx::UniformType::Int1);
-	bgfx::UniformHandle s_light  = bgfx::createUniform("s_light",  bgfx::UniformType::Int1);
-
-	bgfx::UniformHandle u_mtx            = bgfx::createUniform("u_mtx",            bgfx::UniformType::Mat4);
-	bgfx::UniformHandle u_lightPosRadius = bgfx::createUniform("u_lightPosRadius", bgfx::UniformType::Vec4);
-	bgfx::UniformHandle u_lightRgbInnerR = bgfx::createUniform("u_lightRgbInnerR", bgfx::UniformType::Vec4);
-
-	// Create program from shaders.
-	bgfx::ProgramHandle geomProgram    = loadProgram("vs_deferred_geom",       "fs_deferred_geom");
-	bgfx::ProgramHandle lightProgram   = loadProgram("vs_deferred_light",      "fs_deferred_light");
-	bgfx::ProgramHandle combineProgram = loadProgram("vs_deferred_combine",    "fs_deferred_combine");
-	bgfx::ProgramHandle debugProgram   = loadProgram("vs_deferred_debug",      "fs_deferred_debug");
-	bgfx::ProgramHandle lineProgram    = loadProgram("vs_deferred_debug_line", "fs_deferred_debug_line");
-
-	// Load diffuse texture.
-	bgfx::TextureHandle textureColor  = loadTexture("fieldstone-rgba.dds");
-
-	// Load normal texture.
-	bgfx::TextureHandle textureNormal = loadTexture("fieldstone-n.dds");
-
-	bgfx::TextureHandle gbufferTex[3] = { BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE };
-	bgfx::FrameBufferHandle gbuffer = BGFX_INVALID_HANDLE;
-	bgfx::FrameBufferHandle lightBuffer = BGFX_INVALID_HANDLE;
-
-	// Imgui.
-	imguiCreate();
-
-	const int64_t timeOffset = bx::getHPCounter();
-	const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
-	const float texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
-	s_originBottomLeft = bgfx::RendererType::OpenGL == renderer || bgfx::RendererType::OpenGLES == renderer;
-
-	// Get renderer capabilities info.
-	const bgfx::Caps* caps = bgfx::getCaps();
-
-	uint32_t oldWidth  = 0;
-	uint32_t oldHeight = 0;
-	uint32_t oldReset  = reset;
-
-	int32_t scrollArea = 0;
-	int32_t numLights = 512;
-	float lightAnimationSpeed = 0.3f;
-	bool animateMesh = true;
-	bool showScissorRects = false;
-	bool showGBuffer = true;
-
-	float view[16];
-	float initialPos[3] = { 0.0f, 0.0f, -15.0f };
-	cameraCreate();
-	cameraSetPosition(initialPos);
-	cameraSetVerticalAngle(0.0f);
-	cameraGetViewMtx(view);
-
-	entry::MouseState mouseState;
-	while (!entry::processEvents(width, height, debug, reset, &mouseState) )
+	void init(int /*_argc*/, char** /*_argv*/) BX_OVERRIDE
 	{
 	{
-		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);
-
-		float time = (float)( (now-timeOffset)/freq);
-
-		// Use debug font to print information about this example.
-		bgfx::dbgTextClear();
-		bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/21-deferred");
-		bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: MRT rendering and deferred shading.");
-		bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
-
-		if (2 > caps->maxFBAttachments)
-		{
-			// When multiple render targets (MRT) is not supported by GPU,
-			// implement alternative code path that doesn't use MRT.
-			bool blink = uint32_t(time*3.0f)&1;
-			bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " MRT not supported by GPU. ");
+		m_width = 1280;
+		m_height = 720;
+		m_debug = BGFX_DEBUG_TEXT;
+		m_reset = BGFX_RESET_VSYNC;
 
 
-			// Set view 0 default viewport.
-			bgfx::setViewRect(0, 0, 0, width, height);
+		bgfx::init();
+		bgfx::reset(m_width, m_height, m_reset);
 
 
-			// This dummy draw call is here to make sure that view 0 is cleared
-			// if no other draw calls are submitted to view 0.
-			bgfx::touch(0);
-		}
-		else
-		{
-			if (oldWidth  != width
-			||  oldHeight != height
-			||  oldReset  != reset
-			||  !bgfx::isValid(gbuffer) )
-			{
-				// Recreate variable size render targets when resolution changes.
-				oldWidth  = width;
-				oldHeight = height;
-				oldReset  = reset;
+		// Enable m_debug text.
+		bgfx::setDebug(m_debug);
 
 
-				if (bgfx::isValid(gbuffer) )
-				{
-					bgfx::destroyFrameBuffer(gbuffer);
-				}
+		// Set clear color palette for index 0
+		bgfx::setClearColor(0, UINT32_C(0x00000000) );
 
 
-				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
-					;
-				gbufferTex[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
-				gbufferTex[1] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
-				gbufferTex[2] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D24,   samplerFlags);
-				gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(gbufferTex), gbufferTex, true);
-
-				if (bgfx::isValid(lightBuffer) )
-				{
-					bgfx::destroyFrameBuffer(lightBuffer);
-				}
+		// Set clear color palette for index 1
+		bgfx::setClearColor(1, UINT32_C(0x303030ff) );
 
 
-				lightBuffer = bgfx::createFrameBuffer(width, height, bgfx::TextureFormat::BGRA8, samplerFlags);
-			}
+		// Set geometry pass view clear state.
+		bgfx::setViewClear(RENDER_PASS_GEOMETRY_ID
+				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+				, 1.0f
+				, 0
+				, 1
+				);
 
 
-			imguiBeginFrame(mouseState.m_mx
-				, mouseState.m_my
-				, (mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT  : 0)
-				| (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
-				, mouseState.m_mz
-				, width
-				, height
+		// Set light pass view clear state.
+		bgfx::setViewClear(RENDER_PASS_LIGHT_ID
+				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+				, 1.0f
+				, 0
+				, 0
 				);
 				);
 
 
-			imguiBeginScrollArea("Settings", width - width / 5 - 10, 10, width / 5, height / 3, &scrollArea);
-			imguiSeparatorLine();
+		// Create vertex stream declaration.
+		PosNormalTangentTexcoordVertex::init();
+		PosTexCoord0Vertex::init();
+		DebugVertex::init();
 
 
-			imguiSlider("Num lights", numLights, 1, 2048);
+		calcTangents(s_cubeVertices
+				, BX_COUNTOF(s_cubeVertices)
+				, PosNormalTangentTexcoordVertex::ms_decl
+				, s_cubeIndices
+				, BX_COUNTOF(s_cubeIndices)
+				);
 
 
-			if (imguiCheck("Show G-Buffer.", showGBuffer) )
-			{
-				showGBuffer = !showGBuffer;
-			}
+		// Create static vertex buffer.
+		m_vbh = bgfx::createVertexBuffer(
+				bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
+				, PosNormalTangentTexcoordVertex::ms_decl
+				);
 
 
-			if (imguiCheck("Show light scissor.", showScissorRects) )
-			{
-				showScissorRects = !showScissorRects;
-			}
+		// Create static index buffer.
+		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );
 
 
-			if (imguiCheck("Animate mesh.", animateMesh) )
-			{
-				animateMesh = !animateMesh;
-			}
+		// Create texture sampler uniforms.
+		s_texColor  = bgfx::createUniform("s_texColor",  bgfx::UniformType::Int1);
+		s_texNormal = bgfx::createUniform("s_texNormal", bgfx::UniformType::Int1);
 
 
-			imguiSlider("Lights animation speed", lightAnimationSpeed, 0.0f, 0.4f, 0.01f);
+		s_albedo = bgfx::createUniform("s_albedo", bgfx::UniformType::Int1);
+		s_normal = bgfx::createUniform("s_normal", bgfx::UniformType::Int1);
+		s_depth  = bgfx::createUniform("s_depth",  bgfx::UniformType::Int1);
+		s_light  = bgfx::createUniform("s_light",  bgfx::UniformType::Int1);
 
 
-			imguiEndScrollArea();
-			imguiEndFrame();
+		u_mtx            = bgfx::createUniform("u_mtx",            bgfx::UniformType::Mat4);
+		u_lightPosRadius = bgfx::createUniform("u_lightPosRadius", bgfx::UniformType::Vec4);
+		u_lightRgbInnerR = bgfx::createUniform("u_lightRgbInnerR", bgfx::UniformType::Vec4);
 
 
-			// Update camera.
-			cameraUpdate(deltaTime, mouseState);
-			cameraGetViewMtx(view);
+		// Create program from shaders.
+		m_geomProgram    = loadProgram("vs_deferred_geom",       "fs_deferred_geom");
+		m_lightProgram   = loadProgram("vs_deferred_light",      "fs_deferred_light");
+		m_combineProgram = loadProgram("vs_deferred_combine",    "fs_deferred_combine");
+		m_debugProgram   = loadProgram("vs_deferred_debug",      "fs_deferred_debug");
+		m_lineProgram    = loadProgram("vs_deferred_debug_line", "fs_deferred_debug_line");
 
 
-			// Setup views
-			float vp[16];
-			float invMvp[16];
-			{
-				bgfx::setViewRect(RENDER_PASS_GEOMETRY_ID,      0, 0, width, height);
-				bgfx::setViewRect(RENDER_PASS_LIGHT_ID,         0, 0, width, height);
-				bgfx::setViewRect(RENDER_PASS_COMBINE_ID,       0, 0, width, height);
-				bgfx::setViewRect(RENDER_PASS_DEBUG_LIGHTS_ID,  0, 0, width, height);
-				bgfx::setViewRect(RENDER_PASS_DEBUG_GBUFFER_ID, 0, 0, width, height);
+		// Load diffuse texture.
+		m_textureColor  = loadTexture("fieldstone-rgba.dds");
 
 
-				bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_ID, lightBuffer);
+		// Load normal texture.
+		m_textureNormal = loadTexture("fieldstone-n.dds");
 
 
-				float proj[16];
-				mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
+		m_gbufferTex[0].idx = bgfx::invalidHandle;
+		m_gbufferTex[1].idx = bgfx::invalidHandle;
+		m_gbufferTex[2].idx = bgfx::invalidHandle;
+		m_gbuffer.idx = bgfx::invalidHandle;
+		m_lightBuffer.idx = bgfx::invalidHandle;
 
 
-				bgfx::setViewFrameBuffer(RENDER_PASS_GEOMETRY_ID, gbuffer);
-				bgfx::setViewTransform(RENDER_PASS_GEOMETRY_ID, view, proj);
+		// Imgui.
+		imguiCreate();
 
 
-				bx::mtxMul(vp, view, proj);
-				bx::mtxInverse(invMvp, vp);
+		m_timeOffset = bx::getHPCounter();
+		const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
+		s_texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
+		s_originBottomLeft = bgfx::RendererType::OpenGL == renderer || bgfx::RendererType::OpenGLES == renderer;
 
 
-				bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
-				bgfx::setViewTransform(RENDER_PASS_LIGHT_ID,   NULL, proj);
-				bgfx::setViewTransform(RENDER_PASS_COMBINE_ID, NULL, proj);
+		// Get renderer capabilities info.
+		m_caps = bgfx::getCaps();
 
 
-				const float aspectRatio = float(height)/float(width);
-				const float size = 10.0f;
-				bx::mtxOrtho(proj, -size, size, size*aspectRatio, -size*aspectRatio, 0.0f, 1000.0f);
-				bgfx::setViewTransform(RENDER_PASS_DEBUG_GBUFFER_ID, NULL, proj);
+		m_oldWidth  = 0;
+		m_oldHeight = 0;
+		m_oldReset  = m_reset;
 
 
-				bx::mtxOrtho(proj, 0.0f, (float)width, 0.0f, (float)height, 0.0f, 1000.0f);
-				bgfx::setViewTransform(RENDER_PASS_DEBUG_LIGHTS_ID, NULL, proj);
-			}
+		m_scrollArea = 0;
+		m_numLights = 512;
+		m_lightAnimationSpeed = 0.3f;
+		m_animateMesh = true;
+		m_showScissorRects = false;
+		m_showGBuffer = true;
+
+		cameraCreate();
+
+		const float initialPos[3] = { 0.0f, 0.0f, -15.0f };
+		cameraSetPosition(initialPos);
+		cameraSetVerticalAngle(0.0f);
+	}
+
+	virtual int shutdown() BX_OVERRIDE
+	{
+		// Cleanup.
+		cameraDestroy();
+		imguiDestroy();
+
+		if (bgfx::isValid(m_gbuffer) )
+		{
+			bgfx::destroyFrameBuffer(m_gbuffer);
+			bgfx::destroyFrameBuffer(m_lightBuffer);
+		}
+
+		bgfx::destroyIndexBuffer(m_ibh);
+		bgfx::destroyVertexBuffer(m_vbh);
+
+		bgfx::destroyProgram(m_geomProgram);
+		bgfx::destroyProgram(m_lightProgram);
+		bgfx::destroyProgram(m_combineProgram);
+		bgfx::destroyProgram(m_debugProgram);
+		bgfx::destroyProgram(m_lineProgram);
 
 
-			const uint32_t dim = 11;
-			const float offset = (float(dim-1) * 3.0f) * 0.5f;
+		bgfx::destroyTexture(m_textureColor);
+		bgfx::destroyTexture(m_textureNormal);
+		bgfx::destroyUniform(s_texColor);
+		bgfx::destroyUniform(s_texNormal);
 
 
-			// Draw into geometry pass.
-			for (uint32_t yy = 0; yy < dim; ++yy)
+		bgfx::destroyUniform(s_albedo);
+		bgfx::destroyUniform(s_normal);
+		bgfx::destroyUniform(s_depth);
+		bgfx::destroyUniform(s_light);
+
+		bgfx::destroyUniform(u_lightPosRadius);
+		bgfx::destroyUniform(u_lightRgbInnerR);
+		bgfx::destroyUniform(u_mtx);
+
+		// Shutdown bgfx.
+		bgfx::shutdown();
+
+		return 0;
+	}
+
+	bool update() BX_OVERRIDE
+	{
+		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
+		{
+			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);
+
+			float time = (float)( (now-m_timeOffset)/freq);
+
+			// Use m_debug font to print information about this example.
+			bgfx::dbgTextClear();
+			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/21-deferred");
+			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: MRT rendering and deferred shading.");
+			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
+
+			if (2 > m_caps->maxFBAttachments)
 			{
 			{
-				for (uint32_t xx = 0; xx < dim; ++xx)
+				// When multiple render targets (MRT) is not supported by GPU,
+				// implement alternative code path that doesn't use MRT.
+				bool blink = uint32_t(time*3.0f)&1;
+				bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " MRT not supported by GPU. ");
+
+				// Set view 0 default viewport.
+				bgfx::setViewRect(0, 0, 0, m_width, m_height);
+
+				// This dummy draw call is here to make sure that view 0 is cleared
+				// if no other draw calls are submitted to view 0.
+				bgfx::touch(0);
+			}
+			else
+			{
+				if (m_oldWidth  != m_width
+						||  m_oldHeight != m_height
+						||  m_oldReset  != m_reset
+						||  !bgfx::isValid(m_gbuffer) )
 				{
 				{
-					float mtx[16];
-					if (animateMesh)
+					// Recreate variable size render targets when resolution changes.
+					m_oldWidth  = m_width;
+					m_oldHeight = m_height;
+					m_oldReset  = m_reset;
+
+					if (bgfx::isValid(m_gbuffer) )
 					{
 					{
-						bx::mtxRotateXY(mtx, time*1.023f + xx*0.21f, time*0.03f + yy*0.37f);
+						bgfx::destroyFrameBuffer(m_gbuffer);
 					}
 					}
-					else
+
+					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
+						;
+					m_gbufferTex[0] = bgfx::createTexture2D(m_width, m_height, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
+					m_gbufferTex[1] = bgfx::createTexture2D(m_width, m_height, 1, bgfx::TextureFormat::BGRA8, samplerFlags);
+					m_gbufferTex[2] = bgfx::createTexture2D(m_width, m_height, 1, bgfx::TextureFormat::D24,   samplerFlags);
+					m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_gbufferTex), m_gbufferTex, true);
+
+					if (bgfx::isValid(m_lightBuffer) )
 					{
 					{
-						bx::mtxIdentity(mtx);
+						bgfx::destroyFrameBuffer(m_lightBuffer);
 					}
 					}
-					mtx[12] = -offset + float(xx)*3.0f;
-					mtx[13] = -offset + float(yy)*3.0f;
-					mtx[14] = 0.0f;
 
 
-					// Set transform for draw call.
-					bgfx::setTransform(mtx);
+					m_lightBuffer = bgfx::createFrameBuffer(m_width, m_height, bgfx::TextureFormat::BGRA8, samplerFlags);
+				}
+
+				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_mz
+						, m_width
+						, m_height
+						);
 
 
-					// Set vertex and index buffer.
-					bgfx::setVertexBuffer(vbh);
-					bgfx::setIndexBuffer(ibh);
+				imguiBeginScrollArea("Settings", m_width - m_width / 5 - 10, 10, m_width / 5, m_height / 3, &m_scrollArea);
+				imguiSeparatorLine();
 
 
-					// Bind textures.
-					bgfx::setTexture(0, s_texColor,  textureColor);
-					bgfx::setTexture(1, s_texNormal, textureNormal);
+				imguiSlider("Num lights", m_numLights, 1, 2048);
 
 
-					// Set render states.
-					bgfx::setState(0
-						| BGFX_STATE_RGB_WRITE
-						| BGFX_STATE_ALPHA_WRITE
-						| BGFX_STATE_DEPTH_WRITE
-						| BGFX_STATE_DEPTH_TEST_LESS
-						| BGFX_STATE_MSAA
-						);
+				if (imguiCheck("Show G-Buffer.", m_showGBuffer) )
+				{
+					m_showGBuffer = !m_showGBuffer;
+				}
 
 
-					// Submit primitive for rendering to view 0.
-					bgfx::submit(RENDER_PASS_GEOMETRY_ID, geomProgram);
+				if (imguiCheck("Show light scissor.", m_showScissorRects) )
+				{
+					m_showScissorRects = !m_showScissorRects;
 				}
 				}
-			}
 
 
-			// Draw lights into light buffer.
-			for (int32_t light = 0; light < numLights; ++light)
-			{
-				Sphere lightPosRadius;
+				if (imguiCheck("Animate mesh.", m_animateMesh) )
+				{
+					m_animateMesh = !m_animateMesh;
+				}
 
 
-				float lightTime = time * lightAnimationSpeed * (sinf(light/float(numLights) * bx::piHalf ) * 0.5f + 0.5f);
-				lightPosRadius.m_center[0] = sinf( ( (lightTime + light*0.47f) + bx::piHalf*1.37f ) )*offset;
-				lightPosRadius.m_center[1] = cosf( ( (lightTime + light*0.69f) + bx::piHalf*1.49f ) )*offset;
-				lightPosRadius.m_center[2] = sinf( ( (lightTime + light*0.37f) + bx::piHalf*1.57f ) )*2.0f;
-				lightPosRadius.m_radius = 2.0f;
+				imguiSlider("Lights animation speed", m_lightAnimationSpeed, 0.0f, 0.4f, 0.01f);
 
 
-				Aabb aabb;
-				sphereToAabb(aabb, lightPosRadius);
+				imguiEndScrollArea();
+				imguiEndFrame();
 
 
-				float box[8][3] =
-				{
-					{ aabb.m_min[0], aabb.m_min[1], aabb.m_min[2] },
-					{ aabb.m_min[0], aabb.m_min[1], aabb.m_max[2] },
-					{ aabb.m_min[0], aabb.m_max[1], aabb.m_min[2] },
-					{ aabb.m_min[0], aabb.m_max[1], aabb.m_max[2] },
-					{ aabb.m_max[0], aabb.m_min[1], aabb.m_min[2] },
-					{ aabb.m_max[0], aabb.m_min[1], aabb.m_max[2] },
-					{ aabb.m_max[0], aabb.m_max[1], aabb.m_min[2] },
-					{ aabb.m_max[0], aabb.m_max[1], aabb.m_max[2] },
-				};
-
-				float xyz[3];
-				bx::vec3MulMtxH(xyz, box[0], vp);
-				float minx = xyz[0];
-				float miny = xyz[1];
-				float maxx = xyz[0];
-				float maxy = xyz[1];
-				float maxz = xyz[2];
-
-				for (uint32_t ii = 1; ii < 8; ++ii)
+				// Update camera.
+				cameraUpdate(deltaTime, m_mouseState);
+
+				float view[16];
+				cameraGetViewMtx(view);
+
+				// Setup views
+				float vp[16];
+				float invMvp[16];
 				{
 				{
-					bx::vec3MulMtxH(xyz, box[ii], vp);
-					minx = bx::fmin(minx, xyz[0]);
-					miny = bx::fmin(miny, xyz[1]);
-					maxx = bx::fmax(maxx, xyz[0]);
-					maxy = bx::fmax(maxy, xyz[1]);
-					maxz = bx::fmax(maxz, xyz[2]);
+					bgfx::setViewRect(RENDER_PASS_GEOMETRY_ID,      0, 0, m_width, m_height);
+					bgfx::setViewRect(RENDER_PASS_LIGHT_ID,         0, 0, m_width, m_height);
+					bgfx::setViewRect(RENDER_PASS_COMBINE_ID,       0, 0, m_width, m_height);
+					bgfx::setViewRect(RENDER_PASS_DEBUG_LIGHTS_ID,  0, 0, m_width, m_height);
+					bgfx::setViewRect(RENDER_PASS_DEBUG_GBUFFER_ID, 0, 0, m_width, m_height);
+
+					bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_ID, m_lightBuffer);
+
+					float proj[16];
+					mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f);
+
+					bgfx::setViewFrameBuffer(RENDER_PASS_GEOMETRY_ID, m_gbuffer);
+					bgfx::setViewTransform(RENDER_PASS_GEOMETRY_ID, view, proj);
+
+					bx::mtxMul(vp, view, proj);
+					bx::mtxInverse(invMvp, vp);
+
+					bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
+					bgfx::setViewTransform(RENDER_PASS_LIGHT_ID,   NULL, proj);
+					bgfx::setViewTransform(RENDER_PASS_COMBINE_ID, NULL, proj);
+
+					const float aspectRatio = float(m_height)/float(m_width);
+					const float size = 10.0f;
+					bx::mtxOrtho(proj, -size, size, size*aspectRatio, -size*aspectRatio, 0.0f, 1000.0f);
+					bgfx::setViewTransform(RENDER_PASS_DEBUG_GBUFFER_ID, NULL, proj);
+
+					bx::mtxOrtho(proj, 0.0f, (float)m_width, 0.0f, (float)m_height, 0.0f, 1000.0f);
+					bgfx::setViewTransform(RENDER_PASS_DEBUG_LIGHTS_ID, NULL, proj);
 				}
 				}
 
 
-				// Cull light if it's fully behind camera.
-				if (maxz >= 0.0f)
-				{
-					float x0 = bx::fclamp( (minx * 0.5f + 0.5f) * width,  0.0f, (float)width);
-					float y0 = bx::fclamp( (miny * 0.5f + 0.5f) * height, 0.0f, (float)height);
-					float x1 = bx::fclamp( (maxx * 0.5f + 0.5f) * width,  0.0f, (float)width);
-					float y1 = bx::fclamp( (maxy * 0.5f + 0.5f) * height, 0.0f, (float)height);
+				const uint32_t dim = 11;
+				const float offset = (float(dim-1) * 3.0f) * 0.5f;
 
 
-					if (showScissorRects)
+				// Draw into geometry pass.
+				for (uint32_t yy = 0; yy < dim; ++yy)
+				{
+					for (uint32_t xx = 0; xx < dim; ++xx)
 					{
 					{
-						bgfx::TransientVertexBuffer tvb;
-						bgfx::TransientIndexBuffer tib;
-						if (bgfx::allocTransientBuffers(&tvb, DebugVertex::ms_decl, 4, &tib, 8) )
+						float mtx[16];
+						if (m_animateMesh)
 						{
 						{
-							uint32_t abgr = 0x8000ff00;
-
-							DebugVertex* vertex = (DebugVertex*)tvb.data;
-							vertex->m_x = x0;
-							vertex->m_y = y0;
-							vertex->m_z = 0.0f;
-							vertex->m_abgr = abgr;
-							++vertex;
-
-							vertex->m_x = x1;
-							vertex->m_y = y0;
-							vertex->m_z = 0.0f;
-							vertex->m_abgr = abgr;
-							++vertex;
-
-							vertex->m_x = x1;
-							vertex->m_y = y1;
-							vertex->m_z = 0.0f;
-							vertex->m_abgr = abgr;
-							++vertex;
-
-							vertex->m_x = x0;
-							vertex->m_y = y1;
-							vertex->m_z = 0.0f;
-							vertex->m_abgr = abgr;
-
-							uint16_t* indices = (uint16_t*)tib.data;
-							*indices++ = 0;
-							*indices++ = 1;
-							*indices++ = 1;
-							*indices++ = 2;
-							*indices++ = 2;
-							*indices++ = 3;
-							*indices++ = 3;
-							*indices++ = 0;
-
-							bgfx::setVertexBuffer(&tvb);
-							bgfx::setIndexBuffer(&tib);
-							bgfx::setState(0
+							bx::mtxRotateXY(mtx, time*1.023f + xx*0.21f, time*0.03f + yy*0.37f);
+						}
+						else
+						{
+							bx::mtxIdentity(mtx);
+						}
+						mtx[12] = -offset + float(xx)*3.0f;
+						mtx[13] = -offset + float(yy)*3.0f;
+						mtx[14] = 0.0f;
+
+						// Set transform for draw call.
+						bgfx::setTransform(mtx);
+
+						// Set vertex and index buffer.
+						bgfx::setVertexBuffer(m_vbh);
+						bgfx::setIndexBuffer(m_ibh);
+
+						// Bind textures.
+						bgfx::setTexture(0, s_texColor,  m_textureColor);
+						bgfx::setTexture(1, s_texNormal, m_textureNormal);
+
+						// Set render states.
+						bgfx::setState(0
 								| BGFX_STATE_RGB_WRITE
 								| BGFX_STATE_RGB_WRITE
-								| BGFX_STATE_PT_LINES
-								| BGFX_STATE_BLEND_ALPHA
+								| BGFX_STATE_ALPHA_WRITE
+								| BGFX_STATE_DEPTH_WRITE
+								| BGFX_STATE_DEPTH_TEST_LESS
+								| BGFX_STATE_MSAA
 								);
 								);
-							bgfx::submit(RENDER_PASS_DEBUG_LIGHTS_ID, lineProgram);
-						}
+
+						// Submit primitive for rendering to view 0.
+						bgfx::submit(RENDER_PASS_GEOMETRY_ID, m_geomProgram);
 					}
 					}
+				}
+
+				// Draw lights into light buffer.
+				for (int32_t light = 0; light < m_numLights; ++light)
+				{
+					Sphere lightPosRadius;
+
+					float lightTime = time * m_lightAnimationSpeed * (sinf(light/float(m_numLights) * bx::piHalf ) * 0.5f + 0.5f);
+					lightPosRadius.m_center[0] = sinf( ( (lightTime + light*0.47f) + bx::piHalf*1.37f ) )*offset;
+					lightPosRadius.m_center[1] = cosf( ( (lightTime + light*0.69f) + bx::piHalf*1.49f ) )*offset;
+					lightPosRadius.m_center[2] = sinf( ( (lightTime + light*0.37f) + bx::piHalf*1.57f ) )*2.0f;
+					lightPosRadius.m_radius = 2.0f;
 
 
-					uint8_t val = light&7;
-					float lightRgbInnerR[4] =
+					Aabb aabb;
+					sphereToAabb(aabb, lightPosRadius);
+
+					float box[8][3] =
 					{
 					{
-						val & 0x1 ? 1.0f : 0.25f,
-						val & 0x2 ? 1.0f : 0.25f,
-						val & 0x4 ? 1.0f : 0.25f,
-						0.8f,
+						{ aabb.m_min[0], aabb.m_min[1], aabb.m_min[2] },
+						{ aabb.m_min[0], aabb.m_min[1], aabb.m_max[2] },
+						{ aabb.m_min[0], aabb.m_max[1], aabb.m_min[2] },
+						{ aabb.m_min[0], aabb.m_max[1], aabb.m_max[2] },
+						{ aabb.m_max[0], aabb.m_min[1], aabb.m_min[2] },
+						{ aabb.m_max[0], aabb.m_min[1], aabb.m_max[2] },
+						{ aabb.m_max[0], aabb.m_max[1], aabb.m_min[2] },
+						{ aabb.m_max[0], aabb.m_max[1], aabb.m_max[2] },
 					};
 					};
 
 
-					// Draw light.
-					bgfx::setUniform(u_lightPosRadius, &lightPosRadius);
-					bgfx::setUniform(u_lightRgbInnerR, lightRgbInnerR);
-					bgfx::setUniform(u_mtx, invMvp);
-					const uint16_t scissorHeight = uint16_t(y1-y0);
-					bgfx::setScissor(uint16_t(x0), height-scissorHeight-uint16_t(y0), uint16_t(x1-x0), scissorHeight);
-					bgfx::setTexture(0, s_normal, gbuffer, 1);
-					bgfx::setTexture(1, s_depth,  gbuffer, 2);
-					bgfx::setState(0
-						| BGFX_STATE_RGB_WRITE
-						| BGFX_STATE_ALPHA_WRITE
-						| BGFX_STATE_BLEND_ADD
-						);
-					screenSpaceQuad( (float)width, (float)height, texelHalf, s_originBottomLeft);
-					bgfx::submit(RENDER_PASS_LIGHT_ID, lightProgram);
-				}
-			}
+					float xyz[3];
+					bx::vec3MulMtxH(xyz, box[0], vp);
+					float minx = xyz[0];
+					float miny = xyz[1];
+					float maxx = xyz[0];
+					float maxy = xyz[1];
+					float maxz = xyz[2];
 
 
-			// Combine color and light buffers.
-			bgfx::setTexture(0, s_albedo, gbuffer,     0);
-			bgfx::setTexture(1, s_light,  lightBuffer, 0);
-			bgfx::setState(0
-				| BGFX_STATE_RGB_WRITE
-				| BGFX_STATE_ALPHA_WRITE
-				);
-			screenSpaceQuad( (float)width, (float)height, texelHalf, s_originBottomLeft);
-			bgfx::submit(RENDER_PASS_COMBINE_ID, combineProgram);
+					for (uint32_t ii = 1; ii < 8; ++ii)
+					{
+						bx::vec3MulMtxH(xyz, box[ii], vp);
+						minx = bx::fmin(minx, xyz[0]);
+						miny = bx::fmin(miny, xyz[1]);
+						maxx = bx::fmax(maxx, xyz[0]);
+						maxy = bx::fmax(maxy, xyz[1]);
+						maxz = bx::fmax(maxz, xyz[2]);
+					}
 
 
-			if (showGBuffer)
-			{
-				const float aspectRatio = float(width)/float(height);
+					// Cull light if it's fully behind camera.
+					if (maxz >= 0.0f)
+					{
+						float x0 = bx::fclamp( (minx * 0.5f + 0.5f) * m_width,  0.0f, (float)m_width);
+						float y0 = bx::fclamp( (miny * 0.5f + 0.5f) * m_height, 0.0f, (float)m_height);
+						float x1 = bx::fclamp( (maxx * 0.5f + 0.5f) * m_width,  0.0f, (float)m_width);
+						float y1 = bx::fclamp( (maxy * 0.5f + 0.5f) * m_height, 0.0f, (float)m_height);
 
 
-				// Draw debug GBuffer.
-				for (uint32_t ii = 0; ii < BX_COUNTOF(gbufferTex); ++ii)
-				{
-					float mtx[16];
-					bx::mtxSRT(mtx
-						, aspectRatio, 1.0f, 1.0f
-						, 0.0f, 0.0f, 0.0f
-						, -7.9f - BX_COUNTOF(gbufferTex)*0.1f*0.5f + ii*2.1f*aspectRatio, 4.0f, 0.0f
-						);
+						if (m_showScissorRects)
+						{
+							bgfx::TransientVertexBuffer tvb;
+							bgfx::TransientIndexBuffer tib;
+							if (bgfx::allocTransientBuffers(&tvb, DebugVertex::ms_decl, 4, &tib, 8) )
+							{
+								uint32_t abgr = 0x8000ff00;
+
+								DebugVertex* vertex = (DebugVertex*)tvb.data;
+								vertex->m_x = x0;
+								vertex->m_y = y0;
+								vertex->m_z = 0.0f;
+								vertex->m_abgr = abgr;
+								++vertex;
+
+								vertex->m_x = x1;
+								vertex->m_y = y0;
+								vertex->m_z = 0.0f;
+								vertex->m_abgr = abgr;
+								++vertex;
+
+								vertex->m_x = x1;
+								vertex->m_y = y1;
+								vertex->m_z = 0.0f;
+								vertex->m_abgr = abgr;
+								++vertex;
+
+								vertex->m_x = x0;
+								vertex->m_y = y1;
+								vertex->m_z = 0.0f;
+								vertex->m_abgr = abgr;
+
+								uint16_t* indices = (uint16_t*)tib.data;
+								*indices++ = 0;
+								*indices++ = 1;
+								*indices++ = 1;
+								*indices++ = 2;
+								*indices++ = 2;
+								*indices++ = 3;
+								*indices++ = 3;
+								*indices++ = 0;
+
+								bgfx::setVertexBuffer(&tvb);
+								bgfx::setIndexBuffer(&tib);
+								bgfx::setState(0
+										| BGFX_STATE_RGB_WRITE
+										| BGFX_STATE_PT_LINES
+										| BGFX_STATE_BLEND_ALPHA
+										);
+								bgfx::submit(RENDER_PASS_DEBUG_LIGHTS_ID, m_lineProgram);
+							}
+						}
 
 
-					bgfx::setTransform(mtx);
-					bgfx::setVertexBuffer(vbh);
-					bgfx::setIndexBuffer(ibh, 0, 6);
-					bgfx::setTexture(0, s_texColor, gbufferTex[ii]);
-					bgfx::setState(BGFX_STATE_RGB_WRITE);
-					bgfx::submit(RENDER_PASS_DEBUG_GBUFFER_ID, debugProgram);
+						uint8_t val = light&7;
+						float lightRgbInnerR[4] =
+						{
+							val & 0x1 ? 1.0f : 0.25f,
+							val & 0x2 ? 1.0f : 0.25f,
+							val & 0x4 ? 1.0f : 0.25f,
+							0.8f,
+						};
+
+						// Draw light.
+						bgfx::setUniform(u_lightPosRadius, &lightPosRadius);
+						bgfx::setUniform(u_lightRgbInnerR, lightRgbInnerR);
+						bgfx::setUniform(u_mtx, invMvp);
+						const uint16_t scissorHeight = uint16_t(y1-y0);
+						bgfx::setScissor(uint16_t(x0), m_height-scissorHeight-uint16_t(y0), uint16_t(x1-x0), scissorHeight);
+						bgfx::setTexture(0, s_normal, m_gbuffer, 1);
+						bgfx::setTexture(1, s_depth,  m_gbuffer, 2);
+						bgfx::setState(0
+								| BGFX_STATE_RGB_WRITE
+								| BGFX_STATE_ALPHA_WRITE
+								| BGFX_STATE_BLEND_ADD
+								);
+						screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, s_originBottomLeft);
+						bgfx::submit(RENDER_PASS_LIGHT_ID, m_lightProgram);
+					}
 				}
 				}
-			}
-		}
 
 
-		// Advance to next frame. Rendering thread will be kicked to
-		// process submitted rendering primitives.
-		bgfx::frame();
-	}
-
-	// Cleanup.
-	cameraDestroy();
-	imguiDestroy();
+				// Combine color and light buffers.
+				bgfx::setTexture(0, s_albedo, m_gbuffer,     0);
+				bgfx::setTexture(1, s_light,  m_lightBuffer, 0);
+				bgfx::setState(0
+						| BGFX_STATE_RGB_WRITE
+						| BGFX_STATE_ALPHA_WRITE
+						);
+				screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, s_originBottomLeft);
+				bgfx::submit(RENDER_PASS_COMBINE_ID, m_combineProgram);
 
 
-	if (bgfx::isValid(gbuffer) )
-	{
-		bgfx::destroyFrameBuffer(gbuffer);
-		bgfx::destroyFrameBuffer(lightBuffer);
-	}
+				if (m_showGBuffer)
+				{
+					const float aspectRatio = float(m_width)/float(m_height);
 
 
-	bgfx::destroyIndexBuffer(ibh);
-	bgfx::destroyVertexBuffer(vbh);
+					// Draw m_debug m_gbuffer.
+					for (uint32_t ii = 0; ii < BX_COUNTOF(m_gbufferTex); ++ii)
+					{
+						float mtx[16];
+						bx::mtxSRT(mtx
+								, aspectRatio, 1.0f, 1.0f
+								, 0.0f, 0.0f, 0.0f
+								, -7.9f - BX_COUNTOF(m_gbufferTex)*0.1f*0.5f + ii*2.1f*aspectRatio, 4.0f, 0.0f
+								);
 
 
-	bgfx::destroyProgram(geomProgram);
-	bgfx::destroyProgram(lightProgram);
-	bgfx::destroyProgram(combineProgram);
-	bgfx::destroyProgram(debugProgram);
-	bgfx::destroyProgram(lineProgram);
+						bgfx::setTransform(mtx);
+						bgfx::setVertexBuffer(m_vbh);
+						bgfx::setIndexBuffer(m_ibh, 0, 6);
+						bgfx::setTexture(0, s_texColor, m_gbufferTex[ii]);
+						bgfx::setState(BGFX_STATE_RGB_WRITE);
+						bgfx::submit(RENDER_PASS_DEBUG_GBUFFER_ID, m_debugProgram);
+					}
+				}
+			}
 
 
-	bgfx::destroyTexture(textureColor);
-	bgfx::destroyTexture(textureNormal);
-	bgfx::destroyUniform(s_texColor);
-	bgfx::destroyUniform(s_texNormal);
+			// Advance to next frame. Rendering thread will be kicked to
+			// process submitted rendering primitives.
+			bgfx::frame();
 
 
-	bgfx::destroyUniform(s_albedo);
-	bgfx::destroyUniform(s_normal);
-	bgfx::destroyUniform(s_depth);
-	bgfx::destroyUniform(s_light);
+			return true;
+		}
 
 
-	bgfx::destroyUniform(u_lightPosRadius);
-	bgfx::destroyUniform(u_lightRgbInnerR);
-	bgfx::destroyUniform(u_mtx);
+		return false;
+	}
 
 
-	// Shutdown bgfx.
-	bgfx::shutdown();
+	bgfx::VertexBufferHandle m_vbh;
+	bgfx::IndexBufferHandle m_ibh;
+	bgfx::UniformHandle s_texColor;
+	bgfx::UniformHandle s_texNormal;
+
+	bgfx::UniformHandle s_albedo;
+	bgfx::UniformHandle s_normal;
+	bgfx::UniformHandle s_depth;
+	bgfx::UniformHandle s_light;
+
+	bgfx::UniformHandle u_mtx;
+	bgfx::UniformHandle u_lightPosRadius;
+	bgfx::UniformHandle u_lightRgbInnerR;
+
+	bgfx::ProgramHandle m_geomProgram;
+	bgfx::ProgramHandle m_lightProgram;
+	bgfx::ProgramHandle m_combineProgram;
+	bgfx::ProgramHandle m_debugProgram;
+	bgfx::ProgramHandle m_lineProgram;
+	bgfx::TextureHandle m_textureColor;
+	bgfx::TextureHandle m_textureNormal;
+
+	bgfx::TextureHandle m_gbufferTex[3];
+	bgfx::FrameBufferHandle m_gbuffer;
+	bgfx::FrameBufferHandle m_lightBuffer;
+
+	uint32_t m_width;
+	uint32_t m_height;
+	uint32_t m_debug;
+	uint32_t m_reset;
+
+	uint32_t m_oldWidth;
+	uint32_t m_oldHeight;
+	uint32_t m_oldReset;
+
+	int32_t m_scrollArea;
+	int32_t m_numLights;
+	float m_lightAnimationSpeed;
+	bool m_animateMesh;
+	bool m_showScissorRects;
+	bool m_showGBuffer;
+
+	entry::MouseState m_mouseState;
+
+	const bgfx::Caps* m_caps;
+	int64_t m_timeOffset;
+};
 
 
-	return 0;
-}
+ENTRY_IMPLEMENT_MAIN(Deferred);

+ 4 - 4
examples/common/camera.cpp

@@ -53,7 +53,7 @@ static void cmd(const void* _userData)
 	cmdExec( (const char*)_userData);
 	cmdExec( (const char*)_userData);
 }
 }
 
 
-static const InputBinding s_camBindings[] = 
+static const InputBinding s_camBindings[] =
 {
 {
 	{ entry::Key::KeyW,             entry::Modifier::None, 0, cmd, "move forward"  },
 	{ entry::Key::KeyW,             entry::Modifier::None, 0, cmd, "move forward"  },
 	{ entry::Key::GamepadUp,        entry::Modifier::None, 0, cmd, "move forward"  },
 	{ entry::Key::GamepadUp,        entry::Modifier::None, 0, cmd, "move forward"  },
@@ -258,7 +258,7 @@ struct Camera
 		bx::mtxLookAt(_viewMtx, m_eye, m_at, m_up);
 		bx::mtxLookAt(_viewMtx, m_eye, m_at, m_up);
 	}
 	}
 
 
-	void setPosition(float* _pos)
+	void setPosition(const float* _pos)
 	{
 	{
 		memcpy(m_eye, _pos, sizeof(float)*3);
 		memcpy(m_eye, _pos, sizeof(float)*3);
 	}
 	}
@@ -267,7 +267,7 @@ struct Camera
 	{
 	{
 		m_verticalAngle = _verticalAngle;
 		m_verticalAngle = _verticalAngle;
 	}
 	}
-	
+
 	void setHorizontalAngle(float _horizontalAngle)
 	void setHorizontalAngle(float _horizontalAngle)
 	{
 	{
 		m_horizontalAngle = _horizontalAngle;
 		m_horizontalAngle = _horizontalAngle;
@@ -303,7 +303,7 @@ void cameraDestroy()
 	s_camera = NULL;
 	s_camera = NULL;
 }
 }
 
 
-void cameraSetPosition(float* _pos)
+void cameraSetPosition(const float* _pos)
 {
 {
 	s_camera->setPosition(_pos);
 	s_camera->setPosition(_pos);
 }
 }

+ 1 - 1
examples/common/camera.h

@@ -22,7 +22,7 @@ void cameraCreate();
 void cameraDestroy();
 void cameraDestroy();
 
 
 ///
 ///
-void cameraSetPosition(float* _pos);
+void cameraSetPosition(const float* _pos);
 
 
 ///
 ///
 void cameraSetHorizontalAngle(float _horizontalAngle);
 void cameraSetHorizontalAngle(float _horizontalAngle);