Browse Source

Added 21-deferred example.

Branimir Karadžić 11 years ago
parent
commit
8cede52d91
58 changed files with 1061 additions and 0 deletions
  1. 6 0
      README.md
  2. 739 0
      examples/21-deferred/deferred.cpp
  3. 18 0
      examples/21-deferred/fs_deferred_combine.sc
  4. 15 0
      examples/21-deferred/fs_deferred_debug.sc
  5. 13 0
      examples/21-deferred/fs_deferred_debug_line.sc
  6. 31 0
      examples/21-deferred/fs_deferred_geom.sc
  7. 91 0
      examples/21-deferred/fs_deferred_light.sc
  8. 17 0
      examples/21-deferred/makefile
  9. BIN
      examples/21-deferred/screenshot.png
  10. 17 0
      examples/21-deferred/varying.def.sc
  11. 15 0
      examples/21-deferred/vs_deferred_combine.sc
  12. 15 0
      examples/21-deferred/vs_deferred_debug.sc
  13. 15 0
      examples/21-deferred/vs_deferred_debug_line.sc
  14. 37 0
      examples/21-deferred/vs_deferred_geom.sc
  15. 15 0
      examples/21-deferred/vs_deferred_light.sc
  16. 10 0
      examples/common/shaderlib.sh
  17. BIN
      examples/runtime/shaders/dx11/fs_deferred_combine.bin
  18. BIN
      examples/runtime/shaders/dx11/fs_deferred_debug.bin
  19. BIN
      examples/runtime/shaders/dx11/fs_deferred_debug_line.bin
  20. BIN
      examples/runtime/shaders/dx11/fs_deferred_geom.bin
  21. BIN
      examples/runtime/shaders/dx11/fs_deferred_light.bin
  22. BIN
      examples/runtime/shaders/dx11/vs_deferred_combine.bin
  23. BIN
      examples/runtime/shaders/dx11/vs_deferred_debug.bin
  24. BIN
      examples/runtime/shaders/dx11/vs_deferred_debug_line.bin
  25. BIN
      examples/runtime/shaders/dx11/vs_deferred_geom.bin
  26. BIN
      examples/runtime/shaders/dx11/vs_deferred_light.bin
  27. BIN
      examples/runtime/shaders/dx9/fs_deferred_combine.bin
  28. BIN
      examples/runtime/shaders/dx9/fs_deferred_debug.bin
  29. BIN
      examples/runtime/shaders/dx9/fs_deferred_debug_line.bin
  30. BIN
      examples/runtime/shaders/dx9/fs_deferred_geom.bin
  31. BIN
      examples/runtime/shaders/dx9/fs_deferred_light.bin
  32. BIN
      examples/runtime/shaders/dx9/vs_deferred_combine.bin
  33. BIN
      examples/runtime/shaders/dx9/vs_deferred_debug.bin
  34. BIN
      examples/runtime/shaders/dx9/vs_deferred_debug_line.bin
  35. BIN
      examples/runtime/shaders/dx9/vs_deferred_geom.bin
  36. BIN
      examples/runtime/shaders/dx9/vs_deferred_light.bin
  37. BIN
      examples/runtime/shaders/gles/fs_deferred_combine.bin
  38. BIN
      examples/runtime/shaders/gles/fs_deferred_debug.bin
  39. BIN
      examples/runtime/shaders/gles/fs_deferred_debug_line.bin
  40. BIN
      examples/runtime/shaders/gles/fs_deferred_geom.bin
  41. BIN
      examples/runtime/shaders/gles/fs_deferred_light.bin
  42. BIN
      examples/runtime/shaders/gles/vs_deferred_combine.bin
  43. BIN
      examples/runtime/shaders/gles/vs_deferred_debug.bin
  44. BIN
      examples/runtime/shaders/gles/vs_deferred_debug_line.bin
  45. BIN
      examples/runtime/shaders/gles/vs_deferred_geom.bin
  46. BIN
      examples/runtime/shaders/gles/vs_deferred_light.bin
  47. BIN
      examples/runtime/shaders/glsl/fs_deferred_combine.bin
  48. BIN
      examples/runtime/shaders/glsl/fs_deferred_debug.bin
  49. BIN
      examples/runtime/shaders/glsl/fs_deferred_debug_line.bin
  50. BIN
      examples/runtime/shaders/glsl/fs_deferred_geom.bin
  51. BIN
      examples/runtime/shaders/glsl/fs_deferred_light.bin
  52. BIN
      examples/runtime/shaders/glsl/vs_deferred_combine.bin
  53. BIN
      examples/runtime/shaders/glsl/vs_deferred_debug.bin
  54. BIN
      examples/runtime/shaders/glsl/vs_deferred_debug_line.bin
  55. BIN
      examples/runtime/shaders/glsl/vs_deferred_geom.bin
  56. BIN
      examples/runtime/shaders/glsl/vs_deferred_light.bin
  57. 1 0
      premake/premake4.lua
  58. 6 0
      src/renderer_d3d9.cpp

+ 6 - 0
README.md

@@ -230,6 +230,12 @@ NanoVG is small antialiased vector graphics rendering library.
 
 
 ![example-20-nanovg](https://github.com/bkaradzic/bgfx/raw/master/examples/20-nanovg/screenshot.png)
 ![example-20-nanovg](https://github.com/bkaradzic/bgfx/raw/master/examples/20-nanovg/screenshot.png)
 
 
+### [21-deferred](https://github.com/bkaradzic/bgfx/tree/master/examples/21-deferred)
+
+MRT rendering and deferred shading.
+
+![example-21-deferred](https://github.com/bkaradzic/bgfx/raw/master/examples/21-deferred/screenshot.png)
+
 Dependencies
 Dependencies
 ------------
 ------------
 
 

+ 739 - 0
examples/21-deferred/deferred.cpp

@@ -0,0 +1,739 @@
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "common.h"
+#include "bgfx_utils.h"
+#include "imgui/imgui.h"
+#include "camera.h"
+#include "bounds.h"
+
+#define RENDER_PASS_GEOMETRY_ID       0
+#define RENDER_PASS_GEOMETRY_BIT      (1<<RENDER_PASS_GEOMETRY_ID)
+
+#define RENDER_PASS_LIGHT_ID          1
+#define RENDER_PASS_LIGHT_BIT         (1<<RENDER_PASS_LIGHT_ID)
+
+#define RENDER_PASS_COMBINE_ID        2
+#define RENDER_PASS_COMBINE_BIT       (1<<RENDER_PASS_COMBINE_ID)
+
+#define RENDER_PASS_DEBUG_LIGHTS_ID   3
+#define RENDER_PASS_DEBUG_LIGHTS_BIT  (1<<RENDER_PASS_DEBUG_LIGHTS_ID)
+
+#define RENDER_PASS_DEBUG_GBUFFER_ID  4
+#define RENDER_PASS_DEBUG_GBUFFER_BIT (1<<RENDER_PASS_DEBUG_GBUFFER_ID)
+
+struct PosNormalTangentTexcoordVertex
+{
+	float m_x;
+	float m_y;
+	float m_z;
+	uint32_t m_normal;
+	uint32_t m_tangent;
+	int16_t m_u;
+	int16_t m_v;
+
+	static void init()
+	{
+		ms_decl
+			.begin()
+			.add(bgfx::Attrib::Position,  3, bgfx::AttribType::Float)
+			.add(bgfx::Attrib::Normal,    4, bgfx::AttribType::Uint8, true, true)
+			.add(bgfx::Attrib::Tangent,   4, bgfx::AttribType::Uint8, true, true)
+			.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Int16, true, true)
+			.end();
+	}
+
+	static bgfx::VertexDecl ms_decl;
+};
+
+bgfx::VertexDecl PosNormalTangentTexcoordVertex::ms_decl;
+
+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;
+};
+
+bgfx::VertexDecl PosTexCoord0Vertex::ms_decl;
+
+struct DebugVertex
+{
+	float m_x;
+	float m_y;
+	float m_z;
+	uint32_t m_abgr;
+
+	static void init()
+	{
+		ms_decl
+			.begin()
+			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
+			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
+			.end();
+	}
+
+	static bgfx::VertexDecl ms_decl;
+};
+
+bgfx::VertexDecl DebugVertex::ms_decl;
+
+uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w)
+{
+	union
+	{
+		uint32_t ui32;
+		uint8_t arr[4];
+	} un;
+
+	un.arr[0] = _x;
+	un.arr[1] = _y;
+	un.arr[2] = _z;
+	un.arr[3] = _w;
+
+	return un.ui32;
+}
+
+uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
+{
+	const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
+	const uint8_t yy = uint8_t(_y*127.0f + 128.0f);
+	const uint8_t zz = uint8_t(_z*127.0f + 128.0f);
+	const uint8_t ww = uint8_t(_w*127.0f + 128.0f);
+	return packUint32(xx, yy, zz, ww);
+}
+
+static PosNormalTangentTexcoordVertex s_cubeVertices[24] =
+{
+	{-1.0f,  1.0f,  1.0f, packF4u( 0.0f,  0.0f,  1.0f), 0,      0,      0 },
+	{ 1.0f,  1.0f,  1.0f, packF4u( 0.0f,  0.0f,  1.0f), 0, 0x7fff,      0 },
+	{-1.0f, -1.0f,  1.0f, packF4u( 0.0f,  0.0f,  1.0f), 0,      0, 0x7fff },
+	{ 1.0f, -1.0f,  1.0f, packF4u( 0.0f,  0.0f,  1.0f), 0, 0x7fff, 0x7fff },
+	{-1.0f,  1.0f, -1.0f, packF4u( 0.0f,  0.0f, -1.0f), 0,      0,      0 },
+	{ 1.0f,  1.0f, -1.0f, packF4u( 0.0f,  0.0f, -1.0f), 0, 0x7fff,      0 },
+	{-1.0f, -1.0f, -1.0f, packF4u( 0.0f,  0.0f, -1.0f), 0,      0, 0x7fff },
+	{ 1.0f, -1.0f, -1.0f, packF4u( 0.0f,  0.0f, -1.0f), 0, 0x7fff, 0x7fff },
+	{-1.0f,  1.0f,  1.0f, packF4u( 0.0f,  1.0f,  0.0f), 0,      0,      0 },
+	{ 1.0f,  1.0f,  1.0f, packF4u( 0.0f,  1.0f,  0.0f), 0, 0x7fff,      0 },
+	{-1.0f,  1.0f, -1.0f, packF4u( 0.0f,  1.0f,  0.0f), 0,      0, 0x7fff },
+	{ 1.0f,  1.0f, -1.0f, packF4u( 0.0f,  1.0f,  0.0f), 0, 0x7fff, 0x7fff },
+	{-1.0f, -1.0f,  1.0f, packF4u( 0.0f, -1.0f,  0.0f), 0,      0,      0 },
+	{ 1.0f, -1.0f,  1.0f, packF4u( 0.0f, -1.0f,  0.0f), 0, 0x7fff,      0 },
+	{-1.0f, -1.0f, -1.0f, packF4u( 0.0f, -1.0f,  0.0f), 0,      0, 0x7fff },
+	{ 1.0f, -1.0f, -1.0f, packF4u( 0.0f, -1.0f,  0.0f), 0, 0x7fff, 0x7fff },
+	{ 1.0f, -1.0f,  1.0f, packF4u( 1.0f,  0.0f,  0.0f), 0,      0,      0 },
+	{ 1.0f,  1.0f,  1.0f, packF4u( 1.0f,  0.0f,  0.0f), 0, 0x7fff,      0 },
+	{ 1.0f, -1.0f, -1.0f, packF4u( 1.0f,  0.0f,  0.0f), 0,      0, 0x7fff },
+	{ 1.0f,  1.0f, -1.0f, packF4u( 1.0f,  0.0f,  0.0f), 0, 0x7fff, 0x7fff },
+	{-1.0f, -1.0f,  1.0f, packF4u(-1.0f,  0.0f,  0.0f), 0,      0,      0 },
+	{-1.0f,  1.0f,  1.0f, packF4u(-1.0f,  0.0f,  0.0f), 0, 0x7fff,      0 },
+	{-1.0f, -1.0f, -1.0f, packF4u(-1.0f,  0.0f,  0.0f), 0,      0, 0x7fff },
+	{-1.0f,  1.0f, -1.0f, packF4u(-1.0f,  0.0f,  0.0f), 0, 0x7fff, 0x7fff },
+};
+
+static const uint16_t s_cubeIndices[36] =
+{
+	 0,  2,  1,
+	 1,  2,  3,
+	 4,  5,  6,
+	 5,  7,  6,
+
+	 8, 10,  9,
+	 9, 10, 11,
+    12, 13, 14,
+	13, 15, 14,
+
+	16, 18, 17,
+	17, 18, 19,
+	20, 21, 22,
+	21, 23, 22,
+};
+
+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);
+	}
+}
+
+int _main_(int /*_argc*/, char** /*_argv*/)
+{
+	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 view 0 clear state.
+	bgfx::setViewClear(RENDER_PASS_GEOMETRY_ID
+		, BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT
+		, 0x303030ff
+		, 1.0f
+		, 0
+		);
+
+	bgfx::setViewClear(RENDER_PASS_LIGHT_ID
+		, BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT
+		, 0
+		, 1.0f
+		, 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::Uniform1iv);
+	bgfx::UniformHandle s_texNormal = bgfx::createUniform("s_texNormal", bgfx::UniformType::Uniform1iv);
+
+	bgfx::UniformHandle s_albedo = bgfx::createUniform("s_albedo", bgfx::UniformType::Uniform1iv);
+	bgfx::UniformHandle s_normal = bgfx::createUniform("s_normal", bgfx::UniformType::Uniform1iv);
+	bgfx::UniformHandle s_depth  = bgfx::createUniform("s_depth",  bgfx::UniformType::Uniform1iv);
+	bgfx::UniformHandle s_light  = bgfx::createUniform("s_light",  bgfx::UniformType::Uniform1iv);
+
+	bgfx::UniformHandle u_mtx    = bgfx::createUniform("u_mtx",    bgfx::UniformType::Uniform4x4fv);
+
+	bgfx::UniformHandle u_lightPosRadius = bgfx::createUniform("u_lightPosRadius", bgfx::UniformType::Uniform4fv);
+	bgfx::UniformHandle u_lightRgbInnerR = bgfx::createUniform("u_lightRgbInnerR", bgfx::UniformType::Uniform4fv);
+
+	// 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; 
+
+	void* data = load("font/droidsans.ttf");
+	imguiCreate(data);
+	free(data);
+
+	const int64_t timeOffset = bx::getHPCounter();
+	const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
+	const float texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
+	const bool  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) )
+	{
+		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. ");
+
+			// Set view 0 default viewport.
+			bgfx::setViewRect(0, 0, 0, width, 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::submit(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;
+
+				if (bgfx::isValid(gbuffer) )
+				{
+					bgfx::destroyFrameBuffer(gbuffer);
+				}
+
+				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);
+				}
+
+				lightBuffer = bgfx::createFrameBuffer(width, height, bgfx::TextureFormat::BGRA8, samplerFlags);
+			}
+
+			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)
+				, 0
+				, width
+				, height
+				);
+
+			imguiBeginScrollArea("Settings", width - width / 5 - 10, 10, width / 5, height / 3, &scrollArea);
+			imguiSeparatorLine();
+
+			imguiSlider("Num lights", &numLights, 1, 2048);
+
+			if (imguiCheck("Show G-Buffer.", showGBuffer) )
+			{
+				showGBuffer = !showGBuffer;
+			}
+
+			if (imguiCheck("Show light scissor.", showScissorRects) )
+			{
+				showScissorRects = !showScissorRects;
+			}
+
+			if (imguiCheck("Animate mesh.", animateMesh) )
+			{
+				animateMesh = !animateMesh;
+			}
+
+			imguiSlider("Lights animation speed", &lightAnimationSpeed, 0.0f, 0.4f, 0.01f);
+			
+			imguiEndScrollArea();
+			imguiEndFrame();
+
+			// Update camera.
+			cameraUpdate(deltaTime, mouseState.m_mx, mouseState.m_my, !!mouseState.m_buttons[entry::MouseButton::Right]);
+			cameraGetViewMtx(view);
+
+			// Setup views
+			float vp[16];
+			float invMvp[16];
+			{
+				bgfx::setViewRectMask(0
+					| RENDER_PASS_GEOMETRY_BIT
+					| RENDER_PASS_LIGHT_BIT
+					| RENDER_PASS_COMBINE_BIT
+					| RENDER_PASS_DEBUG_LIGHTS_BIT
+					| RENDER_PASS_DEBUG_GBUFFER_BIT
+					, 0, 0, width, height
+					);
+
+				bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_ID, lightBuffer);
+
+				float proj[16];
+				mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
+
+				bgfx::setViewFrameBuffer(RENDER_PASS_GEOMETRY_ID, gbuffer);
+				bgfx::setViewTransform(RENDER_PASS_GEOMETRY_ID, view, proj);
+
+				mtxMul(vp, view, proj);
+				mtxInverse(invMvp, vp);
+
+				mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
+				bgfx::setViewTransformMask(0
+					| RENDER_PASS_LIGHT_BIT
+					| RENDER_PASS_COMBINE_BIT
+					, NULL, proj
+					);
+
+				const float aspectRatio = float(height)/float(width);
+				const float size = 10.0f;
+				mtxOrtho(proj, -size, size, size*aspectRatio, -size*aspectRatio, 0.0f, 1000.0f);
+				bgfx::setViewTransform(RENDER_PASS_DEBUG_GBUFFER_ID, NULL, proj); 
+
+				mtxOrtho(proj, 0.0f, (float)width, 0.0f, (float)height, 0.0f, 1000.0f);
+				bgfx::setViewTransform(RENDER_PASS_DEBUG_LIGHTS_ID, NULL, proj); 
+			}
+
+			const uint32_t dim = 11;
+			const float offset = (float(dim-1) * 3.0f) * 0.5f;
+
+			// Draw into geometry pass.
+			for (uint32_t yy = 0; yy < dim; ++yy)
+			{
+				for (uint32_t xx = 0; xx < dim; ++xx)
+				{
+					float mtx[16];
+					if (animateMesh)
+					{
+						mtxRotateXY(mtx, time*1.023f + xx*0.21f, time*0.03f + yy*0.37f);
+					}
+					else
+					{
+						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 fragment shaders.
+					bgfx::setProgram(geomProgram);
+
+					// Set vertex and index buffer.
+					bgfx::setVertexBuffer(vbh);
+					bgfx::setIndexBuffer(ibh);
+
+					// Bind textures.
+					bgfx::setTexture(0, s_texColor,  textureColor);
+					bgfx::setTexture(1, s_texNormal, textureNormal);
+
+					// 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
+						);
+
+					// Submit primitive for rendering to view 0.
+					bgfx::submit(RENDER_PASS_GEOMETRY_ID);
+				}
+			}
+
+			// Draw lights into light buffer.
+			for (int32_t light = 0; light < numLights; ++light)
+			{
+				Sphere lightPosRadius;
+
+				float lightTime = time * lightAnimationSpeed * (sin(light/float(numLights) * float(M_PI_2) ) * 0.5f + 0.5f);
+				lightPosRadius.m_center[0] = sin( ( (lightTime + light*0.47f) + float(M_PI_2)*1.37f ) )*offset;
+				lightPosRadius.m_center[1] = cos( ( (lightTime + light*0.69f) + float(M_PI_2)*1.49f ) )*offset;
+				lightPosRadius.m_center[2] = sin( ( (lightTime + light*0.37f) + float(M_PI_2)*1.57f ) )*2.0f;
+				lightPosRadius.m_radius = 2.0f;
+
+				Aabb aabb;
+				sphereToAabb(aabb, lightPosRadius);
+
+				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];
+				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)
+				{
+					vec3MulMtxH(xyz, box[ii], vp);
+					minx = fminf(minx, xyz[0]);
+					miny = fminf(miny, xyz[1]);
+					maxx = fmaxf(maxx, xyz[0]);
+					maxy = fmaxf(maxy, xyz[1]);
+					maxz = fmaxf(maxz, xyz[2]);
+				}
+
+				// Cull light if it's fully behind camera.
+				if (maxz >= 0.0f)
+				{
+					float x0 = fclamp( (minx * 0.5f + 0.5f) * width,  0.0f, (float)width);
+					float y0 = fclamp( (miny * 0.5f + 0.5f) * height, 0.0f, (float)height);
+					float x1 = fclamp( (maxx * 0.5f + 0.5f) * width,  0.0f, (float)width);
+					float y1 = fclamp( (maxy * 0.5f + 0.5f) * height, 0.0f, (float)height);
+
+					if (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::setProgram(lineProgram);
+							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);
+						}
+					}
+
+					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), 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::setProgram(lightProgram);
+					bgfx::setState(0
+						| BGFX_STATE_RGB_WRITE
+						| BGFX_STATE_ALPHA_WRITE
+						| BGFX_STATE_BLEND_ADD
+						);
+					screenSpaceQuad( (float)width, (float)height, texelHalf, originBottomLeft);
+					bgfx::submit(RENDER_PASS_LIGHT_ID);
+				}
+			}
+
+			// Combine color and light buffers.
+			bgfx::setTexture(0, s_albedo, gbuffer,     0);
+			bgfx::setTexture(1, s_light,  lightBuffer, 0);
+			bgfx::setProgram(combineProgram);
+			bgfx::setState(0
+				| BGFX_STATE_RGB_WRITE
+				| BGFX_STATE_ALPHA_WRITE
+				);
+			screenSpaceQuad( (float)width, (float)height, texelHalf, originBottomLeft);
+			bgfx::submit(RENDER_PASS_COMBINE_ID);
+
+			if (showGBuffer)
+			{
+				const float aspectRatio = float(width)/float(height);
+
+				// Draw debug GBuffer.
+				for (uint32_t ii = 0; ii < BX_COUNTOF(gbufferTex); ++ii)
+				{
+					float mtx[16];
+					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
+						);
+
+					bgfx::setTransform(mtx);
+					bgfx::setProgram(debugProgram);
+					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);
+				}
+			}
+		}
+
+		// Advance to next frame. Rendering thread will be kicked to 
+		// process submitted rendering primitives.
+		bgfx::frame();
+	}
+
+	// Cleanup.
+	cameraDestroy();
+	imguiDestroy();
+
+	bgfx::destroyFrameBuffer(gbuffer);
+	bgfx::destroyFrameBuffer(lightBuffer);
+
+	bgfx::destroyIndexBuffer(ibh);
+	bgfx::destroyVertexBuffer(vbh);
+
+	bgfx::destroyProgram(geomProgram);
+	bgfx::destroyProgram(lightProgram);
+	bgfx::destroyProgram(combineProgram);
+	bgfx::destroyProgram(debugProgram);
+	bgfx::destroyProgram(lineProgram);
+
+	bgfx::destroyTexture(textureColor);
+	bgfx::destroyTexture(textureNormal);
+	bgfx::destroyUniform(s_texColor);
+	bgfx::destroyUniform(s_texNormal);
+
+	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;
+}

+ 18 - 0
examples/21-deferred/fs_deferred_combine.sc

@@ -0,0 +1,18 @@
+$input v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+SAMPLER2D(s_albedo, 0);
+SAMPLER2D(s_light,  1);
+
+void main()
+{
+	vec4 albedo  = toLinear(texture2D(s_albedo, v_texcoord0) );
+	vec4 light   = toLinear(texture2D(s_light,  v_texcoord0) );
+	gl_FragColor = toGamma(albedo*light);
+}

+ 15 - 0
examples/21-deferred/fs_deferred_debug.sc

@@ -0,0 +1,15 @@
+$input v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+SAMPLER2D(s_texColor, 0);
+
+void main()
+{
+	gl_FragColor = texture2D(s_texColor, v_texcoord0);
+}

+ 13 - 0
examples/21-deferred/fs_deferred_debug_line.sc

@@ -0,0 +1,13 @@
+$input v_color0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+void main()
+{
+	gl_FragColor = v_color0;
+}

+ 31 - 0
examples/21-deferred/fs_deferred_geom.sc

@@ -0,0 +1,31 @@
+$input v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+SAMPLER2D(s_texColor,  0);
+SAMPLER2D(s_texNormal, 1);
+
+void main()
+{
+	vec3 normal;
+	normal.xy = texture2D(s_texNormal, v_texcoord0).xy * 2.0 - 1.0;
+	normal.z  = sqrt(1.0 - dot(normal.xy, normal.xy) );
+
+	mat3 tbn = mat3(
+				normalize(v_tangent),
+				normalize(v_bitangent),
+				normalize(v_normal)
+				);
+
+	normal = normalize(mul(tbn, normal) );
+
+	vec3 wnormal = normalize(mul(u_invView, vec4(normal, 0.0) ).xyz);
+
+	gl_FragData[0] = texture2D(s_texColor, v_texcoord0);
+	gl_FragData[1] = vec4(encodeNormalUint(wnormal), 1.0);
+}

+ 91 - 0
examples/21-deferred/fs_deferred_light.sc

@@ -0,0 +1,91 @@
+$input v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+SAMPLER2D(s_normal, 0);
+SAMPLER2D(s_depth,  1);
+
+uniform vec4 u_lightPosRadius[1];
+uniform vec4 u_lightRgbInnerR[1];
+uniform mat4 u_mtx;
+
+vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir)
+{
+	float ndotl = dot(_normal, _lightDir);
+	vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal);
+	float rdotv = dot(reflected, _viewDir);
+	return vec2(ndotl, rdotv);
+}
+
+float fresnel(float _ndotl, float _bias, float _pow)
+{
+	float facing = (1.0 - _ndotl);
+	return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0);
+}
+
+vec4 lit(float _ndotl, float _rdotv, float _m)
+{
+	float diff = max(0.0, _ndotl);
+	float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m);
+	return vec4(1.0, diff, spec, 1.0);
+}
+
+vec4 powRgba(vec4 _rgba, float _pow)
+{
+	vec4 result;
+	result.xyz = pow(_rgba.xyz, vec3_splat(_pow) );
+	result.w = _rgba.w;
+	return result;
+}
+
+vec3 calcLight(int _idx, vec3 _wpos, vec3 _normal, vec3 _view)
+{
+	vec3 lp = u_lightPosRadius[_idx].xyz - _wpos;
+	float attn = 1.0 - smoothstep(u_lightRgbInnerR[_idx].w, 1.0, length(lp) / u_lightPosRadius[_idx].w);
+	vec3 lightDir = normalize(lp);
+	vec2 bln = blinn(lightDir, _normal, _view);
+	vec4 lc = lit(bln.x, bln.y, 1.0);
+	vec3 rgb = u_lightRgbInnerR[_idx].xyz * saturate(lc.y) * attn;
+	return rgb;
+}
+
+float toClipSpaceDepth(float _depthTextureZ)
+{
+#if BGFX_SHADER_LANGUAGE_HLSL
+	return _depthTextureZ;
+#else
+	return _depthTextureZ * 2.0 - 1.0;
+#endif // BGFX_SHADER_LANGUAGE_HLSL
+}
+
+vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos)
+{
+	vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) );
+	return wpos.xyz / wpos.w;
+}
+
+void main()
+{
+	vec3  normal      = decodeNormalUint(texture2D(s_normal, v_texcoord0).xyz);
+	float deviceDepth = texture2D(s_depth,  v_texcoord0).x;
+	float depth       = toClipSpaceDepth(deviceDepth);
+
+	vec3 clip = vec3(v_texcoord0 * 2.0 - 1.0, depth);
+#if BGFX_SHADER_LANGUAGE_HLSL
+	clip.y = -clip.y;
+#endif // BGFX_SHADER_LANGUAGE_HLSL
+	vec3 wpos = clipToWorld(u_mtx, clip);
+
+	vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz;
+	view = -normalize(view);
+
+	vec3 lightColor;
+	lightColor = calcLight(0, wpos, normal, view);
+	gl_FragColor.xyz = toGamma(lightColor.xyz);
+	gl_FragColor.w = 1.0;
+}

+ 17 - 0
examples/21-deferred/makefile

@@ -0,0 +1,17 @@
+#
+# Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+# License: http://www.opensource.org/licenses/BSD-2-Clause
+#
+
+BGFX_DIR=../..
+RUNTIME_DIR=$(BGFX_DIR)/examples/runtime
+BUILD_DIR=../../.build
+
+include $(BGFX_DIR)/premake/shader.mk
+
+rebuild:
+	@make -s --no-print-directory TARGET=0 clean all
+	@make -s --no-print-directory TARGET=1 clean all
+	@make -s --no-print-directory TARGET=2 clean all
+	@make -s --no-print-directory TARGET=3 clean all
+	@make -s --no-print-directory TARGET=4 clean all

BIN
examples/21-deferred/screenshot.png


+ 17 - 0
examples/21-deferred/varying.def.sc

@@ -0,0 +1,17 @@
+vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
+vec3 v_wpos      : TEXCOORD1 = vec3(0.0, 0.0, 0.0);
+vec3 v_view      : TEXCOORD2 = vec3(0.0, 0.0, 0.0);
+vec3 v_normal    : NORMAL    = vec3(0.0, 0.0, 1.0);
+vec3 v_tangent   : TANGENT   = vec3(1.0, 0.0, 0.0);
+vec3 v_bitangent : BINORMAL  = vec3(0.0, 1.0, 0.0);
+vec4 v_color0    : COLOR     = vec4(1.0, 0.0, 0.0, 1.0);
+
+vec3 a_position  : POSITION;
+vec4 a_normal    : NORMAL;
+vec4 a_tangent   : TANGENT;
+vec2 a_texcoord0 : TEXCOORD0;
+vec4 a_color0    : COLOR0;
+vec4 i_data0     : TEXCOORD4;
+vec4 i_data1     : TEXCOORD5;
+vec4 i_data2     : TEXCOORD6;
+vec4 i_data3     : TEXCOORD7;

+ 15 - 0
examples/21-deferred/vs_deferred_combine.sc

@@ -0,0 +1,15 @@
+$input a_position, a_texcoord0
+$output v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+void main()
+{
+	gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
+	v_texcoord0 = a_texcoord0;
+}

+ 15 - 0
examples/21-deferred/vs_deferred_debug.sc

@@ -0,0 +1,15 @@
+$input a_position, a_texcoord0
+$output v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+void main()
+{
+	gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
+	v_texcoord0 = a_texcoord0;
+}

+ 15 - 0
examples/21-deferred/vs_deferred_debug_line.sc

@@ -0,0 +1,15 @@
+$input a_position, a_color0
+$output v_color0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+void main()
+{
+	gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
+	v_color0 = a_color0;
+}

+ 37 - 0
examples/21-deferred/vs_deferred_geom.sc

@@ -0,0 +1,37 @@
+$input a_position, a_normal, a_tangent, a_texcoord0
+$output v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+void main()
+{
+	vec3 wpos = mul(u_model[0], vec4(a_position, 1.0) ).xyz;
+	gl_Position = mul(u_viewProj, vec4(wpos, 1.0) );
+	
+	vec4 normal = a_normal * 2.0f - 1.0f;
+	vec3 wnormal = mul(u_model[0], vec4(normal.xyz, 0.0) ).xyz;
+
+	vec4 tangent = a_tangent * 2.0f - 1.0f;
+	vec3 wtangent = mul(u_model[0], vec4(tangent.xyz, 0.0) ).xyz;
+
+	vec3 viewNormal = normalize(mul(u_view, vec4(wnormal, 0.0) ).xyz);
+	vec3 viewTangent = normalize(mul(u_view, vec4(wtangent, 0.0) ).xyz);
+	vec3 viewBitangent = cross(viewNormal, viewTangent) * tangent.w;
+	mat3 tbn = mat3(viewTangent, viewBitangent, viewNormal);
+
+	v_wpos = wpos;
+
+	vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz;
+	v_view = mul(view, tbn);
+
+	v_normal    = viewNormal;
+	v_tangent   = viewTangent;
+	v_bitangent = viewBitangent;
+
+	v_texcoord0 = a_texcoord0;
+}

+ 15 - 0
examples/21-deferred/vs_deferred_light.sc

@@ -0,0 +1,15 @@
+$input a_position, a_texcoord0
+$output v_texcoord0
+
+/*
+ * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+void main()
+{
+	gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
+	v_texcoord0 = a_texcoord0;
+}

+ 10 - 0
examples/common/shaderlib.sh

@@ -39,6 +39,16 @@ vec3 decodeRGBE8(vec4 _rgbe8)
 	return rgb;
 	return rgb;
 }
 }
 
 
+vec3 encodeNormalUint(vec3 _normal)
+{
+	return _normal * 0.5 + 0.5;
+}
+
+vec3 decodeNormalUint(vec3 _encodedNormal)
+{
+	return _encodedNormal * 2.0 - 1.0;
+}
+
 // Reference:
 // Reference:
 // RGB/XYZ Matrices
 // RGB/XYZ Matrices
 // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
 // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

BIN
examples/runtime/shaders/dx11/fs_deferred_combine.bin


BIN
examples/runtime/shaders/dx11/fs_deferred_debug.bin


BIN
examples/runtime/shaders/dx11/fs_deferred_debug_line.bin


BIN
examples/runtime/shaders/dx11/fs_deferred_geom.bin


BIN
examples/runtime/shaders/dx11/fs_deferred_light.bin


BIN
examples/runtime/shaders/dx11/vs_deferred_combine.bin


BIN
examples/runtime/shaders/dx11/vs_deferred_debug.bin


BIN
examples/runtime/shaders/dx11/vs_deferred_debug_line.bin


BIN
examples/runtime/shaders/dx11/vs_deferred_geom.bin


BIN
examples/runtime/shaders/dx11/vs_deferred_light.bin


BIN
examples/runtime/shaders/dx9/fs_deferred_combine.bin


BIN
examples/runtime/shaders/dx9/fs_deferred_debug.bin


BIN
examples/runtime/shaders/dx9/fs_deferred_debug_line.bin


BIN
examples/runtime/shaders/dx9/fs_deferred_geom.bin


BIN
examples/runtime/shaders/dx9/fs_deferred_light.bin


BIN
examples/runtime/shaders/dx9/vs_deferred_combine.bin


BIN
examples/runtime/shaders/dx9/vs_deferred_debug.bin


BIN
examples/runtime/shaders/dx9/vs_deferred_debug_line.bin


BIN
examples/runtime/shaders/dx9/vs_deferred_geom.bin


BIN
examples/runtime/shaders/dx9/vs_deferred_light.bin


BIN
examples/runtime/shaders/gles/fs_deferred_combine.bin


BIN
examples/runtime/shaders/gles/fs_deferred_debug.bin


BIN
examples/runtime/shaders/gles/fs_deferred_debug_line.bin


BIN
examples/runtime/shaders/gles/fs_deferred_geom.bin


BIN
examples/runtime/shaders/gles/fs_deferred_light.bin


BIN
examples/runtime/shaders/gles/vs_deferred_combine.bin


BIN
examples/runtime/shaders/gles/vs_deferred_debug.bin


BIN
examples/runtime/shaders/gles/vs_deferred_debug_line.bin


BIN
examples/runtime/shaders/gles/vs_deferred_geom.bin


BIN
examples/runtime/shaders/gles/vs_deferred_light.bin


BIN
examples/runtime/shaders/glsl/fs_deferred_combine.bin


BIN
examples/runtime/shaders/glsl/fs_deferred_debug.bin


BIN
examples/runtime/shaders/glsl/fs_deferred_debug_line.bin


BIN
examples/runtime/shaders/glsl/fs_deferred_geom.bin


BIN
examples/runtime/shaders/glsl/fs_deferred_light.bin


BIN
examples/runtime/shaders/glsl/vs_deferred_combine.bin


BIN
examples/runtime/shaders/glsl/vs_deferred_debug.bin


BIN
examples/runtime/shaders/glsl/vs_deferred_debug_line.bin


BIN
examples/runtime/shaders/glsl/vs_deferred_geom.bin


BIN
examples/runtime/shaders/glsl/vs_deferred_light.bin


+ 1 - 0
premake/premake4.lua

@@ -177,6 +177,7 @@ exampleProject("17-drawstress",        "9aeea4c6-80dc-11e3-b3ca-4da6db0f677b")
 exampleProject("18-ibl",               "711bcbb0-9531-11e3-a5e2-0800200c9a66")
 exampleProject("18-ibl",               "711bcbb0-9531-11e3-a5e2-0800200c9a66")
 exampleProject("19-oit",               "d7eca4fc-96d7-11e3-a73b-fcafdb0f677b")
 exampleProject("19-oit",               "d7eca4fc-96d7-11e3-a73b-fcafdb0f677b")
 exampleProject("20-nanovg",            "359ce7c4-cd06-11e3-bb8b-6c2f9a125b5a")
 exampleProject("20-nanovg",            "359ce7c4-cd06-11e3-bb8b-6c2f9a125b5a")
+exampleProject("21-deferred",          "f89e59ec-d16b-11e3-bc9c-2dfd99125b5a")
 
 
 if _OPTIONS["with-tools"] then
 if _OPTIONS["with-tools"] then
 	dofile "makedisttex.lua"
 	dofile "makedisttex.lua"

+ 6 - 0
src/renderer_d3d9.cpp

@@ -462,6 +462,12 @@ namespace bgfx
 				m_device->SetRenderState(D3DRS_POINTSIZE, D3DFMT_INST);
 				m_device->SetRenderState(D3DRS_POINTSIZE, D3DFMT_INST);
 			}
 			}
 
 
+			if (s_extendedFormats[ExtendedFormat::Intz].m_supported)
+			{
+				s_textureFormat[TextureFormat::D24].m_fmt = D3DFMT_INTZ;
+				s_textureFormat[TextureFormat::D32].m_fmt = D3DFMT_INTZ;
+			}
+
 			s_textureFormat[TextureFormat::BC4].m_fmt = s_extendedFormats[ExtendedFormat::Ati1].m_supported ? D3DFMT_ATI1 : D3DFMT_UNKNOWN;
 			s_textureFormat[TextureFormat::BC4].m_fmt = s_extendedFormats[ExtendedFormat::Ati1].m_supported ? D3DFMT_ATI1 : D3DFMT_UNKNOWN;
 			s_textureFormat[TextureFormat::BC5].m_fmt = s_extendedFormats[ExtendedFormat::Ati2].m_supported ? D3DFMT_ATI2 : D3DFMT_UNKNOWN;
 			s_textureFormat[TextureFormat::BC5].m_fmt = s_extendedFormats[ExtendedFormat::Ati2].m_supported ? D3DFMT_ATI2 : D3DFMT_UNKNOWN;