Browse Source

Merge pull request #75 from dariomanesku/master

18-ibl example and some minor fixes.
Branimir Karadžić 12 years ago
parent
commit
8f56c5a120
53 changed files with 1133 additions and 45 deletions
  1. 3 2
      examples/14-shadowvolumes/fs_shadowvolume_color_lightning.sc
  2. 3 2
      examples/14-shadowvolumes/fs_shadowvolume_texture_lightning.sc
  3. 12 13
      examples/14-shadowvolumes/shadowvolumes.cpp
  4. 1 1
      examples/14-shadowvolumes/vs_shadowvolume_color_lightning.sc
  5. 1 1
      examples/14-shadowvolumes/vs_shadowvolume_texture_lightning.sc
  6. 25 25
      examples/16-shadowmaps/shadowmaps.cpp
  7. 79 0
      examples/18-ibl/fs_ibl_mesh.sc
  8. 23 0
      examples/18-ibl/fs_ibl_skybox.sc
  9. 921 0
      examples/18-ibl/ibl.cpp
  10. 17 0
      examples/18-ibl/makefile
  11. 7 0
      examples/18-ibl/varying.def.sc
  12. 20 0
      examples/18-ibl/vs_ibl_mesh.sc
  13. 19 0
      examples/18-ibl/vs_ibl_skybox.sc
  14. 1 1
      examples/common/entry/entry.cpp
  15. BIN
      examples/runtime/shaders/dx11/fs_ibl_mesh.bin
  16. BIN
      examples/runtime/shaders/dx11/fs_ibl_skybox.bin
  17. BIN
      examples/runtime/shaders/dx11/fs_shadowvolume_color_lightning.bin
  18. BIN
      examples/runtime/shaders/dx11/fs_shadowvolume_texture_lightning.bin
  19. BIN
      examples/runtime/shaders/dx11/vs_ibl_mesh.bin
  20. BIN
      examples/runtime/shaders/dx11/vs_ibl_skybox.bin
  21. BIN
      examples/runtime/shaders/dx11/vs_shadowvolume_color_lightning.bin
  22. BIN
      examples/runtime/shaders/dx11/vs_shadowvolume_texture_lightning.bin
  23. BIN
      examples/runtime/shaders/dx9/fs_ibl_mesh.bin
  24. BIN
      examples/runtime/shaders/dx9/fs_ibl_skybox.bin
  25. BIN
      examples/runtime/shaders/dx9/fs_shadowvolume_color_lightning.bin
  26. BIN
      examples/runtime/shaders/dx9/fs_shadowvolume_texture_lightning.bin
  27. BIN
      examples/runtime/shaders/dx9/vs_ibl_mesh.bin
  28. BIN
      examples/runtime/shaders/dx9/vs_ibl_skybox.bin
  29. BIN
      examples/runtime/shaders/dx9/vs_shadowvolume_color_lightning.bin
  30. BIN
      examples/runtime/shaders/dx9/vs_shadowvolume_texture_lightning.bin
  31. BIN
      examples/runtime/shaders/gles/fs_ibl_mesh.bin
  32. BIN
      examples/runtime/shaders/gles/fs_ibl_skybox.bin
  33. BIN
      examples/runtime/shaders/gles/vs_ibl_mesh.bin
  34. BIN
      examples/runtime/shaders/gles/vs_ibl_skybox.bin
  35. BIN
      examples/runtime/shaders/glsl/fs_ibl_mesh.bin
  36. BIN
      examples/runtime/shaders/glsl/fs_ibl_skybox.bin
  37. BIN
      examples/runtime/shaders/glsl/fs_shadowvolume_color_lightning.bin
  38. BIN
      examples/runtime/shaders/glsl/fs_shadowvolume_texture_lightning.bin
  39. BIN
      examples/runtime/shaders/glsl/vs_ibl_mesh.bin
  40. BIN
      examples/runtime/shaders/glsl/vs_ibl_skybox.bin
  41. BIN
      examples/runtime/shaders/glsl/vs_shadowvolume_color_lightning.bin
  42. BIN
      examples/runtime/shaders/glsl/vs_shadowvolume_texture_lightning.bin
  43. BIN
      examples/runtime/textures/ennis_irr.dds
  44. BIN
      examples/runtime/textures/ennis_lod.dds
  45. BIN
      examples/runtime/textures/grace_irr.dds
  46. BIN
      examples/runtime/textures/grace_lod.dds
  47. BIN
      examples/runtime/textures/pisa_irr.dds
  48. BIN
      examples/runtime/textures/pisa_lod.dds
  49. BIN
      examples/runtime/textures/uffizi_irr.dds
  50. BIN
      examples/runtime/textures/uffizi_lod.dds
  51. BIN
      examples/runtime/textures/wells_irr.dds
  52. BIN
      examples/runtime/textures/wells_lod.dds
  53. 1 0
      premake/premake4.lua

+ 3 - 2
examples/14-shadowvolumes/fs_shadowvolume_color_lightning.sc

@@ -19,7 +19,7 @@ SAMPLER2D(u_texStencil, 7);
 
 #define u_ambientPass   u_params.x
 #define u_lightningPass u_params.y
-#define u_alpha         u_params.z
+#define u_texelHalf     u_params.z
 #define u_specular      u_specular_shininess.xyz
 #define u_shininess     u_specular_shininess.w
 
@@ -68,6 +68,7 @@ void main()
 	vec3 lightColor = calcLight(v_view, normal, viewDir) * u_lightningPass;
 
 	vec2 ndc = ((v_pos.xy / v_pos.w) + 1.0) / 2.0;
+	ndc += u_viewTexel.xy * u_texelHalf;
 	vec4 texcolor = texture2D(u_texStencil, ndc);
 	float s = (texcolor.x - texcolor.y) + 2.0 * (texcolor.z - texcolor.w);
 	s *= u_useStencilTex;
@@ -84,5 +85,5 @@ void main()
 	vec3 final   = mix(ambient, ambient + diffuse, float((abs(s) < 0.0001)));
 
 	gl_FragColor.xyz = mix(u_fogColor, final, fogFactor);
-	gl_FragColor.w   = u_alpha;
+	gl_FragColor.w   = 1.0;
 }

+ 3 - 2
examples/14-shadowvolumes/fs_shadowvolume_texture_lightning.sc

@@ -20,7 +20,7 @@ SAMPLER2D(u_texStencil, 7);
 
 #define u_ambientPass   u_params.x
 #define u_lightningPass u_params.y
-#define u_alpha         u_params.z
+#define u_texelHalf     u_params.z
 #define u_specular      u_specular_shininess.xyz
 #define u_shininess     u_specular_shininess.w
 
@@ -69,6 +69,7 @@ void main()
 	vec3 lightColor = calcLight(v_view, normal, viewDir) * u_lightningPass;
 
 	vec2 ndc = ((v_pos.xy / v_pos.w) + 1.0) / 2.0;
+	ndc += u_viewTexel.xy * u_texelHalf;
 	vec4 texcolor = texture2D(u_texStencil, ndc);
 	float s = (texcolor.x - texcolor.y) + 2.0 * (texcolor.z - texcolor.w);
 	s *= u_useStencilTex;
@@ -85,6 +86,6 @@ void main()
 	vec3 final   = mix(ambient, ambient + diffuse, float((abs(s) < 0.0001)));
 
 	gl_FragColor.xyz = mix(u_fogColor, final, fogFactor);
-	gl_FragColor.w   = u_alpha;
+	gl_FragColor.w   = 1.0;
 }
 

+ 12 - 13
examples/14-shadowvolumes/shadowvolumes.cpp

@@ -99,6 +99,7 @@ static const uint16_t s_planeIndices[s_numPlaneIndices] =
 
 static const char* s_shaderPath = NULL;
 static bool s_flipV = false;
+static float s_texelHalf = 0.0f;
 
 static uint32_t s_viewMask = 0;
 
@@ -266,8 +267,7 @@ struct Uniforms
 	{
 		m_params.m_ambientPass   = 1.0f;
 		m_params.m_lightningPass = 1.0f;
-		m_params.m_lightCount    = 4.0f;
-		m_params.m_alpha         = 1.0f;
+		m_params.m_texelHalf     = 0.0f;
 
 		m_ambient[0] = 0.05f;
 		m_ambient[1] = 0.05f;
@@ -374,16 +374,16 @@ struct Uniforms
 	{
 		float m_ambientPass;
 		float m_lightningPass;
-		float m_alpha;
-		float m_lightCount;
+		float m_texelHalf;
+		float m_unused00;
 	};
 
 	struct SvParams
 	{
 		float m_useStencilTex;
 		float m_dfail;
-		float m_unused0;
-		float m_unused1;
+		float m_unused10;
+		float m_unused11;
 	};
 
 	Params m_params;
@@ -402,8 +402,8 @@ struct Uniforms
 	/**
 	 * u_params.x - u_ambientPass
 	 * u_params.y - u_lightningPass
-	 * u_params.z - u_alpha
-	 * u_params.w - u_lightCount
+	 * u_params.z - u_texelHalf
+	 * u_params.w - unused
 
 	 * u_svparams.x - u_useStencilTex
 	 * u_svparams.y - u_dfail
@@ -1944,23 +1944,22 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 	default:
 	case bgfx::RendererType::Direct3D9:
 		s_shaderPath = "shaders/dx9/";
-		s_flipV = true;
+		s_texelHalf = 0.5f;
 		break;
 
 	case bgfx::RendererType::Direct3D11:
 		s_shaderPath = "shaders/dx11/";
-		s_flipV = true;
 		break;
 
 	case bgfx::RendererType::OpenGL:
 		s_shaderPath = "shaders/glsl/";
-		s_flipV = false;
+		s_flipV = true;
 		break;
 
 	case bgfx::RendererType::OpenGLES2:
 	case bgfx::RendererType::OpenGLES3:
 		s_shaderPath = "shaders/gles/";
-		s_flipV = false;
+		s_flipV = true;
 		break;
 	}
 
@@ -2331,7 +2330,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		//update settings
 		s_uniforms.m_params.m_ambientPass     = 1.0f;
 		s_uniforms.m_params.m_lightningPass   = 1.0f;
-		s_uniforms.m_params.m_lightCount      = settings_numLights;
+		s_uniforms.m_params.m_texelHalf       = s_texelHalf;
 		s_uniforms.m_svparams.m_useStencilTex = float(settings_useStencilTexture);
 		s_uniforms.submitPerFrameUniforms();
 

+ 1 - 1
examples/14-shadowvolumes/vs_shadowvolume_color_lightning.sc

@@ -19,5 +19,5 @@ void main()
 	v_view = mul(u_modelView, vec4(a_position, 1.0)).xyz;
 
 	v_pos = gl_Position;
-	v_pos.y *= -u_flipV;
+	v_pos.y *= u_flipV;
 }

+ 1 - 1
examples/14-shadowvolumes/vs_shadowvolume_texture_lightning.sc

@@ -21,5 +21,5 @@ void main()
 	v_texcoord0 = a_texcoord0;
 
 	v_pos = gl_Position;
-	v_pos.y *= -u_flipV;
+	v_pos.y *= u_flipV;
 }

+ 25 - 25
examples/16-shadowmaps/shadowmaps.cpp

@@ -86,9 +86,9 @@ struct LightType
 {
 	enum Enum
 	{
-		SpotLight        = 0,
-		PointLight       = 1,
-		DirectionalLight = 2,
+		SpotLight,
+		PointLight,
+		DirectionalLight,
 
 		Count
 	};
@@ -99,8 +99,8 @@ struct DepthImpl
 {
 	enum Enum
 	{
-		InvZ   = 0,
-		Linear = 1,
+		InvZ,
+		Linear,
 
 		Count
 	};
@@ -110,8 +110,8 @@ struct PackDepth
 {
 	enum Enum
 	{
-		RGBA = 0,
-		VSM  = 1,
+		RGBA,
+		VSM,
 
 		Count
 	};
@@ -121,10 +121,10 @@ struct SmImpl
 {
 	enum Enum
 	{
-		Hard = 0,
-		PCF  = 1,
-		VSM  = 2,
-		ESM  = 3,
+		Hard,
+		PCF,
+		VSM,
+		ESM,
 
 		Count
 	};
@@ -134,9 +134,9 @@ struct SmType
 {
 	enum Enum
 	{
-		Single  = 0,
-		Omni    = 1,
-		Cascade = 2,
+		Single,
+		Omni,
+		Cascade,
 
 		Count
 	};
@@ -146,12 +146,12 @@ struct TetrahedronFaces
 {
 	enum Enum
 	{
-		Green  = 0,
-		Yellow = 1,
-		Blue   = 2,
-		Red    = 3,
+		Green,
+		Yellow,
+		Blue,
+		Red,
 
-		Count  = 4
+		Count
 	};
 };
 
@@ -159,8 +159,8 @@ struct ProjType
 {
 	enum Enum
 	{
-		Horizontal = 0,
-		Vertical   = 1,
+		Horizontal,
+		Vertical,
 
 		Count
 	};
@@ -170,10 +170,10 @@ struct ShadowMapRenderTargets
 {
 	enum Enum
 	{
-		First  = 0,
-		Second = 1,
-		Third  = 2,
-		Fourth = 3,
+		First,
+		Second,
+		Third,
+		Fourth,
 
 		Count
 	};

+ 79 - 0
examples/18-ibl/fs_ibl_mesh.sc

@@ -0,0 +1,79 @@
+$input v_view, v_normal
+
+/*
+ * Copyright 2014 Dario Manesku. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+uniform float u_time;
+uniform vec4 u_params;
+uniform mat4 u_mtx;
+uniform vec4 u_flags;
+uniform vec3 u_camPos;
+uniform vec3 u_rgbDiff;
+uniform vec3 u_rgbSpec;
+
+SAMPLERCUBE(u_texCube, 4);
+SAMPLERCUBE(u_texCubeIrr, 5);
+
+#define u_glossiness u_params.x
+#define u_exposure   u_params.y
+#define u_diffspec   u_params.z
+
+#define u_doDiffuse     u_flags.x
+#define u_doSpecular    u_flags.y
+#define u_doDiffuseIbl  u_flags.z
+#define u_doSpecularIbl u_flags.w
+
+vec3 fresnel(vec3 _cspec, float _dot)
+{
+	return _cspec + (1.0 - _cspec) * pow(1.0 - _dot, 5);
+}
+
+void main()
+{
+	vec3 light = vec3(0.0f, 0.0f, -1.0f);
+	vec3 clight = vec3(1.0f, 1.0f, 1.0f);
+
+	vec3 v = v_view;
+	vec3 n = normalize(v_normal);
+	vec3 l = normalize(light);
+	vec3 h = normalize(v + l);
+
+	float ndotl = clamp(dot(n, l), 0.0, 1.0); //diff
+	float ndoth = clamp(dot(n, h), 0.0, 1.0); //spec
+	float vdoth = clamp(dot(v, h), 0.0, 1.0); //spec fresnel
+	float ndotv = clamp(dot(n, v), 0.0, 1.0); //env spec fresnel
+
+	vec3 r = 2.0*ndotv*n - v; // reflect(v, n);
+
+	vec3 cubeR = normalize(mul(u_mtx, vec4(r, 0.0)).xyz);
+	vec3 cubeN = normalize(mul(u_mtx, vec4(n, 0.0)).xyz);
+
+	float mipLevel = min((1.0 - u_glossiness)*11.0 + 1.0, 8.0);
+	vec3 cenv = textureCubeLod(u_texCube, cubeR, mipLevel).xyz;
+
+	vec3 kd = u_rgbDiff;
+	vec3 ks = u_rgbSpec;
+
+	vec3 cs = ks * u_diffspec;
+	vec3 cd = kd * (1.0 - cs);
+
+	vec3 diff = cd;
+    float pwr = exp2(u_glossiness * 11.0 + 1.0);
+	vec3 spec = cs * pow(ndoth, pwr) * ( (pwr + 8.0)/8.0) * fresnel(cs, vdoth);
+
+	vec3 ambspec = fresnel(cs, ndotv) * cenv;
+	vec3 ambdiff = cd * textureCube(u_texCubeIrr, cubeN).xyz;
+
+	vec3 lc = (   diff * u_doDiffuse    +    spec * u_doSpecular   ) * ndotl * clight;
+	vec3 ec = (ambdiff * u_doDiffuseIbl + ambspec * u_doSpecularIbl);
+
+	vec3 color = lc + ec;
+	color = color * exp2(u_exposure);
+
+	gl_FragColor.xyz = toFilmic(color);
+	gl_FragColor.w = 1.0;
+}

+ 23 - 0
examples/18-ibl/fs_ibl_skybox.sc

@@ -0,0 +1,23 @@
+$input v_dir
+
+/*
+ * Copyright 2014 Dario Manesku. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+SAMPLERCUBE(u_texCube, 4);
+
+uniform vec4 u_params;
+#define u_exposure  u_params.y
+
+void main()
+{
+	vec3 dir = normalize(v_dir);
+
+	vec4 color = textureCubeLod(u_texCube, dir, 0.0);
+	color *= exp2(u_exposure);
+
+	gl_FragColor = toFilmic(color);
+}

+ 921 - 0
examples/18-ibl/ibl.cpp

@@ -0,0 +1,921 @@
+/*
+ * Copyright 2014 Dario Manesku. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include <string>
+#include <vector>
+
+#include "common.h"
+
+#include <bgfx.h>
+#include <bx/timer.h>
+#include <bx/readerwriter.h>
+#include "entry/entry.h"
+#include "fpumath.h"
+#include "imgui/imgui.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static const char* s_shaderPath = NULL;
+static bool s_flipV = false;
+static float s_texelHalf = 0.0f;
+
+static void shaderFilePath(char* _out, const char* _name)
+{
+	strcpy(_out, s_shaderPath);
+	strcat(_out, _name);
+	strcat(_out, ".bin");
+}
+
+long int fsize(FILE* _file)
+{
+	long int pos = ftell(_file);
+	fseek(_file, 0L, SEEK_END);
+	long int size = ftell(_file);
+	fseek(_file, pos, SEEK_SET);
+	return size;
+}
+
+static const bgfx::Memory* load(const char* _filePath)
+{
+	FILE* file = fopen(_filePath, "rb");
+	if (NULL != file)
+	{
+		uint32_t size = (uint32_t)fsize(file);
+		const bgfx::Memory* mem = bgfx::alloc(size+1);
+		size_t ignore = fread(mem->data, 1, size, file);
+		BX_UNUSED(ignore);
+		fclose(file);
+		mem->data[mem->size-1] = '\0';
+		return mem;
+	}
+
+	return NULL;
+}
+
+static const bgfx::Memory* loadShader(const char* _name)
+{
+	char filePath[512];
+	shaderFilePath(filePath, _name);
+	return load(filePath);
+}
+
+static bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName)
+{
+	const bgfx::Memory* mem;
+
+	mem = loadShader(_vsName);
+	bgfx::VertexShaderHandle vs = bgfx::createVertexShader(mem);
+	mem = loadShader(_fsName);
+	bgfx::FragmentShaderHandle fs = bgfx::createFragmentShader(mem);
+	bgfx::ProgramHandle program = bgfx::createProgram(vs, fs);
+	bgfx::destroyVertexShader(vs);
+	bgfx::destroyFragmentShader(fs);
+
+	return program;
+}
+
+static const bgfx::Memory* loadTexture(const char* _name)
+{
+	char filePath[512];
+	strcpy(filePath, "textures/");
+	strcat(filePath, _name);
+	return load(filePath);
+}
+
+struct Uniforms
+{
+	void init()
+	{
+		m_time = 0.0f;
+		mtxIdentity(m_mtx);
+
+		u_time    = bgfx::createUniform("u_time",     bgfx::UniformType::Uniform1f);
+		u_mtx     = bgfx::createUniform("u_mtx",      bgfx::UniformType::Uniform4x4fv);
+		u_params  = bgfx::createUniform("u_params",  bgfx::UniformType::Uniform4fv);
+		u_flags   = bgfx::createUniform("u_flags",    bgfx::UniformType::Uniform4fv);
+		u_camPos  = bgfx::createUniform("u_camPos",   bgfx::UniformType::Uniform3fv);
+		u_rgbDiff = bgfx::createUniform("u_rgbDiff",  bgfx::UniformType::Uniform3fv);
+		u_rgbSpec = bgfx::createUniform("u_rgbSpec",  bgfx::UniformType::Uniform3fv);
+	}
+
+	// Call this once at initialization.
+	void submitConstUniforms()
+	{
+	}
+
+	// Call this once per frame.
+	void submitPerFrameUniforms()
+	{
+		bgfx::setUniform(u_time, &m_time);
+		bgfx::setUniform(u_mtx, m_mtx);
+		bgfx::setUniform(u_flags, m_flags);
+		bgfx::setUniform(u_camPos, m_camPos);
+		bgfx::setUniform(u_rgbDiff, m_rgbDiff);
+		bgfx::setUniform(u_rgbSpec, m_rgbSpec);
+	}
+
+	// Call this before each draw call.
+	void submitPerDrawUniforms()
+	{
+		bgfx::setUniform(u_params, m_params);
+	}
+
+	void destroy()
+	{
+		bgfx::destroyUniform(u_rgbSpec);
+		bgfx::destroyUniform(u_rgbDiff);
+		bgfx::destroyUniform(u_camPos);
+		bgfx::destroyUniform(u_flags);
+		bgfx::destroyUniform(u_params);
+		bgfx::destroyUniform(u_mtx);
+		bgfx::destroyUniform(u_time);
+	}
+
+	union
+	{
+		struct
+		{
+			float m_glossiness;
+			float m_exposure;
+			float m_diffspec;
+			float m_unused0;
+		};
+
+		float m_params[4];
+	};
+
+	union
+	{
+		struct
+		{
+			float m_diffuse;
+			float m_specular;
+			float m_diffuseIbl;
+			float m_specularIbl;
+		};
+
+		float m_flags[4];
+	};
+
+	float m_time;
+	float m_mtx[16];
+	float m_camPos[3];
+	float m_rgbDiff[3];
+	float m_rgbSpec[3];
+
+	bgfx::UniformHandle u_time;
+	bgfx::UniformHandle u_mtx;
+	bgfx::UniformHandle u_params;
+	bgfx::UniformHandle u_flags;
+	bgfx::UniformHandle u_camPos;
+	bgfx::UniformHandle u_rgbDiff;
+	bgfx::UniformHandle u_rgbSpec;
+};
+static Uniforms s_uniforms;
+
+struct Aabb
+{
+	float m_min[3];
+	float m_max[3];
+};
+
+struct Obb
+{
+	float m_mtx[16];
+};
+
+struct Sphere
+{
+	float m_center[3];
+	float m_radius;
+};
+
+struct Primitive
+{
+	uint32_t m_startIndex;
+	uint32_t m_numIndices;
+	uint32_t m_startVertex;
+	uint32_t m_numVertices;
+
+	Sphere m_sphere;
+	Aabb m_aabb;
+	Obb m_obb;
+};
+
+typedef std::vector<Primitive> PrimitiveArray;
+
+struct Group
+{
+	Group()
+	{
+		reset();
+	}
+
+	void reset()
+	{
+		m_vbh.idx = bgfx::invalidHandle;
+		m_ibh.idx = bgfx::invalidHandle;
+		m_prims.clear();
+	}
+
+	bgfx::VertexBufferHandle m_vbh;
+	bgfx::IndexBufferHandle m_ibh;
+	Sphere m_sphere;
+	Aabb m_aabb;
+	Obb m_obb;
+	PrimitiveArray m_prims;
+};
+
+struct Mesh
+{
+	void load(const char* _filePath)
+	{
+#define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x0)
+#define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0)
+#define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
+
+		bx::CrtFileReader reader;
+		reader.open(_filePath);
+
+		Group group;
+
+		uint32_t chunk;
+		while (4 == bx::read(&reader, chunk) )
+		{
+			switch (chunk)
+			{
+			case BGFX_CHUNK_MAGIC_VB:
+				{
+					bx::read(&reader, group.m_sphere);
+					bx::read(&reader, group.m_aabb);
+					bx::read(&reader, group.m_obb);
+
+					bx::read(&reader, m_decl);
+					uint16_t stride = m_decl.getStride();
+
+					uint16_t numVertices;
+					bx::read(&reader, numVertices);
+					const bgfx::Memory* mem = bgfx::alloc(numVertices*stride);
+					bx::read(&reader, mem->data, mem->size);
+
+					group.m_vbh = bgfx::createVertexBuffer(mem, m_decl);
+				}
+				break;
+
+			case BGFX_CHUNK_MAGIC_IB:
+				{
+					uint32_t numIndices;
+					bx::read(&reader, numIndices);
+					const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
+					bx::read(&reader, mem->data, mem->size);
+					group.m_ibh = bgfx::createIndexBuffer(mem);
+				}
+				break;
+
+			case BGFX_CHUNK_MAGIC_PRI:
+				{
+					uint16_t len;
+					bx::read(&reader, len);
+
+					std::string material;
+					material.resize(len);
+					bx::read(&reader, const_cast<char*>(material.c_str() ), len);
+
+					uint16_t num;
+					bx::read(&reader, num);
+
+					for (uint32_t ii = 0; ii < num; ++ii)
+					{
+						bx::read(&reader, len);
+
+						std::string name;
+						name.resize(len);
+						bx::read(&reader, const_cast<char*>(name.c_str() ), len);
+
+						Primitive prim;
+						bx::read(&reader, prim.m_startIndex);
+						bx::read(&reader, prim.m_numIndices);
+						bx::read(&reader, prim.m_startVertex);
+						bx::read(&reader, prim.m_numVertices);
+						bx::read(&reader, prim.m_sphere);
+						bx::read(&reader, prim.m_aabb);
+						bx::read(&reader, prim.m_obb);
+
+						group.m_prims.push_back(prim);
+					}
+
+					m_groups.push_back(group);
+					group.reset();
+				}
+				break;
+
+			default:
+				DBG("%08x at %d", chunk, reader.seek() );
+				break;
+			}
+		}
+
+		reader.close();
+	}
+
+	void unload()
+	{
+		for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
+		{
+			const Group& group = *it;
+			bgfx::destroyVertexBuffer(group.m_vbh);
+
+			if (bgfx::isValid(group.m_ibh) )
+			{
+				bgfx::destroyIndexBuffer(group.m_ibh);
+			}
+		}
+		m_groups.clear();
+	}
+
+	void submit(uint8_t _view, bgfx::ProgramHandle _program, float* _mtx)
+	{
+		for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
+		{
+			const Group& group = *it;
+
+			// Set uniforms.
+			s_uniforms.submitPerDrawUniforms();
+
+			// Set model matrix for rendering.
+			bgfx::setTransform(_mtx);
+			bgfx::setProgram(_program);
+			bgfx::setIndexBuffer(group.m_ibh);
+			bgfx::setVertexBuffer(group.m_vbh);
+
+			// 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_CULL_CCW
+				| BGFX_STATE_MSAA
+				);
+
+			// Submit primitive for rendering to view 0.
+			bgfx::submit(_view);
+		}
+	}
+
+	bgfx::VertexDecl m_decl;
+	typedef std::vector<Group> GroupArray;
+	GroupArray m_groups;
+};
+
+struct PosColorTexCoord0Vertex
+{
+	float m_x;
+	float m_y;
+	float m_z;
+	uint32_t m_rgba;
+	float m_u;
+	float m_v;
+
+	static void init()
+	{
+		ms_decl.begin();
+		ms_decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
+		ms_decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
+		ms_decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
+		ms_decl.end();
+	}
+
+	static bgfx::VertexDecl ms_decl;
+};
+
+bgfx::VertexDecl PosColorTexCoord0Vertex::ms_decl;
+
+void screenSpaceQuad(float _textureWidth, float _textureHeight, bool _originBottomLeft = false, float _width = 1.0f, float _height = 1.0f)
+{
+	if (bgfx::checkAvailTransientVertexBuffer(3, PosColorTexCoord0Vertex::ms_decl) )
+	{
+		bgfx::TransientVertexBuffer vb;
+		bgfx::allocTransientVertexBuffer(&vb, 3, PosColorTexCoord0Vertex::ms_decl);
+		PosColorTexCoord0Vertex* vertex = (PosColorTexCoord0Vertex*)vb.data;
+
+		const float zz = 0.0f;
+
+		const float minx = -_width;
+		const float maxx =  _width;
+		const float miny = 0.0f;
+		const float maxy = _height*2.0f;
+
+		const float texelHalfW = s_texelHalf/_textureWidth;
+		const float texelHalfH = s_texelHalf/_textureHeight;
+		const float minu = -1.0f + texelHalfW;
+		const float maxu =  1.0f + texelHalfW;
+
+		float minv = texelHalfH;
+		float maxv = 2.0f + texelHalfH;
+
+		if (_originBottomLeft)
+		{
+			std::swap(minv, maxv);
+			minv -= 1.0f;
+			maxv -= 1.0f;
+		}
+
+		vertex[0].m_x = minx;
+		vertex[0].m_y = miny;
+		vertex[0].m_z = zz;
+		vertex[0].m_rgba = 0xffffffff;
+		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_rgba = 0xffffffff;
+		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_rgba = 0xffffffff;
+		vertex[2].m_u = maxu;
+		vertex[2].m_v = maxv;
+
+		bgfx::setVertexBuffer(&vb);
+	}
+}
+
+void mtxScaleRotateTranslate(float* _result
+							, const float _scaleX
+							, const float _scaleY
+							, const float _scaleZ
+							, const float _rotX
+							, const float _rotY
+							, const float _rotZ
+							, const float _translateX
+							, const float _translateY
+							, const float _translateZ
+							)
+{
+	float mtxRotateTranslate[16];
+	float mtxScale[16];
+
+	mtxRotateXYZ(mtxRotateTranslate, _rotX, _rotY, _rotZ);
+	mtxRotateTranslate[12] = _translateX;
+	mtxRotateTranslate[13] = _translateY;
+	mtxRotateTranslate[14] = _translateZ;
+
+	memset(mtxScale, 0, sizeof(float)*16);
+	mtxScale[0]  = _scaleX;
+	mtxScale[5]  = _scaleY;
+	mtxScale[10] = _scaleZ;
+	mtxScale[15] = 1.0f;
+
+	mtxMul(_result, mtxScale, mtxRotateTranslate);
+}
+
+void imguiBool(const char* _str, bool& _flag, bool _enabled = true)
+{
+	if (imguiCheck(_str, _flag, _enabled) )
+	{
+		_flag = !_flag;
+	}
+}
+
+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 views  clear state.
+	bgfx::setViewClear(0
+		, BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT
+		, 0x303030ff
+		, 1.0f
+		, 0
+		);
+
+	// Setup root path for binary shaders. Shader binaries are different
+	// for each renderer.
+	switch (bgfx::getRendererType() )
+	{
+	default:
+	case bgfx::RendererType::Direct3D9:
+		s_shaderPath = "shaders/dx9/";
+		break;
+
+	case bgfx::RendererType::Direct3D11:
+		s_shaderPath = "shaders/dx11/";
+		break;
+
+	case bgfx::RendererType::OpenGL:
+		s_shaderPath = "shaders/glsl/";
+		s_flipV = true;
+		break;
+
+	case bgfx::RendererType::OpenGLES2:
+	case bgfx::RendererType::OpenGLES3:
+		s_shaderPath = "shaders/gles/";
+		s_flipV = true;
+		break;
+	}
+
+	// Imgui.
+	FILE* file = fopen("font/droidsans.ttf", "rb");
+	uint32_t size = (uint32_t)fsize(file);
+	void* data = malloc(size);
+	size_t ignore = fread(data, 1, size, file);
+	BX_UNUSED(ignore);
+	fclose(file);
+	imguiCreate(data, size);
+
+	// Uniforms.
+	s_uniforms.init();
+
+	// Vertex declarations.
+	PosColorTexCoord0Vertex::init();
+
+	struct LightProbe
+	{
+		void load(const char* _name)
+		{
+			const uint32_t texFlags = BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP|BGFX_TEXTURE_W_CLAMP;
+			char filePath[512];
+
+			strcpy(filePath, _name);
+			strcat(filePath, "_lod.dds");
+			m_tex = bgfx::createTexture(loadTexture(filePath), texFlags);
+
+			strcpy(filePath, _name);
+			strcat(filePath, "_irr.dds");
+			m_texIrr = bgfx::createTexture(loadTexture(filePath), texFlags);
+		}
+
+		void destroy()
+		{
+			bgfx::destroyTexture(m_tex);
+			bgfx::destroyTexture(m_texIrr);
+		}
+
+		bgfx::TextureHandle m_tex;
+		bgfx::TextureHandle m_texIrr;
+	};
+
+	enum LightProbes
+	{
+		LPWells,
+		LPUffizi,
+		LPPisa,
+		LPEnnis,
+		LPGrace,
+
+		LPCount
+	};
+
+	LightProbe lightProbes[LPCount];
+	lightProbes[LPWells].load("wells");
+	lightProbes[LPUffizi].load("uffizi");
+	lightProbes[LPPisa].load("pisa");
+	lightProbes[LPEnnis].load("ennis");
+	lightProbes[LPGrace].load("grace");
+	uint8_t currentLightProbe = LPWells;
+
+	bgfx::UniformHandle u_time   = bgfx::createUniform("u_time",   bgfx::UniformType::Uniform1f);
+	bgfx::UniformHandle u_mtx    = bgfx::createUniform("u_mtx",    bgfx::UniformType::Uniform4x4fv);
+	bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Uniform4fv);
+	bgfx::UniformHandle u_flags  = bgfx::createUniform("u_flags",  bgfx::UniformType::Uniform4fv);
+	bgfx::UniformHandle u_camPos = bgfx::createUniform("u_camPos", bgfx::UniformType::Uniform3fv);
+
+	bgfx::UniformHandle u_texCube    = bgfx::createUniform("u_texCube",    bgfx::UniformType::Uniform1i);
+	bgfx::UniformHandle u_texCubeIrr = bgfx::createUniform("u_texCubeIrr", bgfx::UniformType::Uniform1i);
+
+	bgfx::UniformHandle u_texAlbedo    = bgfx::createUniform("u_texAlbedo",    bgfx::UniformType::Uniform1i);
+	bgfx::UniformHandle u_texNormal    = bgfx::createUniform("u_texNormal",    bgfx::UniformType::Uniform1i);
+	bgfx::UniformHandle u_texSpecular  = bgfx::createUniform("u_texSpecular",  bgfx::UniformType::Uniform1i);
+	bgfx::UniformHandle u_texRoughness = bgfx::createUniform("u_texRoughness", bgfx::UniformType::Uniform1i);
+
+	bgfx::ProgramHandle programMesh = loadProgram("vs_ibl_mesh",   "fs_ibl_mesh");
+	bgfx::ProgramHandle programSky  = loadProgram("vs_ibl_skybox", "fs_ibl_skybox");
+
+	Mesh meshBunny;
+	meshBunny.load("meshes/bunny.bin");
+
+	struct Settings
+	{
+		float m_speed;
+		float m_glossiness;
+		float m_exposure;
+		float m_diffspec;
+		float m_rgbDiff[3];
+		float m_rgbSpec[3];
+		bool m_diffuse;
+		bool m_specular;
+		bool m_diffuseIbl;
+		bool m_specularIbl;
+		bool m_singleSliderDiff;
+		bool m_singleSliderSpec;
+	};
+
+	Settings settings;
+	settings.m_speed = 0.37f;
+	settings.m_glossiness = 1.0f;
+	settings.m_exposure = 0.0f;
+	settings.m_diffspec = 0.65f;
+	settings.m_rgbDiff[0] = 0.2f;
+	settings.m_rgbDiff[1] = 0.2f;
+	settings.m_rgbDiff[2] = 0.2f;
+	settings.m_rgbSpec[0] = 1.0f;
+	settings.m_rgbSpec[1] = 1.0f;
+	settings.m_rgbSpec[2] = 1.0f;
+	settings.m_diffuse = true;
+	settings.m_specular = true;
+	settings.m_diffuseIbl = true;
+	settings.m_specularIbl = true;
+	settings.m_singleSliderDiff = false;
+	settings.m_singleSliderSpec = false;
+
+	float time = 0.0f;
+
+	s_uniforms.submitConstUniforms();
+
+	entry::MouseState mouseState;
+	while (!entry::processEvents(width, height, debug, reset, &mouseState) )
+	{
+		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
+			);
+
+		static int32_t rightScrollArea = 0;
+		imguiBeginScrollArea("Settings", width - 256 - 10, 10, 256, 426, &rightScrollArea);
+
+		imguiLabel("Shade:");
+		imguiSeparator();
+		imguiBool("Diffuse",      settings.m_diffuse);
+		imguiBool("Specular",     settings.m_specular);
+		imguiBool("IBL Diffuse",  settings.m_diffuseIbl);
+		imguiBool("IBL Specular", settings.m_specularIbl);
+
+		imguiSeparatorLine();
+		imguiSlider("Speed", &settings.m_speed, 0.0f, 1.0f, 0.01f);
+
+		imguiSeparatorLine();
+		imguiLabel("Environment:");
+		currentLightProbe = imguiChoose(currentLightProbe
+									   , "Wells"
+									   , "Uffizi"
+									   , "Pisa"
+									   , "Ennis"
+									   , "Grace"
+									   );
+
+		imguiSeparator();
+		imguiSlider("Exposure", &settings.m_exposure, -8.0f, 8.0f, 0.01f);
+		imguiEndScrollArea();
+
+		static int32_t leftScrollArea = 0;
+		imguiBeginScrollArea("Settings", 10, 70, 256, 576, &leftScrollArea);
+
+		imguiLabel("Material properties:");
+		imguiSeparator();
+		imguiSlider("Diffuse - Specular", &settings.m_diffspec,   0.0f, 1.0f, 0.01f);
+		imguiSlider("Glossiness"        , &settings.m_glossiness, 0.0f, 1.0f, 0.01f);
+
+		imguiSeparatorLine();
+		imguiLabel("Diffuse color:");
+		imguiSeparator();
+		imguiBool("Single slider", settings.m_singleSliderDiff);
+		if (settings.m_singleSliderDiff)
+		{
+			imguiSlider("RGB:", &settings.m_rgbDiff[0], 0.0f, 1.0f, 0.01f);
+			settings.m_rgbDiff[1] = settings.m_rgbDiff[0];
+			settings.m_rgbDiff[2] = settings.m_rgbDiff[0];
+
+		}
+		else
+		{
+			imguiSlider("R:", &settings.m_rgbDiff[0], 0.0f, 1.0f, 0.01f);
+			imguiSlider("G:", &settings.m_rgbDiff[1], 0.0f, 1.0f, 0.01f);
+			imguiSlider("B:", &settings.m_rgbDiff[2], 0.0f, 1.0f, 0.01f);
+		}
+
+		imguiSeparatorLine();
+		imguiLabel("Specular color:");
+		imguiSeparator();
+		imguiBool("Single slider", settings.m_singleSliderSpec);
+		if (settings.m_singleSliderSpec)
+		{
+			imguiSlider("RGB:", &settings.m_rgbSpec[0], 0.0f, 1.0f, 0.01f);
+			settings.m_rgbSpec[1] = settings.m_rgbSpec[0];
+			settings.m_rgbSpec[2] = settings.m_rgbSpec[0];
+
+		}
+		else
+		{
+			imguiSlider("R:", &settings.m_rgbSpec[0], 0.0f, 1.0f, 0.01f);
+			imguiSlider("G:", &settings.m_rgbSpec[1], 0.0f, 1.0f, 0.01f);
+			imguiSlider("B:", &settings.m_rgbSpec[2], 0.0f, 1.0f, 0.01f);
+		}
+
+		imguiSeparatorLine();
+		imguiLabel("Predefined materials:");
+		imguiSeparator();
+
+		if (imguiButton("Gold") )
+		{
+			settings.m_glossiness = 0.8f;
+			settings.m_diffspec   = 1.0f;
+
+			settings.m_rgbDiff[0] = 0.0f;
+			settings.m_rgbDiff[1] = 0.0f;
+			settings.m_rgbDiff[2] = 0.0f;
+
+			settings.m_rgbSpec[0] = 1.0f;
+			settings.m_rgbSpec[1] = 0.86f;
+			settings.m_rgbSpec[2] = 0.58f;
+
+			settings.m_singleSliderSpec = false;
+		}
+
+		if (imguiButton("Copper") )
+		{
+			settings.m_glossiness = 0.67f;
+			settings.m_diffspec   = 1.0f;
+
+			settings.m_rgbDiff[0] = 0.0f;
+			settings.m_rgbDiff[1] = 0.0f;
+			settings.m_rgbDiff[2] = 0.0f;
+
+			settings.m_rgbSpec[0] = 0.98f;
+			settings.m_rgbSpec[1] = 0.82f;
+			settings.m_rgbSpec[2] = 0.76f;
+
+			settings.m_singleSliderSpec = false;
+		}
+
+		if (imguiButton("Titanium") )
+		{
+			settings.m_glossiness = 0.57f;
+			settings.m_diffspec   = 1.0f;
+
+			settings.m_rgbDiff[0] = 0.0f;
+			settings.m_rgbDiff[1] = 0.0f;
+			settings.m_rgbDiff[2] = 0.0f;
+
+			settings.m_rgbSpec[0] = 0.76f;
+			settings.m_rgbSpec[1] = 0.73f;
+			settings.m_rgbSpec[2] = 0.71f;
+
+			settings.m_singleSliderSpec = false;
+		}
+
+		if (imguiButton("Steel") )
+		{
+			settings.m_glossiness = 0.82f;
+			settings.m_diffspec   = 1.0f;
+
+			settings.m_rgbDiff[0] = 0.0f;
+			settings.m_rgbDiff[1] = 0.0f;
+			settings.m_rgbDiff[2] = 0.0f;
+
+			settings.m_rgbSpec[0] = 0.77f;
+			settings.m_rgbSpec[1] = 0.78f;
+			settings.m_rgbSpec[2] = 0.77f;
+
+			settings.m_singleSliderSpec = false;
+		}
+
+		imguiEndScrollArea();
+		imguiEndFrame();
+
+		s_uniforms.m_glossiness = settings.m_glossiness;
+		s_uniforms.m_exposure = settings.m_exposure;
+		s_uniforms.m_diffspec = settings.m_diffspec;
+		s_uniforms.m_flags[0] = float(settings.m_diffuse);
+		s_uniforms.m_flags[1] = float(settings.m_specular);
+		s_uniforms.m_flags[2] = float(settings.m_diffuseIbl);
+		s_uniforms.m_flags[3] = float(settings.m_specularIbl);
+		memcpy(s_uniforms.m_rgbDiff, settings.m_rgbDiff, 3*sizeof(float));
+		memcpy(s_uniforms.m_rgbSpec, settings.m_rgbSpec, 3*sizeof(float));
+
+		s_uniforms.submitPerFrameUniforms();
+
+		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;
+
+		time += (float)(frameTime*settings.m_speed/freq);
+		s_uniforms.m_time = time;
+
+		// Use debug font to print information about this example.
+		bgfx::dbgTextClear();
+		bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/18-ibl");
+		bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Image based lightning.");
+		bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
+
+		float at[3] = { 0.0f, 0.0f, 0.0f };
+		float eye[3] = { 0.0f, 0.0f, -3.0f };
+
+		mtxRotateXY(s_uniforms.m_mtx
+			, 0.0f
+			, time
+			);
+
+		float view[16];
+		float proj[16];
+
+		mtxIdentity(view);
+		mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
+		bgfx::setViewTransform(0, view, proj);
+
+		mtxLookAt(view, eye, at);
+		memcpy(s_uniforms.m_camPos, eye, 3*sizeof(float));
+		mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
+		bgfx::setViewTransform(1, view, proj);
+
+		bgfx::setViewRect(0, 0, 0, width, height);
+		bgfx::setViewRect(1, 0, 0, width, height);
+
+		// View 0.
+		bgfx::setTexture(4, u_texCube, lightProbes[currentLightProbe].m_tex);
+		bgfx::setProgram(programSky);
+		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
+		screenSpaceQuad( (float)width, (float)height, true);
+		bgfx::submit(0);
+
+		// View 1.
+		float mtx[16];
+		mtxScaleRotateTranslate(mtx
+				, 1.0f
+				, 1.0f
+				, 1.0f
+				, 0.0f
+				, (float(M_PI))+time
+				, 0.0f
+				, 0.0f
+				, -1.0f
+				, 0.0f
+				);
+
+		bgfx::setTexture(4, u_texCube,    lightProbes[currentLightProbe].m_tex);
+		bgfx::setTexture(5, u_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
+		meshBunny.submit(1, programMesh, mtx);
+
+		// Advance to next frame. Rendering thread will be kicked to
+		// process submitted rendering primitives.
+		bgfx::frame();
+	}
+
+	meshBunny.unload();
+
+	// Cleanup.
+	bgfx::destroyProgram(programMesh);
+	bgfx::destroyProgram(programSky);
+
+	bgfx::destroyUniform(u_camPos);
+	bgfx::destroyUniform(u_flags);
+	bgfx::destroyUniform(u_params);
+	bgfx::destroyUniform(u_mtx);
+	bgfx::destroyUniform(u_time);
+
+	bgfx::destroyUniform(u_texRoughness);
+	bgfx::destroyUniform(u_texSpecular);
+	bgfx::destroyUniform(u_texNormal);
+	bgfx::destroyUniform(u_texAlbedo);
+
+	bgfx::destroyUniform(u_texCube);
+	bgfx::destroyUniform(u_texCubeIrr);
+
+	for (uint8_t ii = 0; ii < LPCount; ++ii)
+	{
+		lightProbes[ii].destroy();
+	}
+
+	s_uniforms.destroy();
+
+	imguiDestroy();
+
+	// Shutdown bgfx.
+	bgfx::shutdown();
+
+	return 0;
+}

+ 17 - 0
examples/18-ibl/makefile

@@ -0,0 +1,17 @@
+#
+# Copyright 2014 Dario Manesku. 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

+ 7 - 0
examples/18-ibl/varying.def.sc

@@ -0,0 +1,7 @@
+vec3 v_normal    : NORMAL    = vec3(0.0, 0.0, 1.0);
+vec3 v_dir       : TEXCOORD1 = vec3(0.0, 0.0, 0.0);
+vec3 v_view      : TEXCOORD2 = vec3(0.0, 0.0, 0.0);
+
+vec3 a_position  : POSITION;
+vec2 a_texcoord0 : TEXCOORD0;
+vec3 a_normal    : NORMAL;

+ 20 - 0
examples/18-ibl/vs_ibl_mesh.sc

@@ -0,0 +1,20 @@
+$input a_position, a_normal
+$output v_view, v_normal
+
+/*
+ * Copyright 2014 Dario Manesku. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+uniform vec3 u_camPos;
+
+void main()
+{
+	gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
+
+	vec3 normal = a_normal * 2.0 - 1.0;
+	v_normal = mul(u_model[0], vec4(normal, 0.0) ).xyz;
+	v_view = normalize(u_camPos - mul(u_model[0], vec4(a_position, 1.0)).xyz);
+}

+ 19 - 0
examples/18-ibl/vs_ibl_skybox.sc

@@ -0,0 +1,19 @@
+$input a_position, a_texcoord0
+$output v_dir
+
+/*
+ * Copyright 2014 Dario Manesku. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "../common/common.sh"
+
+uniform mat4 u_mtx;
+
+void main()
+{
+	gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
+
+	vec2 tex = 2.0 * a_texcoord0 - 1.0;
+	v_dir = mul(u_mtx, vec4(tex, 1.0, 0.0) ).xyz;
+}

+ 1 - 1
examples/common/entry/entry.cpp

@@ -197,7 +197,7 @@ namespace entry
 						const MouseEvent* mouse = static_cast<const MouseEvent*>(ev);
 
 						//TODO: move this from here.
-						cameraSetMouseState(mouse->m_mx, mouse->m_my, mouse->m_down, mouse->m_move);
+						cameraSetMouseState(mouse->m_mx, mouse->m_my, mouse->m_down && MouseButton::Right == mouse->m_button, mouse->m_move);
 
 						if (mouse->m_move)
 						{

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


BIN
examples/runtime/textures/ennis_irr.dds


BIN
examples/runtime/textures/ennis_lod.dds


BIN
examples/runtime/textures/grace_irr.dds


BIN
examples/runtime/textures/grace_lod.dds


BIN
examples/runtime/textures/pisa_irr.dds


BIN
examples/runtime/textures/pisa_lod.dds


BIN
examples/runtime/textures/uffizi_irr.dds


BIN
examples/runtime/textures/uffizi_lod.dds


BIN
examples/runtime/textures/wells_irr.dds


BIN
examples/runtime/textures/wells_lod.dds


+ 1 - 0
premake/premake4.lua

@@ -165,6 +165,7 @@ exampleProject("14-shadowvolumes",     "d7eb4bcc-37bc-11e3-b7a4-e46428d43830")
 exampleProject("15-shadowmaps-simple", "a10f22ab-e0ee-471a-b2b6-2f6cb1c63fdc")
 exampleProject("16-shadowmaps",        "f9a91cb0-7b1b-11e3-981f-0800200c9a66")
 exampleProject("17-drawstress",        "9aeea4c6-80dc-11e3-b3ca-4da6db0f677b")
+exampleProject("18-ibl",               "711bcbb0-9531-11e3-a5e2-0800200c9a66")
 
 dofile "makedisttex.lua"
 dofile "shaderc.lua"