Przeglądaj źródła

Added HDR rendering with eye adaption (automatic exposure)

-Added HDR rendering with automatic exposure (eye adaption). Toggleable and adjustable. Engine now supports high dynamic range within a scene and can adjust the exposure based on the brightness of visible pixels. This eliminates problems with areas that are too dark and lights that are too bright.
-Added reinhard and filmic tone mapping.
-Added support in the renderer (backend) for Shader Storage Buffer Objects, modified Uniform Updater to check for them.
-Added shaders and base classes for a gaussian blur pass (not yet being used).
-Added uniform support for delta time in the shaders.
-Modified renderer and command buffer to accept a wider range of GPU buffers. Now it does not care if it's a uniform or shader storage buffer.
Paulcodedev 7 lat temu
rodzic
commit
c9fa5c45fa
51 zmienionych plików z 806 dodań i 170 usunięć
  1. 10 4
      .gitignore
  2. BIN
      Builds/x64/Debug 64bit/FreeImage.dll
  3. BIN
      Builds/x64/Debug 64bit/SDL2.dll
  4. BIN
      Builds/x64/Debug 64bit/assimp.dll
  5. BIN
      Builds/x64/Debug 64bit/glew32.dll
  6. BIN
      Builds/x64/Debug 64bit/tbb.dll
  7. BIN
      Builds/x64/Debug 64bit/tbb_debug.dll
  8. BIN
      Builds/x64/Release 64bit/FreeImage.dll
  9. BIN
      Builds/x64/Release 64bit/SDL2.dll
  10. BIN
      Builds/x64/Release 64bit/assimp.dll
  11. BIN
      Builds/x64/Release 64bit/glew32.dll
  12. BIN
      Builds/x64/Release 64bit/tbb.dll
  13. 1 1
      Praxis3D/Data/Maps/default.pmap
  14. 3 3
      Praxis3D/Data/Maps/default_lite.pmap
  15. 43 0
      Praxis3D/Data/Shaders/exposurePass.frag
  16. 10 0
      Praxis3D/Data/Shaders/exposurePass.vert
  17. 96 9
      Praxis3D/Data/Shaders/finalPass.frag
  18. 44 0
      Praxis3D/Data/Shaders/finalPass.vert
  19. 40 0
      Praxis3D/Data/Shaders/gaussianBlurHorizontal.frag
  20. 29 0
      Praxis3D/Data/Shaders/gaussianBlurHorizontal.vert
  21. 40 0
      Praxis3D/Data/Shaders/gaussianBlurVertical.frag
  22. 29 0
      Praxis3D/Data/Shaders/gaussianBlurVertical.vert
  23. 1 0
      Praxis3D/Data/config.ini
  24. 25 24
      Praxis3D/Praxis3D.vcxproj
  25. 26 40
      Praxis3D/Praxis3D.vcxproj.filters
  26. BIN
      Praxis3D/Praxis3D1.rc
  27. BIN
      Praxis3D/RCa08000
  28. 86 0
      Praxis3D/Source/BlurPass.h
  29. 1 1
      Praxis3D/Source/CommandBuffer.h
  30. 13 6
      Praxis3D/Source/CommonDefinitions.h
  31. 9 1
      Praxis3D/Source/Config.cpp
  32. 23 0
      Praxis3D/Source/Config.h
  33. 1 1
      Praxis3D/Source/DeferredRenderer.cpp
  34. 30 5
      Praxis3D/Source/FinalPass.h
  35. 10 4
      Praxis3D/Source/GeometryBuffer.cpp
  36. 15 0
      Praxis3D/Source/GeometryBuffer.h
  37. 2 0
      Praxis3D/Source/GeometryPass.h
  38. 12 2
      Praxis3D/Source/GraphicsDataSets.h
  39. 8 3
      Praxis3D/Source/LightingPass.h
  40. 2 0
      Praxis3D/Source/ReflectionPass.h
  41. 1 0
      Praxis3D/Source/RenderPassBase.h
  42. 1 0
      Praxis3D/Source/RendererBackend.h
  43. 25 4
      Praxis3D/Source/RendererFrontend.cpp
  44. 7 6
      Praxis3D/Source/RendererFrontend.h
  45. 1 53
      Praxis3D/Source/ShaderLoader.h
  46. 27 1
      Praxis3D/Source/ShaderUniformUpdater.cpp
  47. 19 1
      Praxis3D/Source/ShaderUniformUpdater.h
  48. 96 1
      Praxis3D/Source/ShaderUniforms.h
  49. 4 0
      Praxis3D/Source/UniformData.h
  50. BIN
      Praxis3D/icon1.ico
  51. 16 0
      Praxis3D/resource1.h

+ 10 - 4
.gitignore

@@ -3,10 +3,16 @@ VC/
 
 VC x64/
 
-x64/
+\.vs/
 
-Release/
+Builds/x32/
 
-Debug/
+Builds/x64/Debug/
 
-Praxis3D/Data/Models/
+Builds/x64/Debug 64bit/lnk\{4EFA342B-62AB-4145-8CAE-43C91978D51E}\.tmp
+
+Builds/x64/Release 64bit/Praxis3D\.iobj
+
+Builds/x64/Release 64bit/Praxis3D\.ipdb
+
+*.dae

BIN
Builds/x64/Debug 64bit/FreeImage.dll


BIN
Builds/x64/Debug 64bit/SDL2.dll


BIN
Builds/x64/Debug 64bit/assimp.dll


BIN
Builds/x64/Debug 64bit/glew32.dll


BIN
Builds/x64/Debug 64bit/tbb.dll


BIN
Builds/x64/Debug 64bit/tbb_debug.dll


BIN
Builds/x64/Release 64bit/FreeImage.dll


BIN
Builds/x64/Release 64bit/SDL2.dll


BIN
Builds/x64/Release 64bit/assimp.dll


BIN
Builds/x64/Release 64bit/glew32.dll


BIN
Builds/x64/Release 64bit/tbb.dll


+ 1 - 1
Praxis3D/Data/Maps/default.pmap

@@ -434,7 +434,7 @@
 					"Name": "DirectionalLight 1",
 					"Color": "1.0, 1.0, 1.0",
 					"Direction": "0.0, 0.25, 1.0",
-					"Intensity": "10.1"
+					"Intensity": "1.1"
 				},
 				{
 					"Type": "PointLight",

+ 3 - 3
Praxis3D/Data/Maps/default_lite.pmap

@@ -707,7 +707,7 @@
 					"Name": "PointLight 1",
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
-					"Intensity": "100.0f",
+					"Intensity": "10.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"Position": "-19.2421f, 10.0f, 5.45328f"
 				},
@@ -716,7 +716,7 @@
 					"Name": "PointLight 2",
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
-					"Intensity": "100.0f",
+					"Intensity": "10.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"Position": "9.12898f, 7.98369f, 9.59357f"
 				},
@@ -725,7 +725,7 @@
 					"Name": "PointLight 3",
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
-					"Intensity": "100.0f",
+					"Intensity": "10.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"Position": "-6.94746f, 8.59811f, 7.54629f"
 				},

+ 43 - 0
Praxis3D/Data/Shaders/exposurePass.frag

@@ -0,0 +1,43 @@
+#version 430 core
+
+//#define ENABLE_TONE_MAPPING
+
+out vec4 outputColor;
+
+uniform sampler2D finalColorMap;
+uniform ivec2 screenSize;
+uniform float gamma;
+
+#ifdef ENABLE_TONE_MAPPING
+vec3 simpleToneMapping(vec3 p_color, float p_gamma)
+{
+    return pow(exp(-1.0 / (2.72 * p_color + 0.15)), vec3(1.0 / p_gamma));
+}
+#endif
+
+vec2 calcTexCoord(void)
+{
+    return gl_FragCoord.xy / screenSize;
+}
+
+void main(void)
+{
+	float mipmapLevel = textureQueryLod(myTexture, textureCoord).x;
+    fragColor = textureLod(myTexture, textureCoord, mipmapLevel);
+
+	// Calculate screen-space texture coordinates, for buffer access
+	vec2 texCoord = calcTexCoord();
+	
+	// Perform gamma correction on the color from the final framebuffer
+	vec3 color = pow(texture(finalColorMap, texCoord).xyz, vec3(1.0 / gamma));
+	
+	#ifdef ENABLE_TONE_MAPPING
+	// Perform simple tonemapping on the final color
+	color = simpleToneMapping(color, gamma);
+	#endif
+	
+	color = color / (color + vec3(1.0));
+	
+	// Write the color to the default framebuffer
+	outputColor = vec4(color, 1.0);
+}

+ 10 - 0
Praxis3D/Data/Shaders/exposurePass.vert

@@ -0,0 +1,10 @@
+#version 430 core
+
+void main(void) 
+{
+	// Determine texture coordinates
+	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	
+	// Calculate the position, so that the triangle fills the whole screen
+	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);
+}

+ 96 - 9
Praxis3D/Data/Shaders/finalPass.frag

@@ -1,6 +1,15 @@
 #version 430 core
 
-//#define ENABLE_TONE_MAPPING
+//#define ENABLE_SIMPLE_TONE_MAPPING
+//#define ENABLE_REINHARD_TONE_MAPPING
+#define ENABLE_FILMIC_TONE_MAPPING
+
+#define AVG_INTENDED_BRIGHTNESS 0.5
+#define MIN_INTENDED_BRIGHTNESS 0.005
+#define MAX_INTENDED_BRIGHTNESS 5.0
+
+
+in float avgBrightness;
 
 out vec4 outputColor;
 
@@ -8,12 +17,47 @@ uniform sampler2D finalColorMap;
 uniform ivec2 screenSize;
 uniform float gamma;
 
-#ifdef ENABLE_TONE_MAPPING
-vec3 simpleToneMapping(vec3 p_color, float p_gamma)
+// Averages RGB color into a single brightness value
+float averageColors(vec3 p_color)
+{
+	return (p_color.x + p_color.y + p_color.z) / 3.0;
+}
+
+vec3 gammaCorrection(vec3 p_color, float p_gamma)
+{
+	return pow(p_color, vec3(1.0 / p_gamma));
+}
+
+// Adjusts an RGB color based on the average brightness (exposure)
+// by making overall brightness match the average intended brightness (AVG_INTENDED_BRIGHTNESS)
+vec3 brightnessMapping(vec3 p_color, float p_exposure)
+{
+	return p_color * clamp(AVG_INTENDED_BRIGHTNESS / p_exposure, MIN_INTENDED_BRIGHTNESS, MAX_INTENDED_BRIGHTNESS);
+}
+
+vec3 simpleToneMapping(vec3 p_color)
+{
+    return exp(-1.0 / (2.72 * p_color + 0.15));
+}
+
+// Simple reinhard tone mapping
+vec3 reinhardToneMapping(vec3 p_color)
 {
-    return pow(exp(-1.0 / (2.72 * p_color + 0.15)), vec3(1.0 / p_gamma));
+	return p_color / (p_color + vec3(1.0));
+}
+	
+// Filmic tone mapping using an algorithm created by John Hable for Uncharted 2
+vec3 filmicToneMapping(vec3 p_color)
+{
+	float A = 0.15;
+	float B = 0.50;
+	float C = 0.10;
+	float D = 0.20;
+	float E = 0.02;
+	float F = 0.30;
+
+	return ((p_color*(A*p_color+C*B)+D*E)/(p_color*(A*p_color+B)+D*F))-E/F;
 }
-#endif
 
 vec2 calcTexCoord(void)
 {
@@ -26,14 +70,57 @@ void main(void)
 	vec2 texCoord = calcTexCoord();
 	
 	// Perform gamma correction on the color from the final framebuffer
-	vec3 color = pow(texture(finalColorMap, texCoord).xyz, vec3(1.0 / gamma));
+	vec3 color = texture(finalColorMap, texCoord).xyz;
+		
+	// Adjust the fragment brightness based on average
+	color = brightnessMapping(color, avgBrightness);
 	
 	#ifdef ENABLE_TONE_MAPPING
 	// Perform simple tonemapping on the final color
-	color = simpleToneMapping(color, gamma);
+	color = simpleToneMapping(color);
 	#endif
 	
+	#ifdef ENABLE_REINHARD_TONE_MAPPING
+	// Perform reinhard tonemapping on the final color
+	color = reinhardToneMapping(color);
+	#endif
+	
+	#ifdef ENABLE_FILMIC_TONE_MAPPING
+	// Perform filmic tonemapping on the final color
+	color = filmicToneMapping(color);
+	#endif
+	
+	// Perform gamma correction as the last step of the fragment color
+	color = gammaCorrection(color, gamma);
+	
 	// Write the color to the default framebuffer
-	//outputColor = vec4(1.0, 0.0, 0.0, 1.0);
 	outputColor = vec4(color, 1.0);
-}
+}
+
+	//vec3 filmicToneMapping2(vec3 p_fragmentColor)
+	//{
+	//float3 texColor = tex2D(Texture0, texCoord ); // Tex Read
+	// Filmic Curve
+	//vec3 color = max(vec3(0.0), p_fragmentColor - 0.004); 
+	//vec3 retColor = (color * (6.2 * color + .5)) / (color * (6.2 * color + 1.7) + 0.06);
+	//return retColor;
+	//}
+	//vec3 color = pow(texture(finalColorMap, texCoord).xyz, vec3(1.0 / gamma));
+	//vec3 lumVec = textureLod(finalColorMap, texCoord, exposureMipmapLevel).xyz;
+	//float lum = (lumVec.x + lumVec.y + lumVec.z) / 3.0;
+	//lum = max(lumVec.x, max(lumVec.y, lumVec.z));
+	//float lum = lumVec.x;
+	//color = pow(uncharted2Tonemap(color), vec3(1.0 / gamma));
+	//color = uncharted2Tonemap(color);
+    // Exposure tone mapping
+    //color = vec3(1.0) - exp(-color * min(1.0 - lum, 0.5));
+    //color = vec3(1.0) - exp(-color * (0.5 / max(lum, 0.2)));
+	//color = vec3(0.5) / lum;
+	//color = color * (1.0 / max(lum, 1.0));
+	//color = color * clamp(0.5 / lum, 0.05, 5.0);
+	//color = color / (color + vec3(1.0));
+    //color = vec3(1.0) - exp(-color * (0.5 / lum));
+	//color = color / max(lum, 1.0);
+	//color = color / lum;
+	//color = filmicToneMapping(color);
+	//color = color * clamp(0.5 / lum, 0.05, 5.0);

+ 44 - 0
Praxis3D/Data/Shaders/finalPass.vert

@@ -1,7 +1,51 @@
 #version 430 core
 
+#define ENABLE_HDR
+
+layout(std430, binding = 0) buffer HDRBuffer
+{
+	float screenBrightness;
+};
+ 
+out float avgBrightness;
+
+uniform float eyeAdaptionRate;
+uniform float deltaTimeS;
+uniform ivec2 screenSize;
+uniform sampler2D finalColorMap;
+
+// Calculates the maximum texture mipmap level
+float calcMaxMipmapLevel(vec2 p_textureSize)
+{
+	return 1 + floor(log2(max(p_textureSize.x, p_textureSize.y)));
+}
+
+// Averages RGB color into a single brightness value
+float averageColors(vec3 p_color)
+{
+	return (p_color.x + p_color.y + p_color.z) / 3.0;
+}
+
 void main(void) 
 {
+	#ifdef ENABLE_HDR
+	
+	// Get maximum mipmap level (1x1) of a framebuffer
+	float exposureMipmapLevel = calcMaxMipmapLevel(screenSize);
+	// Get the current (previous frame) average brightness
+	float avgBrightnessPrevFrame = averageColors(textureLod(finalColorMap, vec2(0.0), exposureMipmapLevel).xyz);
+	// Perform a linear interpolation between current and previous brightness based on delta time
+	screenBrightness = mix(screenBrightness, avgBrightnessPrevFrame, deltaTimeS * eyeAdaptionRate);
+	// Send average brightness to the fragment shader
+	avgBrightness = screenBrightness;
+	
+	#else
+	
+	// Set the average brightness to 0.5 so it does not affect the scene
+	avgBrightness = 0.5;
+	
+	#endif
+	
 	// Determine texture coordinates
 	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
 	

+ 40 - 0
Praxis3D/Data/Shaders/gaussianBlurHorizontal.frag

@@ -0,0 +1,40 @@
+#version 430 core
+//precision mediump float;
+
+in vec2 blurTexCoords[14];
+
+out vec4 outputColor;
+
+uniform sampler2D blurTexture;
+uniform ivec2 screenSize;
+ 
+vec2 calcTexCoord(void)
+{
+    return gl_FragCoord.xy / screenSize;
+}
+
+void main(void)
+{
+	// Calculate screen-space texture coordinates, for buffer access
+	vec2 texCoord = calcTexCoord();
+	
+    vec3 fragColor = vec3(0.0);
+	
+    fragColor += texture(blurMap, blurTexCoords[ 0]).xyz * 0.0044299121055113265;
+    fragColor += texture(blurMap, blurTexCoords[ 1]).xyz * 0.00895781211794;
+    fragColor += texture(blurMap, blurTexCoords[ 2]).xyz * 0.0215963866053;
+    fragColor += texture(blurMap, blurTexCoords[ 3]).xyz * 0.0443683338718;
+    fragColor += texture(blurMap, blurTexCoords[ 4]).xyz * 0.0776744219933;
+    fragColor += texture(blurMap, blurTexCoords[ 5]).xyz * 0.115876621105;
+    fragColor += texture(blurMap, blurTexCoords[ 6]).xyz * 0.147308056121;
+    fragColor += texture(blurMap, texCoord         ).xyz * 0.259576912161;
+    fragColor += texture(blurMap, blurTexCoords[ 7]).xyz * 0.147308056121;
+    fragColor += texture(blurMap, blurTexCoords[ 8]).xyz * 0.115876621105;
+    fragColor += texture(blurMap, blurTexCoords[ 9]).xyz * 0.0776744219933;
+    fragColor += texture(blurMap, blurTexCoords[10]).xyz * 0.0443683338718;
+    fragColor += texture(blurMap, blurTexCoords[11]).xyz * 0.0215963866053;
+    fragColor += texture(blurMap, blurTexCoords[12]).xyz * 0.00895781211794;
+    fragColor += texture(blurMap, blurTexCoords[13]).xyz * 0.0044299121055113265;
+	
+	outputColor = vec4(fragColor, 1.0);
+}

+ 29 - 0
Praxis3D/Data/Shaders/gaussianBlurHorizontal.vert

@@ -0,0 +1,29 @@
+#version 430 core
+
+out vec2 blurTexCoords[14];
+
+uniform float blurOffset;
+
+void main(void)
+{
+    blurTexCoords[ 0] = texCoord + vec2(-0.028*blurOffset, 0.0);
+    blurTexCoords[ 1] = texCoord + vec2(-0.024*blurOffset, 0.0);
+    blurTexCoords[ 2] = texCoord + vec2(-0.020*blurOffset, 0.0);
+    blurTexCoords[ 3] = texCoord + vec2(-0.016*blurOffset, 0.0);
+    blurTexCoords[ 4] = texCoord + vec2(-0.012*blurOffset, 0.0);
+    blurTexCoords[ 5] = texCoord + vec2(-0.008*blurOffset, 0.0);
+    blurTexCoords[ 6] = texCoord + vec2(-0.004*blurOffset, 0.0);
+    blurTexCoords[ 7] = texCoord + vec2( 0.004*blurOffset, 0.0);
+    blurTexCoords[ 8] = texCoord + vec2( 0.008*blurOffset, 0.0);
+    blurTexCoords[ 9] = texCoord + vec2( 0.012*blurOffset, 0.0);
+    blurTexCoords[10] = texCoord + vec2( 0.016*blurOffset, 0.0);
+    blurTexCoords[11] = texCoord + vec2( 0.020*blurOffset, 0.0);
+    blurTexCoords[12] = texCoord + vec2( 0.024*blurOffset, 0.0);
+    blurTexCoords[13] = texCoord + vec2( 0.028*blurOffset, 0.0);
+	
+	// Determine texture coordinates
+	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	
+	// Calculate the position, so that the triangle fills the whole screen
+	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);
+}

+ 40 - 0
Praxis3D/Data/Shaders/gaussianBlurVertical.frag

@@ -0,0 +1,40 @@
+#version 430 core
+//precision mediump float;
+
+in vec2 blurTexCoords[14];
+
+out vec4 outputColor;
+
+uniform sampler2D emissiveTexture;
+uniform ivec2 screenSize;
+
+vec2 calcTexCoord(void)
+{
+    return gl_FragCoord.xy / screenSize;
+}
+
+void main(void)
+{
+	// Calculate screen-space texture coordinates, for buffer access
+	vec2 texCoord = calcTexCoord();
+	
+    vec3 fragColor = vec3(0.0);
+	
+    fragColor += texture(emissiveMap, blurTexCoords[ 0]).xyz * 0.0044299121055113265;
+    fragColor += texture(emissiveMap, blurTexCoords[ 1]).xyz * 0.00895781211794;
+    fragColor += texture(emissiveMap, blurTexCoords[ 2]).xyz * 0.0215963866053;
+    fragColor += texture(emissiveMap, blurTexCoords[ 3]).xyz * 0.0443683338718;
+    fragColor += texture(emissiveMap, blurTexCoords[ 4]).xyz * 0.0776744219933;
+    fragColor += texture(emissiveMap, blurTexCoords[ 5]).xyz * 0.115876621105;
+    fragColor += texture(emissiveMap, blurTexCoords[ 6]).xyz * 0.147308056121;
+    fragColor += texture(emissiveMap, texCoord         ).xyz * 0.259576912161;
+    fragColor += texture(emissiveMap, blurTexCoords[ 7]).xyz * 0.147308056121;
+    fragColor += texture(emissiveMap, blurTexCoords[ 8]).xyz * 0.115876621105;
+    fragColor += texture(emissiveMap, blurTexCoords[ 9]).xyz * 0.0776744219933;
+    fragColor += texture(emissiveMap, blurTexCoords[10]).xyz * 0.0443683338718;
+    fragColor += texture(emissiveMap, blurTexCoords[11]).xyz * 0.0215963866053;
+    fragColor += texture(emissiveMap, blurTexCoords[12]).xyz * 0.00895781211794;
+    fragColor += texture(emissiveMap, blurTexCoords[13]).xyz * 0.0044299121055113265;
+	
+	outputColor = vec4(fragColor, 1.0);
+}

+ 29 - 0
Praxis3D/Data/Shaders/gaussianBlurVertical.vert

@@ -0,0 +1,29 @@
+#version 430 core
+
+out vec2 blurTexCoords[14];
+
+uniform float blurOffset;
+
+void main(void)
+{
+    blurTexCoords[ 0] = texCoord + vec2(0.0, -0.028*blurOffset);
+    blurTexCoords[ 1] = texCoord + vec2(0.0, -0.024*blurOffset);
+    blurTexCoords[ 2] = texCoord + vec2(0.0, -0.020*blurOffset);
+    blurTexCoords[ 3] = texCoord + vec2(0.0, -0.016*blurOffset);
+    blurTexCoords[ 4] = texCoord + vec2(0.0, -0.012*blurOffset);
+    blurTexCoords[ 5] = texCoord + vec2(0.0, -0.008*blurOffset);
+    blurTexCoords[ 6] = texCoord + vec2(0.0, -0.004*blurOffset);
+    blurTexCoords[ 7] = texCoord + vec2(0.0,  0.004*blurOffset);
+    blurTexCoords[ 8] = texCoord + vec2(0.0,  0.008*blurOffset);
+    blurTexCoords[ 9] = texCoord + vec2(0.0,  0.012*blurOffset);
+    blurTexCoords[10] = texCoord + vec2(0.0,  0.016*blurOffset);
+    blurTexCoords[11] = texCoord + vec2(0.0,  0.020*blurOffset);
+    blurTexCoords[12] = texCoord + vec2(0.0,  0.024*blurOffset);
+    blurTexCoords[13] = texCoord + vec2(0.0,  0.028*blurOffset);
+	
+	// Determine texture coordinates
+	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	
+	// Calculate the position, so that the triangle fills the whole screen
+	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);
+}

+ 1 - 0
Praxis3D/Data/config.ini

@@ -14,6 +14,7 @@ generate_mipmaps 1
 gl_texture_anisotropy 16
 camera_freelook_speed 25
 face_culling 1
+eye_adaption 1
 fov 80
 z_near 0.1
 z_far 40000

+ 25 - 24
Praxis3D/Praxis3D.vcxproj

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug 64bit|Win32">
       <Configuration>Debug 64bit</Configuration>
@@ -37,58 +37,58 @@
   <PropertyGroup Label="Globals">
     <ProjectGuid>{A97875DA-A9E8-4B91-928C-8F0CE88581B9}</ProjectGuid>
     <RootNamespace>Praxis3D</RootNamespace>
-    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 64bit|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 64bit|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 64bit|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 64bit|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v141</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
@@ -141,18 +141,22 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <IncludePath>$(SolutionDir)\VC\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)\VC\lib;$(LibraryPath)</LibraryPath>
+    <OutDir>$(SolutionDir)\Builds\$(Platform)\$(Configuration)\</OutDir>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 64bit|x64'">
     <IncludePath>$(SolutionDir)\VC x64\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)\VC x64\lib;$(LibraryPath)</LibraryPath>
+    <OutDir>$(SolutionDir)\Builds\$(Platform)\$(Configuration)\</OutDir>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <IncludePath>$(SolutionDir)\VC\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)\VC\lib;$(LibraryPath)</LibraryPath>
+    <OutDir>$(SolutionDir)\Builds\$(Platform)\$(Configuration)\</OutDir>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 64bit|x64'">
     <IncludePath>$(SolutionDir)\VC x64\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)\VC x64\lib;$(LibraryPath)</LibraryPath>
+    <OutDir>$(SolutionDir)\Builds\$(Platform)\$(Configuration)\</OutDir>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
@@ -199,6 +203,7 @@
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
       <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -278,6 +283,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp" />
+    <ClCompile Include="Source\BaseGraphicsObjects.cpp" />
     <ClCompile Include="Source\ChangeController.cpp" />
     <ClCompile Include="Source\ClockLocator.cpp" />
     <ClCompile Include="Source\Config.cpp" />
@@ -294,6 +300,7 @@
     <ClCompile Include="Source\Math.cpp" />
     <ClCompile Include="Source\ModelLoader.cpp" />
     <ClCompile Include="Source\NullSystemObjects.cpp" />
+    <ClCompile Include="Source\ObjectDirectorycpp.cpp" />
     <ClCompile Include="Source\ObserverBase.cpp" />
     <ClCompile Include="Source\PlayState.cpp" />
     <ClCompile Include="Source\PropertyLoader.cpp" />
@@ -313,6 +320,7 @@
     <ClCompile Include="Source\ShaderLoader.cpp" />
     <ClCompile Include="Source\ShaderUniformUpdater.cpp" />
     <ClCompile Include="Source\SpinWait.cpp" />
+    <ClCompile Include="Source\System.cpp" />
     <ClCompile Include="Source\TaskManager.cpp" />
     <ClCompile Include="Source\TaskManagerLocator.cpp" />
     <ClCompile Include="Source\TaskScheduler.cpp" />
@@ -324,13 +332,16 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="resource.h" />
+    <ClInclude Include="resource1.h" />
     <ClInclude Include="Source\BaseGraphicsObjects.h" />
     <ClInclude Include="Source\BaseScriptObject.h" />
+    <ClInclude Include="Source\BlurPass.h" />
     <ClInclude Include="Source\CameraGraphicsObject.h" />
     <ClInclude Include="Source\CameraScript.h" />
     <ClInclude Include="Source\ChangeController.h" />
     <ClInclude Include="Source\Clock.h" />
     <ClInclude Include="Source\ClockLocator.h" />
+    <ClInclude Include="Source\CommandBuffer.h" />
     <ClInclude Include="Source\CommonDefinitions.h" />
     <ClInclude Include="Source\Config.h" />
     <ClInclude Include="Source\ConfigLoader.h" />
@@ -360,6 +371,7 @@
     <ClInclude Include="Source\ModelLoader.h" />
     <ClInclude Include="Source\ModelGraphicsObjects.h" />
     <ClInclude Include="Source\NullSystemObjects.h" />
+    <ClInclude Include="Source\ObjectDirectory.h" />
     <ClInclude Include="Source\ObjectPool.h" />
     <ClInclude Include="Source\ObserverBase.h" />
     <ClInclude Include="Source\PlayState.h" />
@@ -400,27 +412,16 @@
     <ClInclude Include="Source\WorldEditState.h" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="ClassDiagram.cd" />
     <None Include="Data\config.ini" />
     <None Include="Data\error-strings-eng.data" />
-    <None Include="Data\Shaders\geomBillboard.pfrag" />
-    <None Include="Data\Shaders\geomBillboard.pgeom" />
-    <None Include="Data\Shaders\geomBillboard.pvert" />
-    <None Include="Data\Shaders\geometryPass.pfrag" />
-    <None Include="Data\Shaders\geometryPass.pvert" />
-    <None Include="Data\Shaders\lightPass.pfrag" />
-    <None Include="Data\Shaders\lightPass.pvert" />
-    <None Include="Data\Shaders\test.pfrag" />
-    <None Include="Data\Shaders\test.pvert" />
-    <None Include="Data\Shaders\test2.pfrag" />
-    <None Include="Data\Shaders\test2.pvert" />
-    <None Include="Data\Shaders\test3.pfrag" />
-    <None Include="Data\Shaders\test3.pvert" />
   </ItemGroup>
   <ItemGroup>
-    <ResourceCompile Include="Praxis3D.rc" />
+    <ResourceCompile Include="Praxis3D1.rc" />
   </ItemGroup>
   <ItemGroup>
     <Image Include="..\praxis icon.ico" />
+    <Image Include="icon1.ico" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 26 - 40
Praxis3D/Praxis3D.vcxproj.filters

@@ -249,6 +249,15 @@
     <ClCompile Include="Source\RendererFrontend.cpp">
       <Filter>Renderer\Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BaseGraphicsObjects.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\ObjectDirectorycpp.cpp">
+      <Filter>Service Locators\Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\System.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Source\ErrorCodes.h">
@@ -476,56 +485,33 @@
     <ClInclude Include="Source\ReflectionPass.h">
       <Filter>Renderer\Render Passes\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\CommandBuffer.h">
+      <Filter>Renderer\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\ObjectDirectory.h">
+      <Filter>Service Locators\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="resource1.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\BlurPass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <None Include="Data\Shaders\geomBillboard.pfrag">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\geomBillboard.pgeom">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\geomBillboard.pvert">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\geometryPass.pfrag">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\geometryPass.pvert">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\lightPass.pfrag">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\lightPass.pvert">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\test.pfrag">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\test.pvert">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\test2.pfrag">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\test2.pvert">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\test3.pfrag">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
-    <None Include="Data\Shaders\test3.pvert">
-      <Filter>Shaders\Shader Files</Filter>
-    </None>
     <None Include="Data\config.ini" />
     <None Include="Data\error-strings-eng.data" />
+    <None Include="ClassDiagram.cd" />
   </ItemGroup>
   <ItemGroup>
-    <ResourceCompile Include="Praxis3D.rc">
+    <ResourceCompile Include="Praxis3D1.rc">
       <Filter>Resource Files</Filter>
     </ResourceCompile>
   </ItemGroup>
   <ItemGroup>
+    <Image Include="icon1.ico">
+      <Filter>Resource Files</Filter>
+    </Image>
     <Image Include="..\praxis icon.ico">
       <Filter>Resource Files</Filter>
     </Image>

BIN
Praxis3D/Praxis3D1.rc


BIN
Praxis3D/RCa08000


+ 86 - 0
Praxis3D/Source/BlurPass.h

@@ -0,0 +1,86 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class BlurPass : public RenderPass
+{
+public:
+	BlurPass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer) { }
+
+	~BlurPass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError;
+
+		m_name = "Blur Rendering Pass";
+		
+		// Create a property-set used to load blur vertical shaders
+		PropertySet blurVerticalShaderProperties(Properties::Shaders);
+		blurVerticalShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().gaussian_blur_vertical_vert_shader);
+		blurVerticalShaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().gaussian_blur_vertical_frag_shader);
+
+		// Create a property-set used to load blur horizontal shaders
+		PropertySet blurHorizontalShaderProperties(Properties::Shaders);
+		blurHorizontalShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().gaussian_blur_horizontal_vert_shader);
+		blurHorizontalShaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().gaussian_blur_horizontal_frag_shader);
+
+		// Create shaders
+		m_blurVerticalShader = Loaders::shader().load(blurVerticalShaderProperties);
+		m_blurHorizontalShader = Loaders::shader().load(blurHorizontalShaderProperties);
+
+		//		 _______________________________
+		//		|	LOAD BLUR VERTICAL SHADER	|
+		//		|_______________________________|
+		shaderError = m_blurVerticalShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)					// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_blurVerticalShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+
+		//		 _______________________________
+		//		|	LOAD BLUR HORIZONTAL SHADER	|
+		//		|_______________________________|
+		shaderError = m_blurHorizontalShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)						// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_blurHorizontalShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+		
+		return returnError;
+	}
+
+	void update(const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	{
+		// Set the default framebuffer to be drawn to
+		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
+
+		// Bind emissive texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive);
+
+		// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferBlur);
+
+		// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
+		m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.passScreenSpaceDrawCommandsToBackend();
+
+
+		// Bind intermediate blur texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferBlur);
+
+		// Bind emissive texture for writing to, so the second pass populates it with the final blur result
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferBlur);
+
+		// Perform horizontal blur. Queue and render a full screen quad using a horizontal blur shader
+		m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.passScreenSpaceDrawCommandsToBackend();
+	}
+
+private:
+	ShaderLoader::ShaderProgram	*m_blurVerticalShader,
+								*m_blurHorizontalShader;
+};

+ 1 - 1
Praxis3D/Source/CommandBuffer.h

@@ -153,7 +153,7 @@ public:
 				queueForLoading(p_objectData.m_materials[matType][i]);
 	}
 
-	inline void queueForUpdate(RendererFrontend::LightUniformBuffer &p_lightBuffer)
+	inline void queueForUpdate(RendererFrontend::ShaderBuffer &p_lightBuffer)
 	{
 		// Calculate the sort key
 		RendererBackend::DrawCommands::value_type::first_type sortKey = 0;

+ 13 - 6
Praxis3D/Source/CommonDefinitions.h

@@ -17,9 +17,10 @@ enum CommandType : unsigned int
 
 enum BufferType : unsigned int
 {
-	BufferType_Uniform		= GL_UNIFORM_BUFFER,
-	BufferType_Array		= GL_ARRAY_BUFFER,
-	BufferType_ElementArray = GL_ELEMENT_ARRAY_BUFFER
+	BufferType_Uniform			= GL_UNIFORM_BUFFER,
+	BufferType_Array			= GL_ARRAY_BUFFER,
+	BufferType_ElementArray		= GL_ELEMENT_ARRAY_BUFFER,
+	BufferType_ShaderStorage	= GL_SHADER_STORAGE_BUFFER
 };
 enum BufferUpdateType : unsigned int
 {
@@ -28,15 +29,20 @@ enum BufferUpdateType : unsigned int
 };
 enum BufferUsageHint : unsigned int
 {
-	BufferUsageHint_Stream  = GL_STREAM_DRAW,
-	BufferUsageHint_Static  = GL_STATIC_DRAW,
-	BufferUsageHint_Dynamic = GL_DYNAMIC_DRAW
+	BufferUsageHint_StreamDraw		= GL_STREAM_DRAW,
+	BufferUsageHint_StaticDraw		= GL_STATIC_DRAW,
+	BufferUsageHint_DynamicDraw		= GL_DYNAMIC_DRAW,
+	BufferUsageHint_DynamicCopy		= GL_DYNAMIC_COPY
 };
 enum LightBufferBinding : unsigned int
 {
 	LightBufferBinding_PointLight = 0,
 	LightBufferBinding_SpotLight
 };
+enum SSBOBinding : unsigned int
+{
+	SSBOBinding_HDR = 0
+};
 enum LoadObjectType : unsigned int
 {
 	LoadObject_Buffer,
@@ -62,6 +68,7 @@ enum MaterialType : unsigned int
 	MaterialType_Roughness = MaterialType_NumOfTypes,
 	MaterialType_Metalness,
 	MaterialType_Height,
+	MaterialType_Blur,
 	MaterialType_AmbientOcclusion,
 	MaterialType_NumOfTypes_Extended
 };

+ 9 - 1
Praxis3D/Source/Config.cpp

@@ -103,6 +103,7 @@ void Config::init()
 
 	// Graphics variables
 	AddVariablePredef(m_graphicsVar, double_buffering);
+	AddVariablePredef(m_graphicsVar, eye_adaption);
 	AddVariablePredef(m_graphicsVar, multisampling);
 	AddVariablePredef(m_graphicsVar, alpha_size);
 	AddVariablePredef(m_graphicsVar, dir_shadow_res_x);
@@ -113,6 +114,7 @@ void Config::init()
 	AddVariablePredef(m_graphicsVar, multisample_samples);
 	AddVariablePredef(m_graphicsVar, alpha_threshold);
 	AddVariablePredef(m_graphicsVar, emissive_threshold);
+	AddVariablePredef(m_graphicsVar, eye_adaption_rate);
 	AddVariablePredef(m_graphicsVar, fog_color_x);
 	AddVariablePredef(m_graphicsVar, fog_color_y);
 	AddVariablePredef(m_graphicsVar, fog_color_z);
@@ -214,7 +216,9 @@ void Config::init()
 	AddVariablePredef(m_rendererVar, gaussian_blur_vertical_frag_shader);
 	AddVariablePredef(m_rendererVar, gaussian_blur_vertical_vert_shader);
 	AddVariablePredef(m_rendererVar, gaussian_blur_horizontal_frag_shader);
-	AddVariablePredef(m_rendererVar, gaussian_blur_horizontal_vert_shader);
+	AddVariablePredef(m_rendererVar, gaussian_blur_horizontal_vert_shader); 
+	AddVariablePredef(m_rendererVar, blur_pass_vert_shader);
+	AddVariablePredef(m_rendererVar, blur_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, light_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, light_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, final_pass_vert_shader);
@@ -246,6 +250,8 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, modelViewMatUniform);
 	AddVariablePredef(m_shaderVar, modelViewProjectionMatUniform);
 	AddVariablePredef(m_shaderVar, screenSizeUniform);
+	AddVariablePredef(m_shaderVar, deltaTimeMSUniform);
+	AddVariablePredef(m_shaderVar, deltaTimeSUniform);
 	AddVariablePredef(m_shaderVar, elapsedTimeUniform);
 	AddVariablePredef(m_shaderVar, gammaUniform);
 	AddVariablePredef(m_shaderVar, alphaCullingUniform);
@@ -289,6 +295,8 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, fogColorUniform);
 	AddVariablePredef(m_shaderVar, billboardScaleUniform);
 	AddVariablePredef(m_shaderVar, depthTypeUniform);
+	AddVariablePredef(m_shaderVar, eyeAdaptionRate);
+	AddVariablePredef(m_shaderVar, HDRSSBuffer);
 	AddVariablePredef(m_shaderVar, testMatUniform);
 	AddVariablePredef(m_shaderVar, testVecUniform);
 	AddVariablePredef(m_shaderVar, testFloatUniform);

+ 23 - 0
Praxis3D/Source/Config.h

@@ -381,6 +381,7 @@ class Config
 	friend class DebugUIScript;
 	friend class DeferredRenderer;
 	friend class ErrorHandler;
+	friend class RendererFrontend;
 	friend class Window;
 public:
 	struct ConfigFileVariables
@@ -467,6 +468,7 @@ public:
 			gl_blur_buffer_wrap_s_method = GL_CLAMP_TO_EDGE;
 			gl_blur_buffer_wrap_t_method = GL_CLAMP_TO_EDGE;
 
+			gl_final_buffer_min_filter_HDR = GL_NEAREST_MIPMAP_NEAREST;
 			gl_final_buffer_min_filter = GL_NEAREST;
 			gl_final_buffer_mag_filter = GL_NEAREST;
 			gl_final_buffer_s_method = GL_CLAMP_TO_EDGE;
@@ -515,6 +517,7 @@ public:
 		int gl_blur_buffer_wrap_s_method;
 		int gl_blur_buffer_wrap_t_method;
 
+		float gl_final_buffer_min_filter_HDR;
 		float gl_final_buffer_min_filter;
 		float gl_final_buffer_mag_filter;
 		int gl_final_buffer_s_method;
@@ -536,6 +539,7 @@ public:
 		GraphicsVariables()
 		{
 			double_buffering = true;
+			eye_adaption = true;
 			multisampling = true;
 			alpha_size = 8;
 			current_resolution_x = 0;
@@ -550,6 +554,7 @@ public:
 			rendering_res_y = 900;
 			alpha_threshold = 0.0f;
 			emissive_threshold = 0.3f;
+			eye_adaption_rate = 1.0f;
 			fog_color_x = 0.55f;
 			fog_color_y = 0.55f;
 			fog_color_z = 0.55f;
@@ -569,6 +574,7 @@ public:
 		}
 
 		bool double_buffering;
+		bool eye_adaption;
 		bool multisampling;
 		int alpha_size;
 		int current_resolution_x;
@@ -583,6 +589,7 @@ public:
 		int rendering_res_y;
 		float alpha_threshold;
 		float emissive_threshold;
+		float eye_adaption_rate;
 		float fog_color_x;
 		float fog_color_y;
 		float fog_color_z;
@@ -762,6 +769,8 @@ public:
 			gaussian_blur_vertical_vert_shader = "gaussianBlurVertical.vert";
 			gaussian_blur_horizontal_frag_shader = "gaussianBlurHorizontal.frag";
 			gaussian_blur_horizontal_vert_shader = "gaussianBlurHorizontal.vert";
+			blur_pass_vert_shader = "blurPass.vert";
+			blur_pass_frag_shader = "blurPass.frag";
 			light_pass_vert_shader = "lightPass.vert";
 			light_pass_frag_shader = "lightPass.frag";
 			final_pass_vert_shader = "finalPass.vert";
@@ -806,6 +815,8 @@ public:
 		std::string gaussian_blur_vertical_vert_shader;
 		std::string gaussian_blur_horizontal_frag_shader;
 		std::string gaussian_blur_horizontal_vert_shader;
+		std::string blur_pass_vert_shader;
+		std::string blur_pass_frag_shader;
 		std::string light_pass_vert_shader;
 		std::string light_pass_frag_shader;
 		std::string final_pass_vert_shader;
@@ -840,6 +851,8 @@ public:
 			modelViewMatUniform = "modelViewMat";
 			modelViewProjectionMatUniform = "MVP";
 			screenSizeUniform = "screenSize";
+			deltaTimeMSUniform = "deltaTimeMS";
+			deltaTimeSUniform = "deltaTimeS";
 			elapsedTimeUniform = "elapsedTime";
 			gammaUniform = "gamma";
 			alphaCullingUniform = "alphaCulling";
@@ -882,6 +895,7 @@ public:
 			normalTextureUniform = "normalTexture";
 			specularTextureUniform = "specularTexture";
 			emissiveTextureUniform = "emissiveTexture";
+			blurTextureUniform = "blurTexture";
 			glossTextureUniform = "glossTexture";
 			heightTextureUniform = "heightTexture";
 			combinedTextureUniform = "combinedTexture";
@@ -894,6 +908,9 @@ public:
 			billboardScaleUniform = "billboardScale";
 			depthTypeUniform = "depthType";
 
+			eyeAdaptionRate = "eyeAdaptionRate";
+			HDRSSBuffer = "HDRBuffer";
+
 			testMatUniform = "testMat";
 			testVecUniform = "testVec";
 			testFloatUniform = "testFloat";
@@ -906,6 +923,8 @@ public:
 		std::string modelViewMatUniform;
 		std::string modelViewProjectionMatUniform;
 		std::string screenSizeUniform;
+		std::string deltaTimeMSUniform;
+		std::string deltaTimeSUniform;
 		std::string elapsedTimeUniform;
 		std::string gammaUniform;
 		std::string alphaCullingUniform;
@@ -948,6 +967,7 @@ public:
 		std::string normalTextureUniform;
 		std::string specularTextureUniform;
 		std::string emissiveTextureUniform;
+		std::string blurTextureUniform;
 		std::string glossTextureUniform;
 		std::string heightTextureUniform;
 		std::string combinedTextureUniform;
@@ -960,6 +980,9 @@ public:
 		std::string billboardScaleUniform;
 		std::string depthTypeUniform;
 
+		std::string eyeAdaptionRate;
+		std::string HDRSSBuffer;
+
 		std::string testMatUniform;
 		std::string testVecUniform;
 		std::string testFloatUniform;

+ 1 - 1
Praxis3D/Source/DeferredRenderer.cpp

@@ -30,7 +30,7 @@ DeferredRenderer::~DeferredRenderer()
 ErrorCode DeferredRenderer::init()
 {
 	ErrorCode returnCode = ErrorCode::Success;
-
+	
 	// Get the current screen size
 	m_screenSize.x = Config::graphicsVar().current_resolution_x;
 	m_screenSize.y = Config::graphicsVar().current_resolution_y;

+ 30 - 5
Praxis3D/Source/FinalPass.h

@@ -1,11 +1,16 @@
 #pragma once
 
+#include "GraphicsDataSets.h"
 #include "RenderPassBase.h"
 
 class FinalPass : public RenderPass
 {
 public:
-	FinalPass(RendererFrontend &p_renderer) : RenderPass(p_renderer) { }
+	FinalPass(RendererFrontend &p_renderer) : 
+		RenderPass(p_renderer),
+		m_HDRSSBuffer(BufferType_ShaderStorage, BufferUsageHint_DynamicCopy) { }
+
+	~FinalPass() { }
 
 	ErrorCode init()
 	{
@@ -13,6 +18,14 @@ public:
 
 		m_name = "Final Rendering Pass";
 		
+		// SetHDR binding index
+		m_HDRSSBuffer.m_bindingIndex = SSBOBinding_HDR;
+		
+		m_HDRSSBuffer.m_data = &m_HDRDataSet;
+
+		// Set the HDR buffer size
+		m_HDRSSBuffer.m_size = sizeof(HDRDataSet);
+
 		// Create a property-set used to load geometry shader
 		PropertySet finalShaderProperties(Properties::Shaders);
 		finalShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().final_pass_vert_shader);
@@ -30,6 +43,9 @@ public:
 			m_renderer.queueForLoading(*m_shaderFinalPass);
 		}
 
+		// Queue HDR buffer to be created
+		m_renderer.queueForLoading(m_HDRSSBuffer);
+
 		return returnError;
 	}
 
@@ -53,9 +69,13 @@ public:
 
 		glDisable(GL_DEPTH_TEST);
 
-		// Bind final framebuffer
-		//glActiveTexture(GL_TEXTURE0 + GeometryBuffer::GBufferFinal);
-		//glBindTexture(GL_TEXTURE_2D, GeometryBuffer::GBufferFinal);
+		if(Config::graphicsVar().eye_adaption)
+		{
+			// Generate mipmaps for the final buffer, for use in tone mapping
+			m_renderer.m_backend.getGeometryBuffer()->generateMipmap(GeometryBuffer::GBufferFinal);
+		}
+
+		// Bind final texture for reading so it can be accessed in the shaders
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal);
 
 		// Set the default framebuffer to be drawn to
@@ -64,11 +84,16 @@ public:
 
 #endif // SETTING_USE_BLIT_FRAMEBUFFER
 
+		// Queue and render a full screen quad using a final pass shader
 		m_renderer.queueForDrawing(m_shaderFinalPass->getShaderHandle(), m_shaderFinalPass->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
-
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 	}
 
 private:
 	ShaderLoader::ShaderProgram	*m_shaderFinalPass;
+
+	HDRDataSet m_HDRDataSet;
+
+	// HDR shader storage buffer
+	RendererFrontend::ShaderBuffer m_HDRSSBuffer;
 };

+ 10 - 4
Praxis3D/Source/GeometryBuffer.cpp

@@ -109,10 +109,14 @@ ErrorCode GeometryBuffer::init()
 		glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
 		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_final_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0, 
 					 Config::FramebfrVariables().gl_final_buffer_texture_format, Config::FramebfrVariables().gl_final_buffer_texture_type, NULL);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Config::FramebfrVariables().gl_final_buffer_min_filter);
+		// If eye adaption (HDR) is enabled, buffer should use a different min_filter (to support mipmapping)
+		if(Config::graphicsVar().eye_adaption)
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Config::FramebfrVariables().gl_final_buffer_min_filter);
+		else
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Config::FramebfrVariables().gl_final_buffer_min_filter_HDR);
 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Config::FramebfrVariables().gl_final_buffer_mag_filter);
 		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBufferFinal, GL_TEXTURE_2D, m_finalBuffer, 0);
-
+		
 		// Check for errors and return an error in case of one
 		m_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 		if(m_status != GL_FRAMEBUFFER_COMPLETE)
@@ -120,6 +124,8 @@ ErrorCode GeometryBuffer::init()
 
 		// Restore the default FBO, so it doesn't get changed from the outside of the class
 		//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
+		glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
 	}
 	return returnCode;
 }
@@ -175,7 +181,7 @@ void GeometryBuffer::setBufferSize(GLuint p_buffer, unsigned int p_bufferWidth,
 		case GBufferFinal:
 			// Resize depth buffer
 			glBindTexture(GL_TEXTURE_2D, m_depthBuffer);
-			glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_depth_buffer_internal_format, p_bufferWidth, p_bufferHeight, 0, 
+			glTexImage2D(GL_TEXTURE_2D, 10, Config::FramebfrVariables().gl_depth_buffer_internal_format, p_bufferWidth, p_bufferHeight, 0, 
 						 Config::FramebfrVariables().gl_depth_buffer_texture_format, Config::FramebfrVariables().gl_depth_buffer_texture_type, NULL);
 			
 			// Resize the final buffer
@@ -243,7 +249,7 @@ void GeometryBuffer::initFinalPass()
 	// Bind final framebuffer
 	glActiveTexture(GL_TEXTURE0 + GBufferFinal);
 	glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
-
+	
 	// Set the default framebuffer to be drawn to
 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 

+ 15 - 0
Praxis3D/Source/GeometryBuffer.h

@@ -42,6 +42,7 @@ public:
 	virtual void initLightPass();		// Bind buffers from geometry pass so they can be accessed when rendering lights
 	virtual void initFinalPass();		// Bind the final buffer to 'read from' and the default screen buffer to 'write to'
 	
+	// Buffer binding functions
 	inline void bindBufferForReading(GBufferTextureType p_buffer, int p_activeTexture)
 	{
 		glActiveTexture(GL_TEXTURE0 + p_activeTexture);
@@ -95,6 +96,7 @@ public:
 		glDrawBuffers((GLsizei)p_buffers.size(), p_buffers.data() );
 	}
 	
+	// Framebuffer binding functions
 	inline void bindFramebufferForReading(GBufferFramebufferType p_framebufferType)
 	{
 		switch(p_framebufferType)
@@ -120,6 +122,19 @@ public:
 		}
 	}
 
+	// Generates mipmaps for the texture inside the gbuffer
+	inline void generateMipmap(GBufferTextureType p_buffer)
+	{
+		glActiveTexture(GL_TEXTURE0);
+
+		// Bind the supplied texture
+		glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
+
+		// Generate mipmaps
+		glGenerateMipmap(GL_TEXTURE_2D);
+	}
+
+	// Getters
 	inline GLenum getBufferLocation(GBufferTextureType p_buffer)
 	{
 		return GL_COLOR_ATTACHMENT0 + p_buffer;

+ 2 - 0
Praxis3D/Source/GeometryPass.h

@@ -7,6 +7,8 @@ class GeometryPass : public RenderPass
 public:
 	GeometryPass(RendererFrontend &p_renderer) : RenderPass(p_renderer) { }
 
+	~GeometryPass() { }
+
 	ErrorCode init()
 	{
 		ErrorCode returnError;

+ 12 - 2
Praxis3D/Source/GraphicsDataSets.h

@@ -46,9 +46,9 @@ struct RenderableObjectData
 
 //	 ===========================================================================================================
 //	|												WARNING:													|
-//	|				The layout of light data sets below are order-sensitive. Do not edit.						|
+//	|					The layout of data sets below are order-sensitive. Do not edit.							|
 //	|																											|
-//	| Their member variables are arranged by the order of buffer offsets used in light pass shader.				|
+//	|		Their member variables are arranged by the order of buffer offsets used in shaders.					|
 //	| Editing their location would break the synchronization, since these structs are put into buffers as is.	|
 //	 ===========================================================================================================
 
@@ -97,4 +97,14 @@ struct SpotLightDataSet
 	Math::Vec3f m_attenuation;
 	float m_intensity;
 	float m_cutoffAngle;
+};
+
+struct HDRDataSet
+{
+	HDRDataSet()
+	{
+		m_screenBrightness = 0.5f;
+	}
+
+	float m_screenBrightness;
 };

+ 8 - 3
Praxis3D/Source/LightingPass.h

@@ -5,7 +5,12 @@
 class LightingPass : public RenderPass
 {
 public:
-	LightingPass(RendererFrontend &p_renderer) : RenderPass(p_renderer) { }
+	LightingPass(RendererFrontend &p_renderer) : 
+		RenderPass(p_renderer), 
+		m_pointLightBuffer(BufferType_Uniform, BufferUsageHint_DynamicDraw),
+		m_spotLightBuffer(BufferType_Uniform, BufferUsageHint_DynamicDraw) { }
+
+	~LightingPass() { }
 
 	ErrorCode init()
 	{
@@ -90,6 +95,6 @@ private:
 	std::vector<GeometryBuffer::GBufferTexture> m_emissiveAndFinalBuffers;
 
 	// Light buffers
-	RendererFrontend::LightUniformBuffer m_pointLightBuffer, 
-										 m_spotLightBuffer;
+	RendererFrontend::ShaderBuffer	m_pointLightBuffer, 
+									m_spotLightBuffer;
 };

+ 2 - 0
Praxis3D/Source/ReflectionPass.h

@@ -7,6 +7,8 @@ class ReflectionPass : public RenderPass
 public:
 	ReflectionPass(RendererFrontend &p_renderer) : RenderPass(p_renderer) { }
 
+	~ReflectionPass() { }
+
 	ErrorCode init()
 	{
 		ErrorCode returnError;

+ 1 - 0
Praxis3D/Source/RenderPassBase.h

@@ -8,6 +8,7 @@ class RenderPass
 {
 public:
 	RenderPass(RendererFrontend &p_renderer) : m_renderer(p_renderer) { }
+	virtual ~RenderPass() { }
 
 	virtual ErrorCode init() = 0;
 

+ 1 - 0
Praxis3D/Source/RendererBackend.h

@@ -739,6 +739,7 @@ protected:
 					//p_command.m_objectData.m_shaderData.m_uniformUpdater.generateUpdateList();
 					p_command.m_objectData.m_shaderData.m_uniformUpdater.updateTextureUniforms();
 					p_command.m_objectData.m_shaderData.m_uniformUpdater.updateBlockBindingPoints();
+					p_command.m_objectData.m_shaderData.m_uniformUpdater.updateSSBBindingPoints();
 				}
 				// If shader loading failed
 				else

+ 25 - 4
Praxis3D/Source/RendererFrontend.cpp

@@ -1,35 +1,56 @@
 
+#include "BlurPass.h"
 #include "GeometryPass.h"
 #include "LightingPass.h"
 #include "FinalPass.h"
 #include "ReflectionPass.h"
 #include "RendererFrontend.h"
 
+RendererFrontend::~RendererFrontend()
+{
+	// Delete rendering passes
+	//for(decltype(m_renderingPasses.size()) i = 0, size = m_renderingPasses.size(); i < size; i++)
+	//{
+		//delete m_renderingPasses[i];
+	//}
+}
+
 ErrorCode RendererFrontend::init()
 {
 	ErrorCode returnCode = ErrorCode::Success;
 
+	// If eye adaption is disabled, eye adaption rate should be set to 0
+	if(!Config::graphicsVar().eye_adaption)
+	{
+		Config::m_graphicsVar.eye_adaption_rate = 0.0f;
+	}
+
 	// Get the current screen size
 	m_frameData.m_screenSize.x = Config::graphicsVar().current_resolution_x;
 	m_frameData.m_screenSize.y = Config::graphicsVar().current_resolution_y;
 
 	// Initialize renderer backend and check if it was successful
-	if (!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
+	if(!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
 		return returnCode;
 
 	// Add geometry rendering pass, if it was initialized successfuly
 	GeometryPass *geometryPass = new GeometryPass(*this);
-	if (geometryPass->init() == ErrorCode::Success)
+	if(geometryPass->init() == ErrorCode::Success)
 		m_renderingPasses.push_back(geometryPass);
 
 	// Add lighting rendering pass, if it was initialized successfuly
 	LightingPass *lightingPass = new LightingPass(*this);
-	if (lightingPass->init() == ErrorCode::Success)
+	if(lightingPass->init() == ErrorCode::Success)
 		m_renderingPasses.push_back(lightingPass);
 
+	// Add blur rendering pass, if it was initialized successfully
+	//BlurPass *blurPass = new BlurPass(*this);
+	//if(blurPass->init() == ErrorCode::Success)
+	//	m_renderingPasses.push_back(blurPass);
+
 	// Add final rendering pass, if it was initialized successfuly
 	FinalPass *finalPass = new FinalPass(*this);
-	if (finalPass->init() == ErrorCode::Success)
+	if(finalPass->init() == ErrorCode::Success)
 		m_renderingPasses.push_back(finalPass);
 
 	updateProjectionMatrix();

+ 7 - 6
Praxis3D/Source/RendererFrontend.h

@@ -8,15 +8,16 @@ class RenderPass;
 
 class RendererFrontend
 {
+	friend class BlurPass;
 	friend class GeometryPass;
 	friend class LightingPass;
 	friend class FinalPass;
 	friend class ReflectionPass;
 public:
-	// A handle for buffer that holds data of lights
-	struct LightUniformBuffer
+	// A handle for a uniform or shader storage buffer
+	struct ShaderBuffer
 	{
-		LightUniformBuffer() : m_bufferType(BufferType_Uniform), m_bufferUsage(BufferUsageHint_Dynamic)
+		ShaderBuffer(BufferType p_bufferType, BufferUsageHint p_usageHint) : m_bufferType(p_bufferType), m_bufferUsage(p_usageHint)
 		{
 			m_data = 0;
 			m_size = 0;
@@ -36,7 +37,7 @@ public:
 	};
 
 	RendererFrontend() { }
-	~RendererFrontend() { }
+	~RendererFrontend();
 
 	ErrorCode init();
 
@@ -164,7 +165,7 @@ protected:
 			for(int matType = 0; matType < MaterialType_NumOfTypes; matType++)
 				queueForLoading(p_objectData.m_materials[matType][i]);
 	}
-	inline void queueForLoading(LightUniformBuffer &p_lightBuffer)
+	inline void queueForLoading(ShaderBuffer &p_lightBuffer)
 	{
 		m_loadCommands.emplace_back(p_lightBuffer.m_handle,
 			p_lightBuffer.m_bufferType,
@@ -174,7 +175,7 @@ protected:
 			p_lightBuffer.m_data);
 	}
 
-	inline void queueForUpdate(LightUniformBuffer &p_lightBuffer)
+	inline void queueForUpdate(ShaderBuffer &p_lightBuffer)
 	{
 		m_bufferUpdateCommands.emplace_back(p_lightBuffer.m_handle,
 			p_lightBuffer.m_offset,

+ 1 - 53
Praxis3D/Source/ShaderLoader.h

@@ -145,60 +145,8 @@ public:
 		friend class CommandBuffer;
 		friend class ShaderLoader;
 		friend class RendererFrontend;
-	public:
-		/*inline void addShader(Shader *p_shader)
-		{
-			if(p_shader != nullptr)
-			{
-				switch(p_shader->m_shaderType)
-				{
-				case ShaderLoader::ShaderFragment:
-					m_shaders[ArrayFragment] = p_shader;
-					break;
-				case ShaderLoader::ShaderGeometry:
-					m_shaders[ArrayGeometry] = p_shader;
-					break;
-				case ShaderLoader::ShaderVertex:
-					m_shaders[ArrayVertex] = p_shader;
-					break;
-				case ShaderLoader::ShaderTessControl:
-					m_shaders[ArrayTessControl] = p_shader;
-					m_tessellated = true;
-					break;
-				case ShaderLoader::ShaderTessEvaluation:
-					m_shaders[ArrayTessEvaluation] = p_shader;
-					m_tessellated = true;
-					break;
-				}
-			}
-		}
-		inline void addShader(ShaderLoader::ShaderArrayTypes p_shaderType, const std::string &p_filename)
-		{
-			if(!p_filename.empty())
-			{
-				switch(p_shaderType)
-				{
-				case ShaderLoader::ArrayFragment:
-					m_shaders[ArrayFragment] = new Shader(p_filename, ShaderFragment);
-					break;
-				case ShaderLoader::ArrayGeometry:
-					m_shaders[ArrayGeometry] = new Shader(p_filename, ShaderGeometry);
-					break;
-				case ShaderLoader::ArrayVertex:
-					m_shaders[ArrayVertex] = new Shader(p_filename, ShaderVertex);
-					break;
-				case ShaderLoader::ArrayTessControl:
-					m_shaders[ArrayTessControl] = new Shader(p_filename, ShaderTessControl);
-					m_tessellated = true;
-					break;
-				case ShaderLoader::ArrayTessEvaluation:
-					m_shaders[ArrayTessEvaluation] = new Shader(p_filename, ShaderTessEvaluation);
-					m_tessellated = true;
-					break;
-				}
-			}
-		}*/
 
+	public:
 		inline void addShader(ShaderType p_shaderType, const std::string &p_filename)
 		{
 			m_shaderFilename[p_shaderType] = p_filename;

+ 27 - 1
Praxis3D/Source/ShaderUniformUpdater.cpp

@@ -19,12 +19,14 @@ ErrorCode ShaderUniformUpdater::generateUpdateList()
 	returnError = generatePerModelList();
 	returnError = generatePerMeshList();
 	returnError = generateUniformBlockList();
+	returnError = generateSSBBlockList();
 
 	m_numUpdatesPerFrame = m_updatesPerFrame.size();
 	m_numUpdatesPerModel = m_updatesPerModel.size();
 	m_numUpdatesPerMesh = m_updatesPerMesh.size();
 	m_numTextureUpdates = m_textureUpdates.size();
 	m_numUniformBlockUpdates = m_uniformBlockUpdates.size();
+	m_numSSBBBlockUpdates = m_SSBBlockUpdates.size();
 
 	// Check for errors, and cache it if it exists, since we are returning the error to higher layer
 	if(returnError != ErrorCode::Success)
@@ -48,6 +50,7 @@ ErrorCode ShaderUniformUpdater::generateTextureUpdateList()
 	uniformList.push_back(new MatPropertiesMapUniform(m_shaderHandle));
 	uniformList.push_back(new BlurMapUniform(m_shaderHandle));
 	uniformList.push_back(new FinalMapUniform(m_shaderHandle));
+	uniformList.push_back(new BlurTextureUniform(m_shaderHandle));
 
 	// Cubemap texture uniforms
 	uniformList.push_back(new DynamicEnvironmentMapUniform(m_shaderHandle));
@@ -65,7 +68,7 @@ ErrorCode ShaderUniformUpdater::generateTextureUpdateList()
 	uniformList.push_back(new NormalTextureUniform(m_shaderHandle));
 	uniformList.push_back(new EmissiveTextureUniform(m_shaderHandle));
 	uniformList.push_back(new CombinedTextureUniform(m_shaderHandle));
-	
+		
 	// Go through each uniform and check if it is valid
 	// If it is, add it to the update list, if not, delete it
 	for(decltype(uniformList.size()) i = 0, size = uniformList.size(); i < size; i++)
@@ -111,8 +114,11 @@ ErrorCode ShaderUniformUpdater::generatePerFrameList()
 	uniformList.push_back(new ScreenSizeUniform(m_shaderHandle));
 
 	// Misc
+	uniformList.push_back(new DeltaTimeMSUniform(m_shaderHandle));
+	uniformList.push_back(new DeltaTimeSUniform(m_shaderHandle));
 	uniformList.push_back(new ElapsedTimeUniform(m_shaderHandle));
 	uniformList.push_back(new GammaUniform(m_shaderHandle));
+	uniformList.push_back(new EyeAdaptionRateUniform(m_shaderHandle));
 
 	// Go through each uniform and check if it is valid
 	// If it is, add it to the update list, if not, delete it
@@ -187,3 +193,23 @@ ErrorCode ShaderUniformUpdater::generateUniformBlockList()
 
 	return returnError;
 }
+ErrorCode ShaderUniformUpdater::generateSSBBlockList()
+{
+	ErrorCode returnError = ErrorCode::Success;
+
+	// Make a vector of SSBO classes and populate it
+	std::vector<BaseShaderStorageBlock*> SSBBlockList;
+
+	// HDR SSBO
+	SSBBlockList.push_back(new HDRShaderStorageBuffer(m_shaderHandle));
+
+	// Go through each uniform and check if it is valid
+	// If it is, add it to the update list, if not, delete it
+	for(decltype(SSBBlockList.size()) i = 0, size = SSBBlockList.size(); i < size; i++)
+		if(SSBBlockList[i]->isValid())
+			m_SSBBlockUpdates.push_back(SSBBlockList[i]);
+		else
+			delete SSBBlockList[i];
+
+	return returnError;
+}

+ 19 - 1
Praxis3D/Source/ShaderUniformUpdater.h

@@ -21,6 +21,7 @@ public:
 		m_numUpdatesPerMesh = 0;
 		m_numTextureUpdates = 0;
 		m_numUniformBlockUpdates = 0;
+		m_numSSBBBlockUpdates = 0;
 	}
 	~ShaderUniformUpdater()
 	{
@@ -36,6 +37,7 @@ public:
 	inline size_t getNumUpdatesPerMesh() const	{ return m_numUpdatesPerMesh;		}
 	inline size_t getNumTextureUpdates() const	{ return m_numTextureUpdates;		}
 	inline size_t getNumUniformBlocks() const	{ return m_numUniformBlockUpdates;	}
+	inline size_t getNumSSBBufferBlocks() const	{ return m_numSSBBBlockUpdates;		}
 
 private:
 	// Checks which uniforms are used in the shader, and generates a list of valid ones
@@ -47,24 +49,28 @@ private:
 		for(decltype(m_numUpdatesPerFrame) i = 0; i < m_numUpdatesPerFrame; i++)
 			m_updatesPerFrame[i]->update(p_uniformData);
 	}
+
 	// Should be called once per model
 	const inline void updateModel(const UniformData &p_uniformData = m_defaultUniformData) const
 	{
 		for(decltype(m_numUpdatesPerModel) i = 0; i < m_numUpdatesPerModel; i++)
 			m_updatesPerModel[i]->update(p_uniformData);
 	}
+
 	// Should be called once per mesh
 	const inline void updateMesh(const UniformData &p_uniformData = m_defaultUniformData) const
 	{
 		for(decltype(m_numUpdatesPerMesh) i = 0; i < m_numUpdatesPerMesh; i++)
 			m_updatesPerMesh[i]->update(p_uniformData);
 	}
+
 	// Should be called when texture handles need updating
 	const inline void updateTextureUniforms(const UniformData &p_uniformData = m_defaultUniformData) const
 	{
 		for(decltype(m_numTextureUpdates) i = 0; i < m_numTextureUpdates; i++)
 			m_textureUpdates[i]->update(p_uniformData);
 	}
+
 	// Should never be called, unless a binding point for a uniform block has changed
 	// (Does not update the data in the uniform block, only updates the binding point)
 	const inline void updateBlockBindingPoints(const UniformData &p_uniformData = m_defaultUniformData) const
@@ -73,11 +79,20 @@ private:
 			m_uniformBlockUpdates[i]->update(p_uniformData);
 	}
 
+	// Should never be called, unless a binding point for a uniform block has changed
+	// (Does not update the data in the uniform block, only updates the binding point)
+	const inline void updateSSBBindingPoints(const UniformData &p_uniformData = m_defaultUniformData) const
+	{
+		for(decltype(m_numSSBBBlockUpdates) i = 0; i < m_numSSBBBlockUpdates; i++)
+			m_uniformBlockUpdates[i]->update(p_uniformData);
+	}
+
 	ErrorCode generateTextureUpdateList();
 	ErrorCode generatePerFrameList();
 	ErrorCode generatePerModelList();
 	ErrorCode generatePerMeshList();
 	ErrorCode generateUniformBlockList();
+	ErrorCode generateSSBBlockList();
 
 	std::vector<BaseUniform*>	m_updatesPerFrame,
 								m_updatesPerModel,
@@ -86,11 +101,14 @@ private:
 
 	std::vector<BaseUniformBlock*> m_uniformBlockUpdates;
 
+	std::vector<BaseShaderStorageBlock*> m_SSBBlockUpdates;
+
 	size_t	m_numUpdatesPerFrame,
 			m_numUpdatesPerModel,
 			m_numUpdatesPerMesh,
 			m_numTextureUpdates,
-			m_numUniformBlockUpdates;
+			m_numUniformBlockUpdates,
+			m_numSSBBBlockUpdates;
 
 	unsigned int m_shaderHandle;
 	ShaderLoader::ShaderProgram &m_shader;

+ 96 - 1
Praxis3D/Source/ShaderUniforms.h

@@ -67,6 +67,42 @@ protected:
 	const std::string m_name;
 	unsigned int m_uniformHandle;
 	const unsigned int m_shaderHandle;
+}; 
+class BaseShaderStorageBlock
+{
+public:
+	BaseShaderStorageBlock(const std::string &p_name, const unsigned int p_shaderHandle)
+		: m_name(p_name), m_shaderHandle(p_shaderHandle)
+	{
+		// Get the SSBO location (returns -1 in case it is not present in the shader)
+		m_SSBOHandle = glGetProgramResourceIndex(m_shaderHandle, GL_SHADER_STORAGE_BLOCK, p_name.c_str());
+	}
+
+	// Returns true if the uniform is present in the shader
+	const inline bool isValid() const { return (m_SSBOHandle != -1); }
+	/*const inline int getBlockSize() const
+	{
+		int blockSize = 0;
+
+		// Get the uniform block size
+		glGetActiveUniformBlockiv(m_shaderHandle, m_SSBOHandle, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
+
+		return blockSize;
+	}*/
+
+	// Updates the uniform block binding index
+	virtual void update(const UniformData &p_uniformData) = 0;
+
+protected:
+	const inline void updateBlockBinding(const unsigned int p_bindingPoint) const
+	{
+		// Bind the uniform buffer at the specified binding point
+		glUniformBlockBinding(m_shaderHandle, m_SSBOHandle, p_bindingPoint);
+	}
+
+	const std::string m_name;
+	unsigned int m_SSBOHandle;
+	const unsigned int m_shaderHandle;
 };
 
 class ModelMatUniform : public BaseUniform
@@ -149,6 +185,26 @@ public:
 					p_uniformData.m_frameData.m_screenSize.y);
 	}
 };
+class DeltaTimeMSUniform : public BaseUniform
+{
+public:
+	DeltaTimeMSUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().deltaTimeMSUniform, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1f(m_uniformHandle, ClockLocator::get().getDeltaMSF());
+	}
+};
+class DeltaTimeSUniform : public BaseUniform
+{
+public:
+	DeltaTimeSUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().deltaTimeSUniform, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1f(m_uniformHandle, ClockLocator::get().getDeltaSecondsF());
+	}
+};
 class ElapsedTimeUniform : public BaseUniform
 {
 public:
@@ -260,7 +316,7 @@ private:
 class TextureTilingFactorUniform : public BaseUniform
 {
 public:
-	TextureTilingFactorUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().textureTilingFactorUniform, p_shaderHandle), m_currentTexTillingFactor(0.0) { }
+	TextureTilingFactorUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().textureTilingFactorUniform, p_shaderHandle), m_currentTexTillingFactor(0.0f) { }
 
 	void update(const UniformData &p_uniformData)
 	{
@@ -275,6 +331,25 @@ public:
 
 private:
 	float m_currentTexTillingFactor;
+}; 
+class EyeAdaptionRateUniform : public BaseUniform
+{
+public:
+	EyeAdaptionRateUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().eyeAdaptionRate, p_shaderHandle), eyeAdaptionRate(0.0f) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		// Check if the same value is not already assigned (a small optimization)
+		if(eyeAdaptionRate != Config::graphicsVar().eye_adaption_rate)
+		{
+			eyeAdaptionRate = Config::graphicsVar().eye_adaption_rate;
+
+			glUniform1f(m_uniformHandle, eyeAdaptionRate);
+		}
+	}
+
+private:
+	float eyeAdaptionRate;
 };
 
 class DirLightColorUniform : public BaseUniform
@@ -572,6 +647,16 @@ public:
 		glUniform1i(m_uniformHandle, MaterialType_Emissive);
 	}
 };
+class BlurTextureUniform : public BaseUniform
+{
+public:
+	BlurTextureUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().blurTextureUniform, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1i(m_uniformHandle, MaterialType_Blur);
+	}
+};
 class CombinedTextureUniform : public BaseUniform
 {
 public:
@@ -731,4 +816,14 @@ public:
 	{
 		updateBlockBinding(LightBufferBinding_SpotLight);
 	}
+};
+class HDRShaderStorageBuffer : public BaseShaderStorageBlock
+{
+public:
+	HDRShaderStorageBuffer(unsigned int p_shaderHandle) : BaseShaderStorageBlock(Config::shaderVar().spotLightBuffer, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		updateBlockBinding(SSBOBinding_HDR);
+	}
 };

+ 4 - 0
Praxis3D/Source/UniformData.h

@@ -6,6 +6,7 @@ struct UniformFrameData
 {
 	UniformFrameData()
 	{
+		m_dirLightIntensity = 0.0f;
 		m_numPointLights = 0;
 		m_numSpotLights = 0;
 	}
@@ -26,6 +27,9 @@ struct UniformFrameData
 				m_dirLightDirection;
 	float		m_dirLightIntensity;
 
+	// Delta time of the last frame
+	float		m_deltaTime;
+
 	// Current number of lights in the light buffers
 	unsigned int m_numPointLights,
 				 m_numSpotLights;

BIN
Praxis3D/icon1.ico


+ 16 - 0
Praxis3D/resource1.h

@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Praxis3D1.rc
+//
+#define IDI_ICON1                       102
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        103
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif