Browse Source

Added lens flare, modified render pass init, fixed shader bug

-Added a pseudo lens flare effect as a rendering pass. Performed by taking bright screen fragments, making multiple ghost reflections and a halo effects (by also incorporating chromatic abberration), bluring the result and filtering it with starburst and lens dirt.
-Added lens dirt to the bloom effect.
-Modified shader loader to remove a bug where the shader array is reallocated, thus nullifying all the pointers to shader entries.
-Modified how the rendering passes are constructed, making it easier to add, remove and change the order of rendering pass array.
-Added a new texture loading function, for easier texture creation outside of the model objects (easier to load textures in the rendering passes).
-Fixed warnings after code analysis.
Paulcodedev 7 years ago
parent
commit
db100c62a1
49 changed files with 1217 additions and 338 deletions
  1. 2 1
      Praxis3D/Data/Maps/default_lite.pmap
  2. 30 0
      Praxis3D/Data/Shaders/bloomCompositePass.frag
  3. 10 0
      Praxis3D/Data/Shaders/bloomCompositePass.vert
  4. 1 1
      Praxis3D/Data/Shaders/finalPass.frag
  5. 8 74
      Praxis3D/Data/Shaders/gaussianBlurHorizontal.frag
  6. 1 22
      Praxis3D/Data/Shaders/gaussianBlurHorizontal.vert
  7. 9 67
      Praxis3D/Data/Shaders/gaussianBlurVertical.frag
  8. 1 23
      Praxis3D/Data/Shaders/gaussianBlurVertical.vert
  9. 0 10
      Praxis3D/Data/Shaders/hdrMappingPass.frag
  10. 9 7
      Praxis3D/Data/Shaders/hdrMappingPass.vert
  11. 49 0
      Praxis3D/Data/Shaders/lenseFlareCompositePass.frag
  12. 16 0
      Praxis3D/Data/Shaders/lenseFlareCompositePass.vert
  13. 135 0
      Praxis3D/Data/Shaders/lenseFlarePass.frag
  14. 17 0
      Praxis3D/Data/Shaders/lenseFlarePass.vert
  15. 120 3
      Praxis3D/Data/Shaders/postProcessPass.frag
  16. 5 1
      Praxis3D/Data/config.ini
  17. 4 0
      Praxis3D/Praxis3D.vcxproj
  18. 9 0
      Praxis3D/Praxis3D.vcxproj.filters
  19. 2 2
      Praxis3D/Source/AtmScatteringModel.cpp
  20. 63 0
      Praxis3D/Source/BloomCompositePass.h
  21. 20 10
      Praxis3D/Source/BlurPass.h
  22. 9 9
      Praxis3D/Source/Clock.h
  23. 23 8
      Praxis3D/Source/CommonDefinitions.h
  24. 27 1
      Praxis3D/Source/Config.cpp
  25. 50 0
      Praxis3D/Source/Config.h
  26. 1 1
      Praxis3D/Source/ConfigLoader.cpp
  27. 6 0
      Praxis3D/Source/FinalPass.h
  28. 50 0
      Praxis3D/Source/GraphicsDataSets.h
  29. 8 4
      Praxis3D/Source/HdrMappingPass.h
  30. 95 0
      Praxis3D/Source/LenseFlareCompositePass.h
  31. 116 0
      Praxis3D/Source/LenseFlarePass.h
  32. 1 0
      Praxis3D/Source/LoaderBase.h
  33. 0 6
      Praxis3D/Source/ObjectPool.h
  34. 56 3
      Praxis3D/Source/PostProcessPass.h
  35. 1 1
      Praxis3D/Source/PropertyLoader.cpp
  36. 1 1
      Praxis3D/Source/ReflectionPass.h
  37. 24 1
      Praxis3D/Source/RenderPassBase.h
  38. 13 13
      Praxis3D/Source/RendererBackend.h
  39. 93 46
      Praxis3D/Source/RendererFrontend.cpp
  40. 21 9
      Praxis3D/Source/RendererFrontend.h
  41. 2 2
      Praxis3D/Source/RendererScene.cpp
  42. 5 5
      Praxis3D/Source/ScriptingScene.cpp
  43. 1 1
      Praxis3D/Source/ShaderGraphicsObjects.h
  44. 7 5
      Praxis3D/Source/ShaderLoader.cpp
  45. 1 1
      Praxis3D/Source/ShaderLoader.h
  46. 8 0
      Praxis3D/Source/ShaderUniformUpdater.cpp
  47. 47 0
      Praxis3D/Source/ShaderUniforms.h
  48. 38 0
      Praxis3D/Source/TextureLoader.cpp
  49. 2 0
      Praxis3D/Source/TextureLoader.h

+ 2 - 1
Praxis3D/Data/Maps/default_lite.pmap

@@ -7,6 +7,7 @@
 			"Scene": 
 			"Scene": 
 			{
 			{
 				"ModelPoolSize": "30",
 				"ModelPoolSize": "30",
+				"ShaderPoolSize": "10",
 				"PointLightPoolSize": "20",
 				"PointLightPoolSize": "20",
 				"SpotLightPoolSize": "20"
 				"SpotLightPoolSize": "20"
 			},
 			},
@@ -1018,7 +1019,7 @@
 				{
 				{
 					"Type": "SolarTimeScript",
 					"Type": "SolarTimeScript",
 					"Name": "Solar Time Script 1",
 					"Name": "Solar Time Script 1",
-					"Hours": "18",
+					"Hours": "15",
 					"Minutes": "0",
 					"Minutes": "0",
 					"Seconds": "0.0f",
 					"Seconds": "0.0f",
 					"Year": "2018",
 					"Year": "2018",

+ 30 - 0
Praxis3D/Data/Shaders/bloomCompositePass.frag

@@ -0,0 +1,30 @@
+#version 430 core
+
+out vec4 outputColor;
+
+uniform ivec2 screenSize;
+
+uniform sampler2D emissiveMap;
+uniform sampler2D inputColorMap;
+uniform sampler2D lensDirtTexture;
+
+vec2 calcTexCoord(void)
+{
+    return gl_FragCoord.xy / screenSize;
+}
+
+void main(void)
+{
+	// Calculate screen-space texture coordinates, for buffer access
+	vec2 texCoord = calcTexCoord();
+	
+	// Perform gamma correction on the color from the final framebuffer
+	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
+	
+	// Add emissive color (which is generated in a blur pass)
+	// And apply lens dirt texture
+	fragmentColor += texture(emissiveMap, texCoord).xyz * min(texture(lensDirtTexture, texCoord).r, 1.0);
+	
+	// Write the color to the framebuffer
+	outputColor = vec4(fragmentColor, 1.0);
+}

+ 10 - 0
Praxis3D/Data/Shaders/bloomCompositePass.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), 0.5, 1.0);
+}

+ 1 - 1
Praxis3D/Data/Shaders/finalPass.frag

@@ -72,7 +72,7 @@ void main(void)
 	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
 	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
 	
 	
 	// Add emissive color (which is generated in a blur pass)
 	// Add emissive color (which is generated in a blur pass)
-	fragmentColor += texture(emissiveMap, texCoord).xyz;
+	//fragmentColor += texture(emissiveMap, texCoord).xyz;
 		
 		
 	#ifdef ENABLE_TONE_MAPPING
 	#ifdef ENABLE_TONE_MAPPING
 	// Perform simple tonemapping on the final color
 	// Perform simple tonemapping on the final color

+ 8 - 74
Praxis3D/Data/Shaders/gaussianBlurHorizontal.frag

@@ -1,17 +1,13 @@
 #version 430 core
 #version 430 core
 //precision mediump float;
 //precision mediump float;
 
 
-in vec2 blurTexCoords[14];
-
 out vec4 outputColor;
 out vec4 outputColor;
 
 
 uniform sampler2D inputColorMap;
 uniform sampler2D inputColorMap;
 uniform ivec2 screenSize;
 uniform ivec2 screenSize;
 
 
-uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
- 
-//uniform float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 );
-//uniform float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 );
+uniform float offset[3] = float[](0.0, 1.3846153846, 3.2307692308);
+uniform float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703);
 
 
 vec2 calcTexCoord(void)
 vec2 calcTexCoord(void)
 {
 {
@@ -23,80 +19,18 @@ void main(void)
 	// Calculate screen-space texture coordinates, for buffer access
 	// Calculate screen-space texture coordinates, for buffer access
 	vec2 texCoord = calcTexCoord();
 	vec2 texCoord = calcTexCoord();
 	
 	
-    vec3 fragColor = vec3(0.0);
-	
-	float blurOffset = 1.0;
-	
 	// Calculate the size of a single pixel
 	// Calculate the size of a single pixel
 	vec2 texCoordOffset = 1.0 / screenSize;
 	vec2 texCoordOffset = 1.0 / screenSize;
 	
 	
-    fragColor = texture(inputColorMap, texCoord).rgb * weight[0]; // current fragment's contribution
+	// Get current fragment color
+	vec3 fragColor = texture(inputColorMap, texCoord).xyz * weight[0];
 	
 	
-	for(int i = 1; i < 5; ++i)
+	// Sample color around adjacent fragments		
+	for(int i = 1; i < 3; i++)
 	{
 	{
-		fragColor += texture(inputColorMap, texCoord + vec2(texCoordOffset.x * i, 0.0)).rgb * weight[i];
-		fragColor += texture(inputColorMap, texCoord - vec2(texCoordOffset.x * i, 0.0)).rgb * weight[i];
+		fragColor += texture(inputColorMap, texCoord + vec2(offset[i] / screenSize.x, 0.0)).xyz * weight[i];
+		fragColor += texture(inputColorMap, texCoord - vec2(offset[i] / screenSize.x, 0.0)).xyz * weight[i];
 	}
 	}
 	
 	
-	//FragmentColor = texture2D( image, vec2(gl_FragCoord)/1024.0 ) * weight[0];
-   /* for(int i=1; i<3; i++) 
-	{
-        fragColor +=
-            texture2D( inputColorMap, (texCoord + vec2(0.0, offset[i])) / 900.0) * weight[i];
-        fragColor +=
-            texture2D( inputColorMap, (texCoord - vec2(0.0, offset[i])) / 900.0) * weight[i];
-    }*/
-	/*
-    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);
-	*/
-	/*
-    fragColor += texture(blurMap, texCoord + vec2(-0.028 * blurOffset, 0.0)).xyz * 0.0044299121055113265;
-    fragColor += texture(blurMap, texCoord + vec2(-0.024 * blurOffset, 0.0)).xyz * 0.00895781211794;
-    fragColor += texture(blurMap, texCoord + vec2(-0.020 * blurOffset, 0.0)).xyz * 0.0215963866053;
-    fragColor += texture(blurMap, texCoord + vec2(-0.016 * blurOffset, 0.0)).xyz * 0.0443683338718;
-    fragColor += texture(blurMap, texCoord + vec2(-0.012 * blurOffset, 0.0)).xyz * 0.0776744219933;
-    fragColor += texture(blurMap, texCoord + vec2(-0.008 * blurOffset, 0.0)).xyz * 0.115876621105;
-    fragColor += texture(blurMap, texCoord + vec2(-0.004 * blurOffset, 0.0)).xyz * 0.147308056121;
-    fragColor += texture(blurMap, texCoord         			  ).xyz * 0.259576912161;
-    fragColor += texture(blurMap, texCoord + vec2(0.004 * blurOffset, 0.0)).xyz * 0.147308056121;
-    fragColor += texture(blurMap, texCoord + vec2(0.008 * blurOffset, 0.0)).xyz * 0.115876621105;
-    fragColor += texture(blurMap, texCoord + vec2(0.012 * blurOffset, 0.0)).xyz * 0.0776744219933;
-    fragColor += texture(blurMap, texCoord + vec2(0.016 * blurOffset, 0.0)).xyz * 0.0443683338718;
-    fragColor += texture(blurMap, texCoord + vec2(0.020 * blurOffset, 0.0)).xyz * 0.0215963866053;
-    fragColor += texture(blurMap, texCoord + vec2(0.024 * blurOffset, 0.0)).xyz * 0.00895781211794;
-    fragColor += texture(blurMap, texCoord + vec2(0.028 * blurOffset, 0.0)).xyz * 0.0044299121055113265;
-	*/
-	/*
-    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);
 	outputColor = vec4(fragColor, 1.0);
-	//outputColor = vec4(0.0, 1.0, 1.0, 1.0);
-	//outputColor = vec4(texture(blurMap, texCoord).xyz, 1.0);
 }
 }

+ 1 - 22
Praxis3D/Data/Shaders/gaussianBlurHorizontal.vert

@@ -1,30 +1,9 @@
 #version 430 core
 #version 430 core
 
 
-out vec2 blurTexCoords[14];
-
-uniform float blurOffset;
-
 void main(void)
 void main(void)
 {
 {
-	vec2 texCoord = vec2(0.0);
-	
-    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
 	// Determine texture coordinates
-	texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	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
 	// 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);
 	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);

+ 9 - 67
Praxis3D/Data/Shaders/gaussianBlurVertical.frag

@@ -1,16 +1,13 @@
 #version 430 core
 #version 430 core
 //precision mediump float;
 //precision mediump float;
 
 
-in vec2 blurTexCoords[14];
-
-//out vec4 blurBuffer;
 out vec4 outputColor;
 out vec4 outputColor;
-//layout(location = 0) out vec4 blurBuffer;
 
 
 uniform sampler2D inputColorMap;
 uniform sampler2D inputColorMap;
 uniform ivec2 screenSize;
 uniform ivec2 screenSize;
 
 
-uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
+uniform float offset[3] = float[](0.0, 1.3846153846, 3.2307692308);
+uniform float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703);
 
 
 vec2 calcTexCoord(void)
 vec2 calcTexCoord(void)
 {
 {
@@ -22,73 +19,18 @@ void main(void)
 	// Calculate screen-space texture coordinates, for buffer access
 	// Calculate screen-space texture coordinates, for buffer access
 	vec2 texCoord = calcTexCoord();
 	vec2 texCoord = calcTexCoord();
 	
 	
-    vec3 fragColor = vec3(0.0);
-	
-	float blurOffset = 1.0;
-	
 	// Calculate the size of a single pixel
 	// Calculate the size of a single pixel
 	vec2 texCoordOffset = 1.0 / screenSize;
 	vec2 texCoordOffset = 1.0 / screenSize;
 	
 	
-    fragColor = texture(inputColorMap, texCoord).rgb * weight[0]; // current fragment's contribution
+	// Get current fragment color
+	vec3 fragColor = texture(inputColorMap, texCoord).xyz * weight[0];
 	
 	
-	for(int i = 1; i < 5; ++i)
+	// Sample color around adjacent fragments
+	for(int i = 1; i < 3; i++) 
 	{
 	{
-		fragColor += texture(inputColorMap, texCoord + vec2(0.0, texCoordOffset.y * i)).rgb * weight[i];
-		fragColor += texture(inputColorMap, texCoord - vec2(0.0, texCoordOffset.y * i)).rgb * weight[i];
+		fragColor += texture(inputColorMap, texCoord + vec2(0.0, offset[i] / screenSize.y)).xyz * weight[i];
+		fragColor += texture(inputColorMap, texCoord - vec2(0.0, offset[i] / screenSize.y)).xyz * weight[i];
 	}
 	}
-		
-	/*
-    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);
-	*/
-	/*
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.028 * blurOffset)).xyz * 0.0044299121055113265;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.024 * blurOffset)).xyz * 0.00895781211794;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.020 * blurOffset)).xyz * 0.0215963866053;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.016 * blurOffset)).xyz * 0.0443683338718;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.012 * blurOffset)).xyz * 0.0776744219933;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.008 * blurOffset)).xyz * 0.115876621105;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0, -0.004 * blurOffset)).xyz * 0.147308056121;
-    fragColor += texture(emissiveMap, texCoord         			  ).xyz * 0.259576912161;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.004 * blurOffset)).xyz * 0.147308056121;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.008 * blurOffset)).xyz * 0.115876621105;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.012 * blurOffset)).xyz * 0.0776744219933;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.016 * blurOffset)).xyz * 0.0443683338718;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.020 * blurOffset)).xyz * 0.0215963866053;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.024 * blurOffset)).xyz * 0.00895781211794;
-    fragColor += texture(emissiveMap, texCoord + vec2(0.0,  0.028 * blurOffset)).xyz * 0.0044299121055113265;
-	*/
-	/*
-    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);
 	outputColor = vec4(fragColor, 1.0);
-	//outputColor = vec4(fragColor, 1.0);
-	//outputColor = vec4(1.0, 0.0, 0.0, 1.0);
-    //blurBuffer = vec4(texture(emissiveMap, texCoord).xyz, 1.0);
 }
 }

+ 1 - 23
Praxis3D/Data/Shaders/gaussianBlurVertical.vert

@@ -1,31 +1,9 @@
 #version 430 core
 #version 430 core
 
 
-out vec2 blurTexCoords[14];
-
-uniform float blurOffset;
-
 void main(void)
 void main(void)
 {
 {
-	vec2 texCoord = vec2(0.0);
-	
 	// Determine texture coordinates
 	// Determine texture coordinates
-	texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
-	
-    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);
-	
+	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
 	// 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);
 	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);

+ 0 - 10
Praxis3D/Data/Shaders/hdrMappingPass.frag

@@ -4,16 +4,6 @@
 #define MIN_INTENDED_BRIGHTNESS 0.05
 #define MIN_INTENDED_BRIGHTNESS 0.05
 #define MAX_INTENDED_BRIGHTNESS 5.0
 #define MAX_INTENDED_BRIGHTNESS 5.0
 
 
-#define MAX_NUM_POINT_LIGHTS 20
-#define MAX_NUM_SPOT_LIGHTS 10
-#define PI 3.1415926535
-
-/*
-layout(std430, binding = 0) buffer HDRBuffer
-{
-	float screenBrightness;
-};*/
-
 layout(location = 0) out vec4 emissiveBuffer;
 layout(location = 0) out vec4 emissiveBuffer;
 layout(location = 1) out vec4 colorBuffer;
 layout(location = 1) out vec4 colorBuffer;
 
 

+ 9 - 7
Praxis3D/Data/Shaders/hdrMappingPass.vert

@@ -43,13 +43,15 @@ void main(void)
 {
 {
 	#ifdef ENABLE_HDR
 	#ifdef ENABLE_HDR
 	
 	
-	// Get maximum mipmap level (1x1) of a framebuffer
-	float exposureMipmapLevel = calcMaxMipmapLevel(screenSize);
-	// Get the current (previous frame) average brightness
-	float avgBrightnessPrevFrame = calcLuma(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);
-	
+	if(gl_VertexID == 0)
+	{
+		// Get maximum mipmap level (1x1) of a framebuffer
+		float exposureMipmapLevel = calcMaxMipmapLevel(screenSize);
+		// Get the current (previous frame) average brightness
+		float avgBrightnessPrevFrame = calcLuma(textureLod(finalColorMap, vec2(0.5), exposureMipmapLevel - 3).xyz);
+		// Perform a linear interpolation between current and previous brightness based on delta time
+		screenBrightness = mix(screenBrightness, avgBrightnessPrevFrame, deltaTimeS / eyeAdaptionRate);
+	}
 	#else
 	#else
 	
 	
 	// Set the average brightness to 0.5 so it does not affect the scene
 	// Set the average brightness to 0.5 so it does not affect the scene

+ 49 - 0
Praxis3D/Data/Shaders/lenseFlareCompositePass.frag

@@ -0,0 +1,49 @@
+#version 430 core
+
+layout(location = 0) out vec4 colorBuffer;
+
+flat in float starburstOffset;
+
+uniform ivec2 screenSize;
+
+uniform sampler2D diffuseMap;
+uniform sampler2D inputColorMap;
+uniform sampler2D lensDirtTexture;
+uniform sampler2D lenseStarburstTexture;
+
+float saturate(float p_value)
+{
+	return clamp(p_value, 0.0f, 1.0f);
+}
+
+vec2 calcTexCoord(void)
+{
+    return gl_FragCoord.xy / screenSize;
+}
+
+void main(void)
+{
+	// Calculate screen-space texture coordinates, for buffer access
+	vec2 texCoord = calcTexCoord();
+	
+	// Get the current fragment color
+	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
+	
+	// Calculate starburst
+	vec2 centerVec = texCoord - vec2(0.5);
+	float d = length(centerVec);
+	float radial = acos(centerVec.x / d);
+	float mask = 
+		  texture(lenseStarburstTexture, vec2(radial + starburstOffset * 1.0, 0.0)).r * 
+		  texture(lenseStarburstTexture, vec2(radial - starburstOffset * 0.5, 0.0)).r;
+		  
+	mask = saturate(mask + (1.0 - smoothstep(0.0, 0.3, d)));
+	
+	// Apply lens dirt
+	mask *= textureLod(lensDirtTexture, texCoord, 0.0).r * 0.5;
+	
+	vec3 lensFlareColor = textureLod(diffuseMap, texCoord, 0.0).rgb * mask;
+	
+	// Write the colors to the framebuffers
+	colorBuffer = vec4(fragmentColor + lensFlareColor, 1.0);
+}

+ 16 - 0
Praxis3D/Data/Shaders/lenseFlareCompositePass.vert

@@ -0,0 +1,16 @@
+#version 430 core
+
+uniform vec3 cameraTargetVec;
+
+flat out float starburstOffset;
+
+void main(void) 
+{	
+	starburstOffset = cameraTargetVec.x + cameraTargetVec.y + cameraTargetVec.z;
+
+	// 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);
+}

+ 135 - 0
Praxis3D/Data/Shaders/lenseFlarePass.frag

@@ -0,0 +1,135 @@
+#version 430 core
+
+#define GHOST_TINT_PER_SAMPLE          1  // Apply txGhostGradientColor inside the sample loop instead of at the end.
+#define DISABLE_HALO_ASPECT_RATIO      0  // Code is simpler/cheaper without this, but the halo shape is fixed.
+#define DISABLE_CHROMATIC_ABERRATION   0  // Takes 3x fewer samples.
+
+layout(location = 0) out vec4 diffuseBuffer;
+//layout(location = 1) out vec4 colorBuffer;
+
+flat in float aspectRatio;
+
+uniform ivec2 screenSize;
+//uniform sampler2D emissiveMap;
+uniform sampler2D inputColorMap;
+uniform sampler2D ghostGradientTexture;
+
+struct LensFlareParameters
+{
+	int m_ghostCount;
+	float m_ghostSpacing;
+	float m_ghostThreshold;
+
+	float m_haloAspectRatio;
+	float m_haloRadius;
+	float m_haloThickness;
+	float m_haloThreshold;
+	
+	float m_chromaticAberration;
+	float m_lensFlaireDownsample;
+};
+
+layout (std140) uniform LensFlareParametersBuffer
+{
+	LensFlareParameters lensFlareParam;
+};
+
+// Cubic window; map [0, p_radius] in [1, 0] as a cubic falloff from p_center.
+float cubicFalloff(float p_x, float p_center, float p_radius)
+{
+	p_x = min(abs(p_x - p_center) / p_radius, 1.0);
+	return 1.0 - p_x * p_x * (3.0 - 2.0 * p_x);
+}
+
+vec3 applyThreshold(in vec3 p_color, in float p_threshold)
+{
+	return max(p_color - vec3(p_threshold), vec3(0.0));
+}
+
+vec3 sampleSceneColor(in vec2 p_texCoord)
+{
+#if DISABLE_CHROMATIC_ABERRATION
+	return textureLod(inputColorMap, p_texCoord, lensFlareParam.m_lensFlaireDownsample).rgb;
+#else
+	vec2 offset = normalize(vec2(0.5) - p_texCoord) * lensFlareParam.m_chromaticAberration;
+	return vec3(
+		textureLod(inputColorMap, p_texCoord + offset, lensFlareParam.m_lensFlaireDownsample).r,
+		textureLod(inputColorMap, p_texCoord, lensFlareParam.m_lensFlaireDownsample).g,
+		textureLod(inputColorMap, p_texCoord - offset, lensFlareParam.m_lensFlaireDownsample).b
+		);
+#endif
+}
+
+vec3 sampleGhosts(in vec2 p_texCoord, in float p_threshold)
+{
+	vec3 ghostColor = vec3(0.0);
+	vec2 ghostVec = (vec2(0.5) - p_texCoord) * lensFlareParam.m_ghostSpacing;
+	for (int i = 0; i < lensFlareParam.m_ghostCount; ++i)
+	{
+		// sample scene color
+		vec2 suv = fract(p_texCoord + ghostVec * vec2(i));
+		vec3 s = sampleSceneColor(suv);
+		s = applyThreshold(s, p_threshold);
+		
+		// tint / weight
+		float distanceToCenter = distance(suv, vec2(0.5));
+		#if GHOST_TINT_PER_SAMPLE
+			// incorporate weight into tint gradient
+			s *= textureLod(ghostGradientTexture, vec2(distanceToCenter, 0.5), 0.0).rgb; 
+		#else
+			// analytical weight
+			float weight = 1.0 - smoothstep(0.0, 0.75, distanceToCenter); // analytical weight
+			s *= weight;
+		#endif
+
+		ghostColor += s;
+	}
+	#if !GHOST_TINT_PER_SAMPLE
+		ghostColor *= textureLod(ghostGradientTexture, vec2(distance(p_texCoord, vec2(0.5)), 0.5), 0.0).rgb;
+	#endif
+
+	return ghostColor;
+}
+
+vec3 sampleHalo(in vec2 p_texCoord, in float p_radius, in float p_aspectRatio, in float p_threshold)
+{
+	vec2 haloVec = vec2(0.5) - p_texCoord;
+	
+	#if DISABLE_HALO_ASPECT_RATIO
+		haloVec = normalize(haloVec);
+		float haloWeight = distance(p_texCoord, vec2(0.5));
+	#else
+		haloVec.x /= p_aspectRatio;
+		haloVec = normalize(haloVec);
+		haloVec.x *= p_aspectRatio;
+		vec2 wuv = (p_texCoord - vec2(0.5, 0.0)) / vec2(p_aspectRatio, 1.0) + vec2(0.5, 0.0);
+		float haloWeight = distance(wuv, vec2(0.5));
+	#endif
+	
+	haloVec *= p_radius;
+	haloWeight = cubicFalloff(haloWeight, p_radius, lensFlareParam.m_haloThickness);
+	
+	return applyThreshold(sampleSceneColor(p_texCoord + haloVec), p_threshold) * haloWeight;
+}
+vec2 calcTexCoord(void)
+{
+    return gl_FragCoord.xy / screenSize;
+}
+
+void main(void)
+{
+	// Calculate screen-space texture coordinates, for buffer access
+	vec2 texCoord = calcTexCoord();
+	vec2 texCoordFlipped = vec2(1.0) - texCoord;
+	
+	vec3 lensFlareColor = vec3(0.0);
+	lensFlareColor += sampleGhosts(texCoordFlipped, lensFlareParam.m_ghostThreshold);
+	lensFlareColor += sampleHalo(
+		texCoordFlipped, 
+		lensFlareParam.m_haloRadius, 
+		aspectRatio, 
+		lensFlareParam.m_haloThreshold);
+	
+	// Write the colors to the framebuffers
+	diffuseBuffer = vec4(lensFlareColor, 1.0);
+}

+ 17 - 0
Praxis3D/Data/Shaders/lenseFlarePass.vert

@@ -0,0 +1,17 @@
+#version 430 core
+
+flat out float aspectRatio;
+
+uniform ivec2 screenSize;
+
+void main(void) 
+{	
+	// Calculate aspect ratio 
+	aspectRatio = screenSize.x / screenSize.y;
+
+	// 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);
+}

+ 120 - 3
Praxis3D/Data/Shaders/postProcessPass.frag

@@ -1,10 +1,114 @@
 #version 430 core
 #version 430 core
 
 
-out vec4 outputColor;
+#define GHOST_TINT_PER_SAMPLE          1  // Apply txGhostGradientColor inside the sample loop instead of at the end.
+#define DISABLE_HALO_ASPECT_RATIO      0  // Code is simpler/cheaper without this, but the halo shape is fixed.
+#define DISABLE_CHROMATIC_ABERRATION   0  // Takes 3x fewer samples.
+
+layout(location = 0) out vec4 diffuseBuffer;
+layout(location = 1) out vec4 colorBuffer;
 
 
 uniform ivec2 screenSize;
 uniform ivec2 screenSize;
+//uniform sampler2D emissiveMap;
 uniform sampler2D inputColorMap;
 uniform sampler2D inputColorMap;
+uniform sampler2D ghostGradientTexture;
+
+struct LensFlareParameters
+{
+	int m_ghostCount;
+	float m_ghostSpacing;
+	float m_ghostThreshold;
+
+	float m_haloAspectRatio;
+	float m_haloRadius;
+	float m_haloThickness;
+	float m_haloThreshold;
+	
+	float m_chromaticAberration;
+	float m_lensFlaireDownsample;
+};
+
+layout (std140) uniform LensFlareParametersBuffer
+{
+	LensFlareParameters lensFlareParam;
+};
+
+// Cubic window; map [0, p_radius] in [1, 0] as a cubic falloff from p_center.
+float cubicFalloff(float p_x, float p_center, float p_radius)
+{
+	p_x = min(abs(p_x - p_center) / p_radius, 1.0);
+	return 1.0 - p_x * p_x * (3.0 - 2.0 * p_x);
+}
+
+vec3 applyThreshold(in vec3 p_color, in float p_threshold)
+{
+	return max(p_color - vec3(p_threshold), vec3(0.0));
+}
+
+vec3 sampleSceneColor(in vec2 p_texCoord)
+{
+#if DISABLE_CHROMATIC_ABERRATION
+	return textureLod(inputColorMap, p_texCoord, lensFlareParam.m_lensFlaireDownsample).rgb;
+#else
+	vec2 offset = normalize(vec2(0.5) - p_texCoord) * lensFlareParam.m_chromaticAberration;
+	return vec3(
+		textureLod(inputColorMap, p_texCoord + offset, lensFlareParam.m_lensFlaireDownsample).r,
+		textureLod(inputColorMap, p_texCoord, lensFlareParam.m_lensFlaireDownsample).g,
+		textureLod(inputColorMap, p_texCoord - offset, lensFlareParam.m_lensFlaireDownsample).b
+		);
+#endif
+}
+
+vec3 sampleGhosts(in vec2 p_texCoord, in float p_threshold)
+{
+	vec3 ghostColor = vec3(0.0);
+	vec2 ghostVec = (vec2(0.5) - p_texCoord) * lensFlareParam.m_ghostSpacing;
+	for (int i = 0; i < lensFlareParam.m_ghostCount; ++i)
+	{
+		// sample scene color
+		vec2 suv = fract(p_texCoord + ghostVec * vec2(i));
+		vec3 s = sampleSceneColor(suv);
+		s = applyThreshold(s, p_threshold);
+		
+		// tint / weight
+		float distanceToCenter = distance(suv, vec2(0.5));
+		#if GHOST_TINT_PER_SAMPLE
+			// incorporate weight into tint gradient
+			s *= textureLod(ghostGradientTexture, vec2(distanceToCenter, 0.5), 0.0).rgb; 
+		#else
+			// analytical weight
+			float weight = 1.0 - smoothstep(0.0, 0.75, distanceToCenter); // analytical weight
+			s *= weight;
+		#endif
+
+		ghostColor += s;
+	}
+	#if !GHOST_TINT_PER_SAMPLE
+		ghostColor *= textureLod(ghostGradientTexture, vec2(distance(p_texCoord, vec2(0.5)), 0.5), 0.0).rgb;
+	#endif
+
+	return ghostColor;
+}
 
 
+vec3 sampleHalo(in vec2 p_texCoord, in float p_radius, in float p_aspectRatio, in float p_threshold)
+{
+	vec2 haloVec = vec2(0.5) - p_texCoord;
+	
+	#if DISABLE_HALO_ASPECT_RATIO
+		haloVec = normalize(haloVec);
+		float haloWeight = distance(p_texCoord, vec2(0.5));
+	#else
+		haloVec.x /= p_aspectRatio;
+		haloVec = normalize(haloVec);
+		haloVec.x *= p_aspectRatio;
+		vec2 wuv = (p_texCoord - vec2(0.5, 0.0)) / vec2(p_aspectRatio, 1.0) + vec2(0.5, 0.0);
+		float haloWeight = distance(wuv, vec2(0.5));
+	#endif
+	
+	haloVec *= p_radius;
+	haloWeight = cubicFalloff(haloWeight, p_radius, lensFlareParam.m_haloThickness);
+	
+	return applyThreshold(sampleSceneColor(p_texCoord + haloVec), p_threshold) * haloWeight;
+}
 vec2 calcTexCoord(void)
 vec2 calcTexCoord(void)
 {
 {
     return gl_FragCoord.xy / screenSize;
     return gl_FragCoord.xy / screenSize;
@@ -14,10 +118,23 @@ void main(void)
 {
 {
 	// Calculate screen-space texture coordinates, for buffer access
 	// Calculate screen-space texture coordinates, for buffer access
 	vec2 texCoord = calcTexCoord();
 	vec2 texCoord = calcTexCoord();
+	vec2 texCoordFlipped = vec2(1.0) - texCoord;
 	
 	
 	// Get the current fragment color
 	// Get the current fragment color
 	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
 	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
 	
 	
-	// Write the color to the framebuffer
-	outputColor = vec4(fragmentColor, 1.0);
+	// Add emissive color (which is generated in a blur pass)
+	//fragmentColor += texture(emissiveMap, texCoord).xyz;
+	
+	vec3 lensFlareColor = vec3(0.0);
+	lensFlareColor += sampleGhosts(texCoordFlipped, lensFlareParam.m_ghostThreshold);
+	lensFlareColor += sampleHalo(
+		texCoordFlipped, 
+		lensFlareParam.m_haloRadius, 
+		lensFlareParam.m_haloAspectRatio, 
+		lensFlareParam.m_haloThreshold);
+	
+	// Write the colors to the framebuffers
+	diffuseBuffer = vec4(lensFlareColor, 1.0);
+	colorBuffer = vec4(fragmentColor + lensFlareColor, 1.0);
 }
 }

+ 5 - 1
Praxis3D/Data/config.ini

@@ -22,4 +22,8 @@ fov 80
 z_near 0.1
 z_near 0.1
 z_far 40000
 z_far 40000
 default_map default_lite.pmap
 default_map default_lite.pmap
-atm_scattering_ground_frag_shader atmosphericScatteringPass_ground_simple.frag
+atm_scattering_ground_frag_shader atmosphericScatteringPass_ground_simple.frag
+lens_flare_ghost_threshold 2.0
+lens_flare_halo_threshold 2.0
+lens_flare_halo_radius 0.55
+lens_flare_ghost_count 8

+ 4 - 0
Praxis3D/Praxis3D.vcxproj

@@ -147,6 +147,7 @@
     <IncludePath>$(SolutionDir)\VC x64\include;$(IncludePath)</IncludePath>
     <IncludePath>$(SolutionDir)\VC x64\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)\VC x64\lib;$(LibraryPath)</LibraryPath>
     <LibraryPath>$(SolutionDir)\VC x64\lib;$(LibraryPath)</LibraryPath>
     <OutDir>$(SolutionDir)\Builds\$(Platform)\$(Configuration)\</OutDir>
     <OutDir>$(SolutionDir)\Builds\$(Platform)\$(Configuration)\</OutDir>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <IncludePath>$(SolutionDir)\VC\include;$(IncludePath)</IncludePath>
     <IncludePath>$(SolutionDir)\VC\include;$(IncludePath)</IncludePath>
@@ -343,6 +344,7 @@
     <ClInclude Include="Source\AtmScatteringShaderPass.h" />
     <ClInclude Include="Source\AtmScatteringShaderPass.h" />
     <ClInclude Include="Source\BaseGraphicsObjects.h" />
     <ClInclude Include="Source\BaseGraphicsObjects.h" />
     <ClInclude Include="Source\BaseScriptObject.h" />
     <ClInclude Include="Source\BaseScriptObject.h" />
+    <ClInclude Include="Source\BloomCompositePass.h" />
     <ClInclude Include="Source\BlurPass.h" />
     <ClInclude Include="Source\BlurPass.h" />
     <ClInclude Include="Source\CameraGraphicsObject.h" />
     <ClInclude Include="Source\CameraGraphicsObject.h" />
     <ClInclude Include="Source\CameraScript.h" />
     <ClInclude Include="Source\CameraScript.h" />
@@ -373,6 +375,8 @@
     <ClInclude Include="Source\HdrMappingPass.h" />
     <ClInclude Include="Source\HdrMappingPass.h" />
     <ClInclude Include="Source\Input.h" />
     <ClInclude Include="Source\Input.h" />
     <ClInclude Include="Source\KeyCommand.h" />
     <ClInclude Include="Source\KeyCommand.h" />
+    <ClInclude Include="Source\LenseFlareCompositePass.h" />
+    <ClInclude Include="Source\LenseFlarePass.h" />
     <ClInclude Include="Source\LightingGraphicsObjects.h" />
     <ClInclude Include="Source\LightingGraphicsObjects.h" />
     <ClInclude Include="Source\LightingPass.h" />
     <ClInclude Include="Source\LightingPass.h" />
     <ClInclude Include="Source\LoaderBase.h" />
     <ClInclude Include="Source\LoaderBase.h" />

+ 9 - 0
Praxis3D/Praxis3D.vcxproj.filters

@@ -536,6 +536,15 @@
     <ClInclude Include="Source\SunScript.h">
     <ClInclude Include="Source\SunScript.h">
       <Filter>Scripting\Objects\Header Files</Filter>
       <Filter>Scripting\Objects\Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Source\BloomCompositePass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\LenseFlarePass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\LenseFlareCompositePass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />
     <None Include="Data\config.ini" />

+ 2 - 2
Praxis3D/Source/AtmScatteringModel.cpp

@@ -1087,8 +1087,8 @@ void AtmScatteringModel::Init(unsigned int num_scattering_orders)
 	}
 	}
 	else
 	else
 	{
 	{
-		constexpr double kLambdaMin = 360.0;
-		constexpr double kLambdaMax = 830.0;
+		//constexpr double kLambdaMin = 360.0;
+		//constexpr double kLambdaMax = 830.0;
 		int num_iterations = (num_precomputed_wavelengths_ + 2) / 3;
 		int num_iterations = (num_precomputed_wavelengths_ + 2) / 3;
 		double dlambda = (kLambdaMax - kLambdaMin) / (3 * num_iterations);
 		double dlambda = (kLambdaMax - kLambdaMin) / (3 * num_iterations);
 		for(int i = 0; i < num_iterations; ++i)
 		for(int i = 0; i < num_iterations; ++i)

+ 63 - 0
Praxis3D/Source/BloomCompositePass.h

@@ -0,0 +1,63 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class BloomCompositePass : public RenderPass
+{
+public:
+	BloomCompositePass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer)
+	{
+
+	}
+
+	~BloomCompositePass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError;
+
+		m_name = "Bloom Composite Rendering Pass";
+		
+		// Create a property-set used to load blur vertical shaders
+		PropertySet shaderProperties(Properties::Shaders);
+		shaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().bloom_composite_pass_vert_shader);
+		shaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().bloom_composite_pass_frag_shader);
+
+		// Create shaders
+		m_bloomCompositeShader = Loaders::shader().load(shaderProperties);
+
+		//		 _______________________________
+		//		|	LOAD POST PROCESS SHADER	|
+		//		|_______________________________|
+		shaderError = m_bloomCompositeShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)						// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_bloomCompositeShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+		
+		return returnError;
+	}
+
+	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	{
+		glDisable(GL_DEPTH_TEST);
+		
+		// Bind input color texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
+		
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
+
+		// Perform various visual effects in the post process shader
+		m_renderer.queueForDrawing(m_bloomCompositeShader->getShaderHandle(), m_bloomCompositeShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.passScreenSpaceDrawCommandsToBackend();
+
+		p_renderPassData.swapColorInputOutputMaps();
+	}
+
+private:
+	ShaderLoader::ShaderProgram	*m_bloomCompositeShader;
+};

+ 20 - 10
Praxis3D/Source/BlurPass.h

@@ -61,48 +61,58 @@ public:
 		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
 		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
 		
 		
 		// Bind emissive texture for reading so it can be accessed in the shaders
 		// Bind emissive texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getEmissiveInputMap(), GeometryBuffer::GBufferInputTexture);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getBlurInputMap(), GeometryBuffer::GBufferInputTexture);
 
 
 		// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
 		// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getIntermediateMap());
 
 
 		// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
 		// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
 		m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 
-		for(int i = 0; i < 5; i++)
+		for(decltype(p_renderPassData.m_numOfBlurPasses) i = 0; i < p_renderPassData.m_numOfBlurPasses; i++)
 		{
 		{
 			// Bind intermediate blur texture for reading so it can be accessed in the shaders
 			// Bind intermediate blur texture for reading so it can be accessed in the shaders
-			m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorOutputMap(), GeometryBuffer::GBufferInputTexture);
+			m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getIntermediateMap(), GeometryBuffer::GBufferInputTexture);
 
 
 			// Bind emissive texture for writing to, so the second pass populates it with the final blur result
 			// Bind emissive texture for writing to, so the second pass populates it with the final blur result
-			m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getEmissiveInputMap());
+			m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getBlurInputMap());
 
 
 			// Perform horizontal blur. Queue and render a full screen quad using a horizontal blur shader
 			// 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.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 			m_renderer.passScreenSpaceDrawCommandsToBackend();
 			m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 
 			// Bind emissive texture for reading so it can be accessed in the shaders
 			// Bind emissive texture for reading so it can be accessed in the shaders
-			m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getEmissiveInputMap(), GeometryBuffer::GBufferInputTexture);
+			m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getBlurInputMap(), GeometryBuffer::GBufferInputTexture);
 
 
 			// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
 			// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
-			m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
+			m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getIntermediateMap());
 
 
 			// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
 			// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
 			m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 			m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 			m_renderer.passScreenSpaceDrawCommandsToBackend();
 			m_renderer.passScreenSpaceDrawCommandsToBackend();
 		}
 		}
 
 
+		// If blending should be enabled
+		if(p_renderPassData.m_blurDoBlending)
+		{
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_ONE, GL_ONE);
+		}
 
 
 		// Bind intermediate blur texture for reading so it can be accessed in the shaders
 		// Bind intermediate blur texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorOutputMap(), GeometryBuffer::GBufferInputTexture);
-
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getIntermediateMap(), GeometryBuffer::GBufferInputTexture);
+		
 		// Bind emissive texture for writing to, so the second pass populates it with the final blur result
 		// Bind emissive texture for writing to, so the second pass populates it with the final blur result
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferEmissive);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getBlurOutputMap());
 
 
 		// Perform horizontal blur. Queue and render a full screen quad using a horizontal blur shader
 		// 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.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
+
+		// If blending should be enabled
+		if(p_renderPassData.m_blurDoBlending)
+			glDisable(GL_BLEND);
 	}
 	}
 
 
 private:
 private:

+ 9 - 9
Praxis3D/Source/Clock.h

@@ -28,7 +28,7 @@ public:
 	const virtual float getElapsedSecondsF() const { return 0.0f; }
 	const virtual float getElapsedSecondsF() const { return 0.0f; }
 
 
 	// Returns the number of elapsed frames since the first update call
 	// Returns the number of elapsed frames since the first update call
-	const virtual unsigned int getElapsedNumFrames() = 0;
+	const virtual size_t getElapsedNumFrames() = 0;
 
 
 	// Returns current number Frames per Second
 	// Returns current number Frames per Second
 	const virtual float getFPS() = 0;
 	const virtual float getFPS() = 0;
@@ -45,8 +45,8 @@ private:
 	LARGE_INTEGER m_timeCurrent;
 	LARGE_INTEGER m_timeCurrent;
 	LARGE_INTEGER m_timeLast;
 	LARGE_INTEGER m_timeLast;
 
 
-	unsigned int m_currentNumFrames;
-	unsigned int m_lastNumFrames;
+	size_t	m_currentNumFrames;
+	size_t	m_lastNumFrames;
 
 
 	float	m_currentFPS,
 	float	m_currentFPS,
 			m_tickSum,
 			m_tickSum,
@@ -56,8 +56,8 @@ private:
 			m_frequency,
 			m_frequency,
 			m_elapsedSeconds;
 			m_elapsedSeconds;
 
 
-	int	m_tickSamples,
-		m_currentTickIndex;
+	size_t	m_tickSamples,
+			m_currentTickIndex;
 
 
 public:
 public:
 	Clock()
 	Clock()
@@ -102,7 +102,7 @@ public:
 
 
 			m_tickList = new float[m_tickSamples]();
 			m_tickList = new float[m_tickSamples]();
 
 
-			for(int i = 0; i < m_tickSamples; i++)
+			for(unsigned int i = 0; i < m_tickSamples; i++)
 				m_tickList[i] = 0.0f;
 				m_tickList[i] = 0.0f;
 
 
 			return ErrorCode::Success;
 			return ErrorCode::Success;
@@ -140,7 +140,7 @@ public:
 
 
 		// Add all the ticks
 		// Add all the ticks
 		m_tickSum = 0.0f;
 		m_tickSum = 0.0f;
-		for(int i = 0; i < m_tickSamples; i++)
+		for(decltype(m_tickSamples) i = 0; i < m_tickSamples; i++)
 			m_tickSum += m_tickList[i];
 			m_tickSum += m_tickList[i];
 
 
 		// Average out the ticks and calculate FPS
 		// Average out the ticks and calculate FPS
@@ -167,7 +167,7 @@ public:
 
 
 	// Number of elapsed frames since the first update call
 	// Number of elapsed frames since the first update call
 	// update() needs to be called once per frame to work accurately
 	// update() needs to be called once per frame to work accurately
-	const unsigned int getElapsedNumFrames() { return m_currentNumFrames; }
+	const size_t getElapsedNumFrames() { return m_currentNumFrames; }
 
 
 	// Returns current number Frames per Second
 	// Returns current number Frames per Second
 	const float getFPS() { return m_currentFPS; }
 	const float getFPS() { return m_currentFPS; }
@@ -202,7 +202,7 @@ public:
 	const double getCurrentTime() { return 0.0; }
 	const double getCurrentTime() { return 0.0; }
 	const float getCurrentTimeF() { return 0.0f; }
 	const float getCurrentTimeF() { return 0.0f; }
 
 
-	const unsigned int getElapsedNumFrames() { return 0; }
+	const size_t getElapsedNumFrames() { return 0; }
 
 
 	const float getFPS() { return 0; }
 	const float getFPS() { return 0; }
 };
 };

+ 23 - 8
Praxis3D/Source/CommonDefinitions.h

@@ -14,13 +14,20 @@ enum CommandType : unsigned int
 	CommandType_Bind,
 	CommandType_Bind,
 	CommandType_Load
 	CommandType_Load
 };
 };
+enum RenderPassType : unsigned int
+{
+	RenderPassType_Geometry,
+	RenderPassType_Lighting,
+	RenderPassType_AtmScattering,
+	RenderPassType_HdrMapping,
+	RenderPassType_Blur,
+	RenderPassType_BloomComposite,
+	RenderPassType_LenseFlare,
+	RenderPassType_LenseFlareComposite,
+	RenderPassType_Final,
+	RenderPassType_NumOfTypes
+};
 
 
-/*
-enum AtmScatteringBufferBinding : unsigned int
-{
-	AtmScatteringBufferBinding_AtmScatParam = LightBufferBinding_Total,
-	AtmScatteringBufferBinding_Total
-};*/
 enum BufferType : unsigned int
 enum BufferType : unsigned int
 {
 {
 	BufferType_Uniform			= GL_UNIFORM_BUFFER,
 	BufferType_Uniform			= GL_UNIFORM_BUFFER,
@@ -93,7 +100,14 @@ enum AtmScatteringTextureType : unsigned int
 	AtmScatteringTextureType_Irradiance = MaterialType_NumOfTypes_Extended,
 	AtmScatteringTextureType_Irradiance = MaterialType_NumOfTypes_Extended,
 	AtmScatteringTextureType_Scattering,
 	AtmScatteringTextureType_Scattering,
 	AtmScatteringTextureType_SingleMie,
 	AtmScatteringTextureType_SingleMie,
-	AtmScatteringTextureType_Transmittance
+	AtmScatteringTextureType_Transmittance,
+	AtmScatteringTextureType_NumOfTypes
+};
+enum LensFlareTextureType : unsigned int
+{
+	LensFlareTextureType_GhostGradient = MaterialType_NumOfTypes_Extended,
+	LensFlareTextureType_LenseDirt,
+	LensFlareTextureType_Starburst
 };
 };
 enum ShaderType : unsigned int
 enum ShaderType : unsigned int
 {
 {
@@ -123,5 +137,6 @@ enum UniformBufferBinding : unsigned int
 {
 {
 	UniformBufferBinding_PointLights,
 	UniformBufferBinding_PointLights,
 	UniformBufferBinding_SpotLights,
 	UniformBufferBinding_SpotLights,
-	UniformBufferBinding_AtmScatParam
+	UniformBufferBinding_AtmScatParam,
+	UniformBufferBinding_LensFlareParam
 };
 };

+ 27 - 1
Praxis3D/Source/Config.cpp

@@ -106,8 +106,11 @@ void Config::init()
 	AddVariablePredef(m_graphicsVar, eye_adaption);
 	AddVariablePredef(m_graphicsVar, eye_adaption);
 	AddVariablePredef(m_graphicsVar, multisampling);
 	AddVariablePredef(m_graphicsVar, multisampling);
 	AddVariablePredef(m_graphicsVar, alpha_size);
 	AddVariablePredef(m_graphicsVar, alpha_size);
+	AddVariablePredef(m_graphicsVar, bloom_blur_passes);
 	AddVariablePredef(m_graphicsVar, dir_shadow_res_x);
 	AddVariablePredef(m_graphicsVar, dir_shadow_res_x);
 	AddVariablePredef(m_graphicsVar, dir_shadow_res_y);
 	AddVariablePredef(m_graphicsVar, dir_shadow_res_y);
+	AddVariablePredef(m_graphicsVar, lens_flare_blur_passes);
+	AddVariablePredef(m_graphicsVar, lens_flare_ghost_count);
 	AddVariablePredef(m_graphicsVar, max_num_point_lights);
 	AddVariablePredef(m_graphicsVar, max_num_point_lights);
 	AddVariablePredef(m_graphicsVar, max_num_spot_lights);
 	AddVariablePredef(m_graphicsVar, max_num_spot_lights);
 	AddVariablePredef(m_graphicsVar, multisample_buffers);
 	AddVariablePredef(m_graphicsVar, multisample_buffers);
@@ -123,6 +126,14 @@ void Config::init()
 	AddVariablePredef(m_graphicsVar, fog_density);
 	AddVariablePredef(m_graphicsVar, fog_density);
 	AddVariablePredef(m_graphicsVar, fov);
 	AddVariablePredef(m_graphicsVar, fov);
 	AddVariablePredef(m_graphicsVar, gamma);
 	AddVariablePredef(m_graphicsVar, gamma);
+	AddVariablePredef(m_graphicsVar, lens_flare_aspect_ratio);
+	AddVariablePredef(m_graphicsVar, lens_flare_chrom_abberration);
+	AddVariablePredef(m_graphicsVar, lens_flare_downsample);
+	AddVariablePredef(m_graphicsVar, lens_flare_ghost_spacing);
+	AddVariablePredef(m_graphicsVar, lens_flare_ghost_threshold);
+	AddVariablePredef(m_graphicsVar, lens_flare_halo_radius);
+	AddVariablePredef(m_graphicsVar, lens_flare_halo_thickness);
+	AddVariablePredef(m_graphicsVar, lens_flare_halo_threshold);
 	AddVariablePredef(m_graphicsVar, light_atten_constant);
 	AddVariablePredef(m_graphicsVar, light_atten_constant);
 	AddVariablePredef(m_graphicsVar, light_atten_linear);
 	AddVariablePredef(m_graphicsVar, light_atten_linear);
 	AddVariablePredef(m_graphicsVar, light_atten_quadratic);
 	AddVariablePredef(m_graphicsVar, light_atten_quadratic);
@@ -222,9 +233,17 @@ void Config::init()
 	AddVariablePredef(m_rendererVar, gaussian_blur_vertical_frag_shader);
 	AddVariablePredef(m_rendererVar, gaussian_blur_vertical_frag_shader);
 	AddVariablePredef(m_rendererVar, gaussian_blur_vertical_vert_shader);
 	AddVariablePredef(m_rendererVar, gaussian_blur_vertical_vert_shader);
 	AddVariablePredef(m_rendererVar, gaussian_blur_horizontal_frag_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, hdr_mapping_pass_frag_shader); 
+	AddVariablePredef(m_rendererVar, hdr_mapping_pass_vert_shader); 
+	AddVariablePredef(m_rendererVar, bloom_composite_pass_vert_shader); 
+	AddVariablePredef(m_rendererVar, bloom_composite_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, blur_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, blur_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, blur_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, blur_pass_frag_shader);
+	AddVariablePredef(m_rendererVar, lense_flare_comp_pass_vert_shader);
+	AddVariablePredef(m_rendererVar, lense_flare_comp_pass_frag_shader);
+	AddVariablePredef(m_rendererVar, lense_flare_pass_vert_shader);
+	AddVariablePredef(m_rendererVar, lense_flare_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, light_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, light_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, light_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, light_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, final_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, final_pass_vert_shader);
@@ -233,6 +252,9 @@ void Config::init()
 	AddVariablePredef(m_rendererVar, final_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, final_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, reflection_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, reflection_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, reflection_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, reflection_pass_frag_shader);
+	AddVariablePredef(m_rendererVar, lens_flare_dirt_texture);
+	AddVariablePredef(m_rendererVar, lens_flare_ghost_gradient_texture);
+	AddVariablePredef(m_rendererVar, lens_flare_starburst_texture);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_x);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_x);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_y);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_y);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_z);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_z);
@@ -309,6 +331,9 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, atmScatteringTextureUniform);
 	AddVariablePredef(m_shaderVar, atmScatteringTextureUniform);
 	AddVariablePredef(m_shaderVar, atmSingleMieScatTextureUniform);
 	AddVariablePredef(m_shaderVar, atmSingleMieScatTextureUniform);
 	AddVariablePredef(m_shaderVar, atmTransmittanceTextureUniform);
 	AddVariablePredef(m_shaderVar, atmTransmittanceTextureUniform);
+	AddVariablePredef(m_shaderVar, lensFlareDirtTextureUniform);
+	AddVariablePredef(m_shaderVar, lensFlareGhostGradientTextureUniform);
+	AddVariablePredef(m_shaderVar, lensFlareStarburstTextureUniform);
 	AddVariablePredef(m_shaderVar, fogDensityUniform);
 	AddVariablePredef(m_shaderVar, fogDensityUniform);
 	AddVariablePredef(m_shaderVar, fogColorUniform);
 	AddVariablePredef(m_shaderVar, fogColorUniform);
 	AddVariablePredef(m_shaderVar, billboardScaleUniform);
 	AddVariablePredef(m_shaderVar, billboardScaleUniform);
@@ -317,6 +342,7 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, eyeAdaptionIntBrightnessUniform);
 	AddVariablePredef(m_shaderVar, eyeAdaptionIntBrightnessUniform);
 	AddVariablePredef(m_shaderVar, HDRSSBuffer);
 	AddVariablePredef(m_shaderVar, HDRSSBuffer);
 	AddVariablePredef(m_shaderVar, atmScatParamBuffer);
 	AddVariablePredef(m_shaderVar, atmScatParamBuffer);
+	AddVariablePredef(m_shaderVar, lensFlareParametersBuffer);
 	AddVariablePredef(m_shaderVar, testMatUniform);
 	AddVariablePredef(m_shaderVar, testMatUniform);
 	AddVariablePredef(m_shaderVar, testVecUniform);
 	AddVariablePredef(m_shaderVar, testVecUniform);
 	AddVariablePredef(m_shaderVar, testFloatUniform);
 	AddVariablePredef(m_shaderVar, testFloatUniform);

+ 50 - 0
Praxis3D/Source/Config.h

@@ -560,10 +560,13 @@ public:
 			eye_adaption = true;
 			eye_adaption = true;
 			multisampling = true;
 			multisampling = true;
 			alpha_size = 8;
 			alpha_size = 8;
+			bloom_blur_passes = 5;
 			current_resolution_x = 0;
 			current_resolution_x = 0;
 			current_resolution_y = 0;
 			current_resolution_y = 0;
 			dir_shadow_res_x = 2048;
 			dir_shadow_res_x = 2048;
 			dir_shadow_res_y = 2048;
 			dir_shadow_res_y = 2048;
+			lens_flare_blur_passes = 5;
+			lens_flare_ghost_count = 4;
 			max_num_point_lights = 50;
 			max_num_point_lights = 50;
 			max_num_spot_lights = 50;
 			max_num_spot_lights = 50;
 			multisample_buffers = 1;
 			multisample_buffers = 1;
@@ -581,6 +584,14 @@ public:
 			fog_density = 0.003f;
 			fog_density = 0.003f;
 			fov = 60.0f;
 			fov = 60.0f;
 			gamma = 2.2f;
 			gamma = 2.2f;
+			lens_flare_aspect_ratio = 1.0f;
+			lens_flare_chrom_abberration = 0.003f;
+			lens_flare_downsample = 0.0f;
+			lens_flare_ghost_spacing = 0.1f;
+			lens_flare_ghost_threshold = 4.0f;
+			lens_flare_halo_radius = 0.55f;
+			lens_flare_halo_thickness = 0.2f;
+			lens_flare_halo_threshold = 4.0f;
 			light_atten_constant = 0.0f;
 			light_atten_constant = 0.0f;
 			light_atten_linear = 0.0f;
 			light_atten_linear = 0.0f;
 			light_atten_quadratic = 1.0f;
 			light_atten_quadratic = 1.0f;
@@ -598,10 +609,13 @@ public:
 		bool eye_adaption;
 		bool eye_adaption;
 		bool multisampling;
 		bool multisampling;
 		int alpha_size;
 		int alpha_size;
+		int bloom_blur_passes;
 		int current_resolution_x;
 		int current_resolution_x;
 		int current_resolution_y;
 		int current_resolution_y;
 		int dir_shadow_res_x;
 		int dir_shadow_res_x;
 		int dir_shadow_res_y;
 		int dir_shadow_res_y;
+		int lens_flare_blur_passes;
+		int lens_flare_ghost_count;
 		int max_num_point_lights;
 		int max_num_point_lights;
 		int max_num_spot_lights;
 		int max_num_spot_lights;
 		int multisample_buffers;
 		int multisample_buffers;
@@ -619,6 +633,14 @@ public:
 		float fog_density;
 		float fog_density;
 		float fov;
 		float fov;
 		float gamma;
 		float gamma;
+		float lens_flare_aspect_ratio;
+		float lens_flare_chrom_abberration;
+		float lens_flare_downsample;
+		float lens_flare_ghost_spacing;
+		float lens_flare_ghost_threshold;
+		float lens_flare_halo_radius;
+		float lens_flare_halo_thickness;
+		float lens_flare_halo_threshold;
 		float light_atten_constant;
 		float light_atten_constant;
 		float light_atten_linear;
 		float light_atten_linear;
 		float light_atten_quadratic;
 		float light_atten_quadratic;
@@ -799,8 +821,14 @@ public:
 			gaussian_blur_horizontal_vert_shader = "gaussianBlurHorizontal.vert";
 			gaussian_blur_horizontal_vert_shader = "gaussianBlurHorizontal.vert";
 			hdr_mapping_pass_frag_shader = "hdrMappingPass.frag";
 			hdr_mapping_pass_frag_shader = "hdrMappingPass.frag";
 			hdr_mapping_pass_vert_shader = "hdrMappingPass.vert";
 			hdr_mapping_pass_vert_shader = "hdrMappingPass.vert";
+			bloom_composite_pass_vert_shader = "bloomCompositePass.vert";
+			bloom_composite_pass_frag_shader = "bloomCompositePass.frag";
 			blur_pass_vert_shader = "blurPass.vert";
 			blur_pass_vert_shader = "blurPass.vert";
 			blur_pass_frag_shader = "blurPass.frag";
 			blur_pass_frag_shader = "blurPass.frag";
+			lense_flare_comp_pass_vert_shader = "lenseFlareCompositePass.vert";
+			lense_flare_comp_pass_frag_shader = "lenseFlareCompositePass.frag";
+			lense_flare_pass_vert_shader = "lenseFlarePass.vert";
+			lense_flare_pass_frag_shader = "lenseFlarePass.frag";
 			light_pass_vert_shader = "lightPass.vert";
 			light_pass_vert_shader = "lightPass.vert";
 			light_pass_frag_shader = "lightPass.frag";
 			light_pass_frag_shader = "lightPass.frag";
 			final_pass_vert_shader = "finalPass.vert";
 			final_pass_vert_shader = "finalPass.vert";
@@ -809,6 +837,9 @@ public:
 			postProcess_pass_frag_shader = "postProcessPass.frag";
 			postProcess_pass_frag_shader = "postProcessPass.frag";
 			reflection_pass_vert_shader = "reflectionPass.vert";
 			reflection_pass_vert_shader = "reflectionPass.vert";
 			reflection_pass_frag_shader = "reflectionPass.frag";
 			reflection_pass_frag_shader = "reflectionPass.frag";
+			lens_flare_dirt_texture = "p3d_lensFlareDirt.png";
+			lens_flare_ghost_gradient_texture = "p3d_lensFlareGhostColorGradient.png";
+			lens_flare_starburst_texture = "p3d_lensFlareStarburst.png";
 			dir_light_quad_offset_x = 0.0f;
 			dir_light_quad_offset_x = 0.0f;
 			dir_light_quad_offset_y = 0.0f;
 			dir_light_quad_offset_y = 0.0f;
 			dir_light_quad_offset_z = 0.0f;
 			dir_light_quad_offset_z = 0.0f;
@@ -853,8 +884,14 @@ public:
 		std::string gaussian_blur_horizontal_vert_shader;
 		std::string gaussian_blur_horizontal_vert_shader;
 		std::string hdr_mapping_pass_frag_shader;
 		std::string hdr_mapping_pass_frag_shader;
 		std::string hdr_mapping_pass_vert_shader;
 		std::string hdr_mapping_pass_vert_shader;
+		std::string bloom_composite_pass_vert_shader;
+		std::string bloom_composite_pass_frag_shader;
 		std::string blur_pass_vert_shader;
 		std::string blur_pass_vert_shader;
 		std::string blur_pass_frag_shader;
 		std::string blur_pass_frag_shader;
+		std::string lense_flare_comp_pass_vert_shader;
+		std::string lense_flare_comp_pass_frag_shader;
+		std::string lense_flare_pass_vert_shader;
+		std::string lense_flare_pass_frag_shader;
 		std::string light_pass_vert_shader;
 		std::string light_pass_vert_shader;
 		std::string light_pass_frag_shader;
 		std::string light_pass_frag_shader;
 		std::string final_pass_vert_shader;
 		std::string final_pass_vert_shader;
@@ -863,6 +900,9 @@ public:
 		std::string postProcess_pass_frag_shader;
 		std::string postProcess_pass_frag_shader;
 		std::string reflection_pass_vert_shader;
 		std::string reflection_pass_vert_shader;
 		std::string reflection_pass_frag_shader;
 		std::string reflection_pass_frag_shader;
+		std::string lens_flare_dirt_texture;
+		std::string lens_flare_ghost_gradient_texture;
+		std::string lens_flare_starburst_texture;
 		float dir_light_quad_offset_x;
 		float dir_light_quad_offset_x;
 		float dir_light_quad_offset_y;
 		float dir_light_quad_offset_y;
 		float dir_light_quad_offset_z;
 		float dir_light_quad_offset_z;
@@ -950,6 +990,10 @@ public:
 			atmSingleMieScatTextureUniform = "atmSingleMieTexture";
 			atmSingleMieScatTextureUniform = "atmSingleMieTexture";
 			atmTransmittanceTextureUniform = "atmTransmitTexture";
 			atmTransmittanceTextureUniform = "atmTransmitTexture";
 
 
+			lensFlareDirtTextureUniform = "lensDirtTexture";
+			lensFlareGhostGradientTextureUniform = "ghostGradientTexture";
+			lensFlareStarburstTextureUniform = "lenseStarburstTexture";
+			
 			dynamicEnvMapUniform = "dynamicEnvMap";
 			dynamicEnvMapUniform = "dynamicEnvMap";
 			staticEnvMapUniform = "staticEnvMap";
 			staticEnvMapUniform = "staticEnvMap";
 
 
@@ -962,6 +1006,7 @@ public:
 			eyeAdaptionIntBrightnessUniform = "eyeAdaptionIntBrightness";
 			eyeAdaptionIntBrightnessUniform = "eyeAdaptionIntBrightness";
 			HDRSSBuffer = "HDRBuffer";
 			HDRSSBuffer = "HDRBuffer";
 			atmScatParamBuffer = "AtmScatParametersBuffer";
 			atmScatParamBuffer = "AtmScatParametersBuffer";
+			lensFlareParametersBuffer = "LensFlareParametersBuffer";
 
 
 			testMatUniform = "testMat";
 			testMatUniform = "testMat";
 			testVecUniform = "testVec";
 			testVecUniform = "testVec";
@@ -1033,6 +1078,10 @@ public:
 		std::string atmScatteringTextureUniform;
 		std::string atmScatteringTextureUniform;
 		std::string atmSingleMieScatTextureUniform;
 		std::string atmSingleMieScatTextureUniform;
 		std::string atmTransmittanceTextureUniform;
 		std::string atmTransmittanceTextureUniform;
+		
+		std::string lensFlareDirtTextureUniform;
+		std::string lensFlareGhostGradientTextureUniform;
+		std::string lensFlareStarburstTextureUniform;
 
 
 		std::string dynamicEnvMapUniform;
 		std::string dynamicEnvMapUniform;
 		std::string staticEnvMapUniform;
 		std::string staticEnvMapUniform;
@@ -1046,6 +1095,7 @@ public:
 		std::string eyeAdaptionIntBrightnessUniform;
 		std::string eyeAdaptionIntBrightnessUniform;
 		std::string HDRSSBuffer;
 		std::string HDRSSBuffer;
 		std::string atmScatParamBuffer;
 		std::string atmScatParamBuffer;
+		std::string lensFlareParametersBuffer;
 
 
 		std::string testMatUniform;
 		std::string testMatUniform;
 		std::string testVecUniform;
 		std::string testVecUniform;

+ 1 - 1
Praxis3D/Source/ConfigLoader.cpp

@@ -228,7 +228,7 @@ ConfigFile::BaseValue *ConfigFile::getValueNode(std::string p_value)
 	int decimalPoints = 0, commas = 0;
 	int decimalPoints = 0, commas = 0;
 	for(std::vector<std::string>::size_type i = 0; i < p_value.size(); i++)
 	for(std::vector<std::string>::size_type i = 0; i < p_value.size(); i++)
 	{
 	{
-		if(isalpha(p_value[i]) && (i < p_value.size() || p_value[i] != 'f'))	// If value is string
+		if(isalpha(p_value.c_str()[i]) && (i < p_value.size() || p_value[i] != 'f'))	// If value is string
 			return new StringValue(p_value);
 			return new StringValue(p_value);
 
 
 		if(p_value[i] == '.')
 		if(p_value[i] == '.')

+ 6 - 0
Praxis3D/Source/FinalPass.h

@@ -57,6 +57,12 @@ public:
 
 
 		glDisable(GL_DEPTH_TEST);
 		glDisable(GL_DEPTH_TEST);
 		
 		
+		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
 		// Bind final texture for reading so it can be accessed in the shaders
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);

+ 50 - 0
Praxis3D/Source/GraphicsDataSets.h

@@ -272,4 +272,54 @@ struct AtmScatteringParameters
 	float m_padding4;
 	float m_padding4;
 
 
 	AtmosphereParameters m_atmosphereParam;
 	AtmosphereParameters m_atmosphereParam;
+};
+
+// Parameters for lens flare effect
+struct LensFlareParameters
+{
+	LensFlareParameters()
+	{
+		m_ghostCount = 0;
+		m_ghostSpacing = 0.0f;
+		m_ghostThreshold = 0.0f;
+		m_haloAspectRatio = 0.0f;
+		m_haloRadius = 0.0f;
+		m_haloThickness = 0.0f;
+		m_haloThreshold = 0.0f;
+		m_chromaticAberration = 0.0f;
+		m_lensFlaireDownsample = 0.0f;
+	}
+
+	LensFlareParameters(
+		int p_ghostCount,
+		float p_ghostSpacing,
+		float p_ghostThreshold,
+		float p_haloAspectRatio,
+		float p_haloRadius,
+		float p_haloThickness,
+		float p_haloThreshold,
+		float p_chromaticAberration,
+		float p_lensFlaireDownsample,
+		float p_starburstOffset): 
+		m_ghostCount(p_ghostCount),
+		m_ghostSpacing(p_ghostSpacing),
+		m_ghostThreshold(p_ghostThreshold),
+		m_haloAspectRatio(p_haloAspectRatio),
+		m_haloRadius(p_haloRadius),
+		m_haloThickness(p_haloThickness),
+		m_haloThreshold(p_haloThreshold),
+		m_chromaticAberration(p_chromaticAberration),
+		m_lensFlaireDownsample(p_lensFlaireDownsample){ }
+
+	int m_ghostCount;
+	float m_ghostSpacing;
+	float m_ghostThreshold;
+
+	float m_haloAspectRatio;
+	float m_haloRadius;
+	float m_haloThickness;
+	float m_haloThreshold;
+	
+	float m_chromaticAberration;
+	float m_lensFlaireDownsample;
 };
 };

+ 8 - 4
Praxis3D/Source/HdrMappingPass.h

@@ -63,16 +63,14 @@ public:
 		if(Config::graphicsVar().eye_adaption)
 		if(Config::graphicsVar().eye_adaption)
 		{
 		{
 			// Generate mipmaps for the final buffer, for use in tone mapping
 			// Generate mipmaps for the final buffer, for use in tone mapping
-			m_renderer.m_backend.getGeometryBuffer()->generateMipmap(GeometryBuffer::GBufferFinal);
+			//m_renderer.m_backend.getGeometryBuffer()->generateMipmap(GeometryBuffer::GBufferFinal);
 		}
 		}
 
 
 		p_renderPassData.setEmissiveInputMap(GeometryBuffer::GBufferDiffuse);
 		p_renderPassData.setEmissiveInputMap(GeometryBuffer::GBufferDiffuse);
 
 
 		m_emissiveAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getEmissiveInputMap());
 		m_emissiveAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getEmissiveInputMap());
 		m_emissiveAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getColorOutputMap());
 		m_emissiveAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getColorOutputMap());
-
-		m_renderer.m_backend.getGeometryBuffer()->generateMipmap(GeometryBuffer::GBufferFinal);
-
+		
 		// Set the default framebuffer to be drawn to
 		// Set the default framebuffer to be drawn to
 		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
 		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
 		
 		
@@ -92,6 +90,12 @@ public:
 		m_renderer.queueForDrawing(m_hdrMappingShader->getShaderHandle(), m_hdrMappingShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.queueForDrawing(m_hdrMappingShader->getShaderHandle(), m_hdrMappingShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 		
 		
+		p_renderPassData.setBlurInputMap(p_renderPassData.getEmissiveInputMap());
+		p_renderPassData.setBlurOutputMap(GeometryBuffer::GBufferEmissive);
+		p_renderPassData.setIntermediateMap(p_renderPassData.getColorInputMap());
+		p_renderPassData.m_blurDoBlending = false;
+		p_renderPassData.m_numOfBlurPasses = Config::graphicsVar().bloom_blur_passes;
+
 		p_renderPassData.swapColorInputOutputMaps();
 		p_renderPassData.swapColorInputOutputMaps();
 	}
 	}
 
 

+ 95 - 0
Praxis3D/Source/LenseFlareCompositePass.h

@@ -0,0 +1,95 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class LenseFlareCompositePass : public RenderPass
+{
+public:
+	LenseFlareCompositePass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer), 
+		m_lensFlareDirt(Loaders::texture2D().load(Config::rendererVar().lens_flare_dirt_texture)),
+		m_lenseFlareStarburst(Loaders::texture2D().load(Config::rendererVar().lens_flare_starburst_texture))
+	{
+		
+	}
+
+	~LenseFlareCompositePass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError = ErrorCode::Success;
+
+		m_name = "Lense Flare Composite Rendering Pass";
+		
+		// Set buffer values
+		m_diffuseAndOutputBuffers.resize(2);
+		m_diffuseAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferDiffuse);
+		m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferFinal);
+
+		// Create a property-set used to load blur vertical shaders
+		PropertySet shaderProperties(Properties::Shaders);
+		shaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().lense_flare_comp_pass_vert_shader);
+		shaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().lense_flare_comp_pass_frag_shader);
+
+		// Create shaders
+		m_lenseFlareShader = Loaders::shader().load(shaderProperties);
+
+		//		 _______________________________
+		//		|	 LOAD LENSE FLARE SHADER	|
+		//		|_______________________________|
+		shaderError = m_lenseFlareShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)					// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_lenseFlareShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+		
+		// Create textures for lens flare effect and load them to memory
+		m_lensFlareDirt.loadToMemory();
+		m_lenseFlareStarburst.loadToMemory();
+		
+		// Queue lens flare textures for loading to GPU
+		m_renderer.queueForLoading(m_lensFlareDirt);
+		m_renderer.queueForLoading(m_lenseFlareStarburst);
+
+		return returnError;
+	}
+
+	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	{
+		glDisable(GL_DEPTH_TEST);
+		
+		// Set the output buffer
+		//m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getColorOutputMap());
+
+		// Bind input color texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferDiffuse, GeometryBuffer::GBufferDiffuse);
+		
+		// Bind textures for writing
+		//m_renderer.m_backend.getGeometryBuffer()->bindBuffersForWriting(m_diffuseAndOutputBuffers);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
+
+		// Bind lens flare textures
+		glActiveTexture(GL_TEXTURE0 + LensFlareTextureType::LensFlareTextureType_LenseDirt);
+		glBindTexture(GL_TEXTURE_2D, m_lensFlareDirt.getHandle());
+		glActiveTexture(GL_TEXTURE0 + LensFlareTextureType::LensFlareTextureType_Starburst);
+		glBindTexture(GL_TEXTURE_2D, m_lenseFlareStarburst.getHandle());
+
+		// Perform various visual effects in the post process shader
+		m_renderer.queueForDrawing(m_lenseFlareShader->getShaderHandle(), m_lenseFlareShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.passScreenSpaceDrawCommandsToBackend();
+		
+		p_renderPassData.swapColorInputOutputMaps();
+	}
+
+private:
+	// Buffer handles used for binding
+	std::vector<GeometryBuffer::GBufferTexture> m_diffuseAndOutputBuffers;
+
+	ShaderLoader::ShaderProgram	*m_lenseFlareShader;
+
+	TextureLoader2D::Texture2DHandle	m_lensFlareDirt,
+										m_lenseFlareStarburst;
+};

+ 116 - 0
Praxis3D/Source/LenseFlarePass.h

@@ -0,0 +1,116 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class LenseFlarePass : public RenderPass
+{
+public:
+	LenseFlarePass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer), 
+		m_lensFlareParamBuffer(BufferType_Uniform, BufferUsageHint_DynamicDraw),
+		m_lensFlareGhostGradient(Loaders::texture2D().load(Config::rendererVar().lens_flare_ghost_gradient_texture))
+	{
+		m_lensFlareParam.m_lensFlaireDownsample = Config::graphicsVar().lens_flare_downsample;
+		m_lensFlareParam.m_chromaticAberration = Config::graphicsVar().lens_flare_chrom_abberration;
+		m_lensFlareParam.m_ghostCount = Config::graphicsVar().lens_flare_ghost_count;
+		m_lensFlareParam.m_ghostSpacing  = Config::graphicsVar().lens_flare_ghost_spacing;
+		m_lensFlareParam.m_ghostThreshold = Config::graphicsVar().lens_flare_ghost_threshold;
+		m_lensFlareParam.m_haloRadius = Config::graphicsVar().lens_flare_halo_radius;
+		m_lensFlareParam.m_haloThickness = Config::graphicsVar().lens_flare_halo_thickness;
+		m_lensFlareParam.m_haloThreshold = Config::graphicsVar().lens_flare_halo_threshold;
+		m_lensFlareParam.m_haloAspectRatio = 1600.0f / 900.0f;// Config::graphicsVar().lens_flare_aspect_ratio;
+	}
+
+	~LenseFlarePass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError;
+
+		m_name = "Lense Flare Rendering Pass";
+		
+		// Set buffer values
+		m_diffuseAndOutputBuffers.resize(2);
+		m_diffuseAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferDiffuse);
+		m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferFinal);
+
+		// Create a property-set used to load blur vertical shaders
+		PropertySet shaderProperties(Properties::Shaders);
+		shaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().lense_flare_pass_vert_shader);
+		shaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().lense_flare_pass_frag_shader);
+
+		// Create shaders
+		m_lenseFlareShader = Loaders::shader().load(shaderProperties);
+
+		//		 _______________________________
+		//		|	 LOAD LENSE FLARE SHADER	|
+		//		|_______________________________|
+		shaderError = m_lenseFlareShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)					// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_lenseFlareShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+		
+		// Set lens flare parameters buffer shader binding index
+		m_lensFlareParamBuffer.m_bindingIndex = UniformBufferBinding_LensFlareParam;
+
+		// Set lens flare parameters buffer size and data
+		m_lensFlareParamBuffer.m_size = sizeof(LensFlareParameters);
+		m_lensFlareParamBuffer.m_data = (void*)(&m_lensFlareParam);
+
+		// Queue lens flare parameters buffer to be created
+		m_renderer.queueForLoading(m_lensFlareParamBuffer);
+
+		// Create textures for lens flare effect and load them to memory
+		m_lensFlareGhostGradient.loadToMemory();
+		
+		// Queue lens flare textures for loading to GPU
+		m_renderer.queueForLoading(m_lensFlareGhostGradient);
+
+		return returnError;
+	}
+
+	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	{
+		glDisable(GL_DEPTH_TEST);
+		
+		// Set the output buffer
+		m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getColorOutputMap());
+
+		// Bind input color texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
+		//m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
+		
+		// Bind textures for writing
+		//m_renderer.m_backend.getGeometryBuffer()->bindBuffersForWriting(m_diffuseAndOutputBuffers);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferDiffuse);
+
+		// Bind lens flare textures
+		glActiveTexture(GL_TEXTURE0 + LensFlareTextureType::LensFlareTextureType_GhostGradient);
+		glBindTexture(GL_TEXTURE_2D, m_lensFlareGhostGradient.getHandle());
+
+		// Perform various visual effects in the post process shader
+		m_renderer.queueForDrawing(m_lenseFlareShader->getShaderHandle(), m_lenseFlareShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.passScreenSpaceDrawCommandsToBackend();
+
+		p_renderPassData.setBlurInputMap(GeometryBuffer::GBufferDiffuse);
+		p_renderPassData.setBlurOutputMap(GeometryBuffer::GBufferDiffuse);
+		p_renderPassData.setIntermediateMap(p_renderPassData.getColorOutputMap());
+		p_renderPassData.m_blurDoBlending = false;
+		p_renderPassData.m_numOfBlurPasses = Config::graphicsVar().lens_flare_blur_passes;
+	}
+
+private:
+	// Buffer handles used for binding
+	std::vector<GeometryBuffer::GBufferTexture> m_diffuseAndOutputBuffers;
+
+	ShaderLoader::ShaderProgram	*m_lenseFlareShader;
+
+	RendererFrontend::ShaderBuffer m_lensFlareParamBuffer;
+
+	LensFlareParameters m_lensFlareParam;
+
+	TextureLoader2D::Texture2DHandle m_lensFlareGhostGradient;
+};

+ 1 - 0
Praxis3D/Source/LoaderBase.h

@@ -41,6 +41,7 @@ public:
 			m_refCounter--;
 			m_refCounter--;
 			if(m_refCounter == 0)
 			if(m_refCounter == 0)
 			{
 			{
+				// TODO: queue texture unload uppon reference counter reaching zero
 				//m_loaderBase->queueUnload(*this);
 				//m_loaderBase->queueUnload(*this);
 			}
 			}
 		}
 		}

+ 0 - 6
Praxis3D/Source/ObjectPool.h

@@ -128,13 +128,7 @@ public:
 			m_firstAvailable = newObject->getNext();
 			m_firstAvailable = newObject->getNext();
 
 
 			// Allocate the template object
 			// Allocate the template object
-			//new (newObject->m_object) T_Object(p_object);
-			//newObject->m_object = new T_Object(p_object);
-
 			new (static_cast<void*>(newObject->m_object)) T_Object(std::move(p_object));
 			new (static_cast<void*>(newObject->m_object)) T_Object(std::move(p_object));
-
-			//*newObject->m_object = std::move(p_object);
-
 			newObject->m_allocated = true;
 			newObject->m_allocated = true;
 
 
 			// Make this object the last one added
 			// Make this object the last one added

+ 56 - 3
Praxis3D/Source/PostProcessPass.h

@@ -7,7 +7,20 @@ class PostProcessPass : public RenderPass
 {
 {
 public:
 public:
 	PostProcessPass(RendererFrontend &p_renderer) :
 	PostProcessPass(RendererFrontend &p_renderer) :
-		RenderPass(p_renderer) { }
+		RenderPass(p_renderer), 
+		m_lensFlareParamBuffer(BufferType_Uniform, BufferUsageHint_DynamicDraw),
+		m_lensFlareGhostGradient(Loaders::texture2D().load(Config::rendererVar().lens_flare_ghost_gradient_texture))
+	{
+		m_lensFlareParam.m_lensFlaireDownsample = 0.0f;
+		m_lensFlareParam.m_chromaticAberration = 0.01f;
+		m_lensFlareParam.m_ghostCount = 4;
+		m_lensFlareParam.m_ghostSpacing = 0.1f;
+		m_lensFlareParam.m_ghostThreshold = 2.0f;
+		m_lensFlareParam.m_haloRadius = 0.6f;
+		m_lensFlareParam.m_haloThickness = 0.1f;
+		m_lensFlareParam.m_haloThreshold = 2.0f;
+		m_lensFlareParam.m_haloAspectRatio = 1.0f;
+	}
 
 
 	~PostProcessPass() { }
 	~PostProcessPass() { }
 
 
@@ -17,6 +30,11 @@ public:
 		ErrorCode shaderError;
 		ErrorCode shaderError;
 
 
 		m_name = "Post Process Rendering Pass";
 		m_name = "Post Process Rendering Pass";
+		
+		// Set buffer values
+		m_diffuseAndOutputBuffers.resize(2);
+		m_diffuseAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferDiffuse);
+		m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferFinal);
 
 
 		// Create a property-set used to load blur vertical shaders
 		// Create a property-set used to load blur vertical shaders
 		PropertySet postProcessShaderProperties(Properties::Shaders);
 		PropertySet postProcessShaderProperties(Properties::Shaders);
@@ -34,6 +52,24 @@ public:
 			m_renderer.queueForLoading(*m_postProcessShader);	// Queue the shader to be loaded to GPU
 			m_renderer.queueForLoading(*m_postProcessShader);	// Queue the shader to be loaded to GPU
 		else
 		else
 			returnError = shaderError;
 			returnError = shaderError;
+		
+		// Set lens flare parameters buffer shader binding index
+		m_lensFlareParamBuffer.m_bindingIndex = UniformBufferBinding_LensFlareParam;
+
+		// Set lens flare parameters buffer size and data
+		m_lensFlareParamBuffer.m_size = sizeof(LensFlareParameters);
+		m_lensFlareParamBuffer.m_data = (void*)(&m_lensFlareParam);
+
+		// Queue lens flare parameters buffer to be created
+		m_renderer.queueForLoading(m_lensFlareParamBuffer);
+
+		// Create textures for lens flare effect and load them to memory
+		m_lensFlareGhostGradient.loadToMemory();
+		
+		// Queue lens flare textures for loading to GPU
+		m_renderer.queueForLoading(m_lensFlareGhostGradient);
+
+		//Loaders::texture2D().load(m_materialNames.m_materials[matType][i].m_filename, static_cast<MaterialType>(matType), false)
 
 
 		return returnError;
 		return returnError;
 	}
 	}
@@ -41,12 +77,20 @@ public:
 	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
 	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
 	{
 	{
 		glDisable(GL_DEPTH_TEST);
 		glDisable(GL_DEPTH_TEST);
+		
+		// Set the output buffer
+		m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getColorOutputMap());
 
 
 		// Bind input color texture for reading so it can be accessed in the shaders
 		// Bind input color texture for reading so it can be accessed in the shaders
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
+		//m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
+		
+		// Bind textures for writing
+		m_renderer.m_backend.getGeometryBuffer()->bindBuffersForWriting(m_diffuseAndOutputBuffers);
 
 
-		// Bind output color texture for writing to, so it can be used as an intermediate buffer between blur passes
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
+		// Bind lens flare textures
+		glActiveTexture(GL_TEXTURE0 + LensFlareTextureType::LensFlareTextureType_GhostGradient);
+		glBindTexture(GL_TEXTURE_2D, m_lensFlareGhostGradient.getHandle());
 
 
 		// Perform various visual effects in the post process shader
 		// Perform various visual effects in the post process shader
 		m_renderer.queueForDrawing(m_postProcessShader->getShaderHandle(), m_postProcessShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.queueForDrawing(m_postProcessShader->getShaderHandle(), m_postProcessShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
@@ -56,5 +100,14 @@ public:
 	}
 	}
 
 
 private:
 private:
+	// Buffer handles used for binding
+	std::vector<GeometryBuffer::GBufferTexture> m_diffuseAndOutputBuffers;
+
 	ShaderLoader::ShaderProgram	*m_postProcessShader;
 	ShaderLoader::ShaderProgram	*m_postProcessShader;
+
+	RendererFrontend::ShaderBuffer m_lensFlareParamBuffer;
+
+	LensFlareParameters m_lensFlareParam;
+
+	TextureLoader2D::Texture2DHandle m_lensFlareGhostGradient;
 };
 };

+ 1 - 1
Praxis3D/Source/PropertyLoader.cpp

@@ -281,7 +281,7 @@ void PropertyLoader::loadProperty(PropertySet &p_propertySet, const Properties::
 		//|	 String value	|
 		//|	 String value	|
 		//|_________________|
 		//|_________________|
 		// If current character is alphabetic (unless it's the last character and is 'f')
 		// If current character is alphabetic (unless it's the last character and is 'f')
-		if(isalpha(p_string[i]) && (i < size && p_string[i] != 'f'))
+		if(isalpha(p_string.c_str()[i]) && (i < size && p_string[i] != 'f'))
 		{
 		{
 			// Convert string to property ID
 			// Convert string to property ID
 			Properties::PropertyID propertyID = Properties::toPropertyID(p_string);
 			Properties::PropertyID propertyID = Properties::toPropertyID(p_string);

+ 1 - 1
Praxis3D/Source/ReflectionPass.h

@@ -11,7 +11,7 @@ public:
 
 
 	ErrorCode init()
 	ErrorCode init()
 	{
 	{
-		ErrorCode returnError;
+		ErrorCode returnError = ErrorCode::Success;
 
 
 		m_name = "Reflection Rendering Pass";
 		m_name = "Reflection Rendering Pass";
 
 

+ 24 - 1
Praxis3D/Source/RenderPassBase.h

@@ -13,7 +13,16 @@ struct RenderPassData
 		m_colorOutputMap = GeometryBuffer::GBufferFinal;
 		m_colorOutputMap = GeometryBuffer::GBufferFinal;
 		m_emissiveInputMap = GeometryBuffer::GBufferEmissive;
 		m_emissiveInputMap = GeometryBuffer::GBufferEmissive;
 
 
+		m_blurInputMap = GeometryBuffer::GBufferEmissive;
+		m_blurOutputMap = GeometryBuffer::GBufferEmissive;
+		m_blurBlendingMap = GeometryBuffer::GBufferFinal;
+
+		m_intermediateMap = GeometryBuffer::GBufferIntermediate;
+
+		m_numOfBlurPasses = 1;
+
 		m_atmScatDoSkyPass = true;
 		m_atmScatDoSkyPass = true;
+		m_blurDoBlending = false;
 	}
 	}
 
 
 	inline void swapColorInputOutputMaps()
 	inline void swapColorInputOutputMaps()
@@ -27,18 +36,32 @@ struct RenderPassData
 	inline void setColorInputMap(GeometryBuffer::GBufferTextureType p_inputColorMap)		{ m_colorInputMap = p_inputColorMap;		}
 	inline void setColorInputMap(GeometryBuffer::GBufferTextureType p_inputColorMap)		{ m_colorInputMap = p_inputColorMap;		}
 	inline void setColorOutputMap(GeometryBuffer::GBufferTextureType p_outputColorMap)		{ m_colorOutputMap = p_outputColorMap;		}
 	inline void setColorOutputMap(GeometryBuffer::GBufferTextureType p_outputColorMap)		{ m_colorOutputMap = p_outputColorMap;		}
 	inline void setEmissiveInputMap(GeometryBuffer::GBufferTextureType p_emissiveInputMap)	{ m_emissiveInputMap = p_emissiveInputMap;	}
 	inline void setEmissiveInputMap(GeometryBuffer::GBufferTextureType p_emissiveInputMap)	{ m_emissiveInputMap = p_emissiveInputMap;	}
+	inline void setBlurInputMap(GeometryBuffer::GBufferTextureType p_blurInputMap)			{ m_blurInputMap = p_blurInputMap;			}
+	inline void setBlurOutputMap(GeometryBuffer::GBufferTextureType p_blurOutputMap)		{ m_blurOutputMap = p_blurOutputMap;		}
+	inline void setBlurBlendingMap(GeometryBuffer::GBufferTextureType p_blurBlendingMap)	{ m_blurBlendingMap = p_blurBlendingMap;	}
+	inline void setIntermediateMap(GeometryBuffer::GBufferTextureType p_intermediateMap)	{ m_intermediateMap = p_intermediateMap;	}
 
 
 	// Getters
 	// Getters
 	const inline GeometryBuffer::GBufferTextureType getColorInputMap() const	{ return m_colorInputMap;		}
 	const inline GeometryBuffer::GBufferTextureType getColorInputMap() const	{ return m_colorInputMap;		}
 	const inline GeometryBuffer::GBufferTextureType getColorOutputMap() const	{ return m_colorOutputMap;		}
 	const inline GeometryBuffer::GBufferTextureType getColorOutputMap() const	{ return m_colorOutputMap;		}
 	const inline GeometryBuffer::GBufferTextureType getEmissiveInputMap() const { return m_emissiveInputMap;	}
 	const inline GeometryBuffer::GBufferTextureType getEmissiveInputMap() const { return m_emissiveInputMap;	}
+	const inline GeometryBuffer::GBufferTextureType getBlurInputMap() const		{ return m_blurInputMap;		}
+	const inline GeometryBuffer::GBufferTextureType getBlurOutputMap() const	{ return m_blurOutputMap;		}
+	const inline GeometryBuffer::GBufferTextureType getBlurBlendingMap() const	{ return m_blurBlendingMap;		}
+	const inline GeometryBuffer::GBufferTextureType getIntermediateMap() const	{ return m_intermediateMap;		}
 
 
 	// Remember which color maps to write to and read from, in different rendering passes.
 	// Remember which color maps to write to and read from, in different rendering passes.
 	GeometryBuffer::GBufferTextureType	m_colorInputMap,
 	GeometryBuffer::GBufferTextureType	m_colorInputMap,
 										m_colorOutputMap,
 										m_colorOutputMap,
-										m_emissiveInputMap;
+										m_emissiveInputMap,
+										m_blurInputMap,
+										m_blurOutputMap,
+										m_blurBlendingMap,
+										m_intermediateMap;
 
 
+	unsigned int m_numOfBlurPasses;
 	bool m_atmScatDoSkyPass;
 	bool m_atmScatDoSkyPass;
+	bool m_blurDoBlending;
 };
 };
 
 
 class RenderPass
 class RenderPass

+ 13 - 13
Praxis3D/Source/RendererBackend.h

@@ -452,20 +452,20 @@ protected:
 	{
 	{
 		// Check if the texture uniforms haven't been updated already
 		// Check if the texture uniforms haven't been updated already
 		//if(m_rendererState.m_lastTexUpdate != p_shaderHandle)
 		//if(m_rendererState.m_lastTexUpdate != p_shaderHandle)
-		{
+		//{
 			// Declare uniform data
 			// Declare uniform data
 			UniformData uniformData(p_objectData, p_frameData);
 			UniformData uniformData(p_objectData, p_frameData);
 
 
 			// Update texture uniforms
 			// Update texture uniforms
 			p_uniformUpdater.updateTextureUniforms(uniformData);
 			p_uniformUpdater.updateTextureUniforms(uniformData);
 			m_rendererState.m_lastTexUpdate = p_shaderHandle;
 			m_rendererState.m_lastTexUpdate = p_shaderHandle;
-		}
+		//}
 	}
 	}
 	inline void frameUniformUpdate(const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const UniformObjectData &p_objectData, const UniformFrameData &p_frameData)
 	inline void frameUniformUpdate(const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const UniformObjectData &p_objectData, const UniformFrameData &p_frameData)
 	{
 	{
 		// Check if the frame uniforms haven't been updated already
 		// Check if the frame uniforms haven't been updated already
 		//if(m_rendererState.m_lastFrameUpdate != p_shaderHandle)
 		//if(m_rendererState.m_lastFrameUpdate != p_shaderHandle)
-		{
+		//{
 			bindShader(p_shaderHandle);
 			bindShader(p_shaderHandle);
 
 
 			// Declare uniform data
 			// Declare uniform data
@@ -474,33 +474,33 @@ protected:
 			// Update frame uniforms
 			// Update frame uniforms
 			p_uniformUpdater.updateFrame(uniformData);
 			p_uniformUpdater.updateFrame(uniformData);
 			m_rendererState.m_lastFrameUpdate = p_shaderHandle;
 			m_rendererState.m_lastFrameUpdate = p_shaderHandle;
-		}
+		//}
 	}
 	}
 	inline void modelUniformUpdate(const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const UniformObjectData &p_objectData, const UniformFrameData &p_frameData)
 	inline void modelUniformUpdate(const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const UniformObjectData &p_objectData, const UniformFrameData &p_frameData)
 	{
 	{
 		// Check if the model uniforms haven't been updated already
 		// Check if the model uniforms haven't been updated already
 		//if(m_rendererState.m_lastModelUpdate != p_shaderHandle)
 		//if(m_rendererState.m_lastModelUpdate != p_shaderHandle)
-		{
+		//{
 			// Declare uniform data
 			// Declare uniform data
 			UniformData uniformData(p_objectData, p_frameData);
 			UniformData uniformData(p_objectData, p_frameData);
 			
 			
 			// Update model uniforms
 			// Update model uniforms
 			p_uniformUpdater.updateModel(uniformData);
 			p_uniformUpdater.updateModel(uniformData);
 			m_rendererState.m_lastModelUpdate = p_shaderHandle;
 			m_rendererState.m_lastModelUpdate = p_shaderHandle;
-		}
+		//}
 	}
 	}
 	inline void meshUniformUpdate(const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const UniformObjectData &p_objectData, const UniformFrameData &p_frameData)
 	inline void meshUniformUpdate(const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const UniformObjectData &p_objectData, const UniformFrameData &p_frameData)
 	{
 	{
 		// Check if the mesh uniforms haven't been updated already
 		// Check if the mesh uniforms haven't been updated already
 		//if(m_rendererState.m_lastMeshUpdate != p_shaderHandle)
 		//if(m_rendererState.m_lastMeshUpdate != p_shaderHandle)
-		{
+		//{
 			// Declare uniform data
 			// Declare uniform data
 			UniformData uniformData(p_objectData, p_frameData);
 			UniformData uniformData(p_objectData, p_frameData);
 
 
 			// Update mesh uniforms
 			// Update mesh uniforms
 			p_uniformUpdater.updateMesh(uniformData);
 			p_uniformUpdater.updateMesh(uniformData);
 			m_rendererState.m_lastMeshUpdate = p_shaderHandle;
 			m_rendererState.m_lastMeshUpdate = p_shaderHandle;
-		}
+		//}
 	}
 	}
 	
 	
 	inline void processCommand(const DrawCommand &p_command, const UniformFrameData &p_frameData)
 	inline void processCommand(const DrawCommand &p_command, const UniformFrameData &p_frameData)
@@ -650,7 +650,7 @@ protected:
 						shaderHandles[i] = glCreateShader(shaderTypes[i]);
 						shaderHandles[i] = glCreateShader(shaderTypes[i]);
 
 
 						// Check for errors
 						// Check for errors
-						GLenum glError = glGetError();
+						glError = glGetError();
 						if(glError != GL_NO_ERROR)
 						if(glError != GL_NO_ERROR)
 						{
 						{
 							// Log an error with a shader info log
 							// Log an error with a shader info log
@@ -674,7 +674,7 @@ protected:
 							glGetShaderiv(shaderHandles[i], GL_COMPILE_STATUS, &shaderCompileResult);
 							glGetShaderiv(shaderHandles[i], GL_COMPILE_STATUS, &shaderCompileResult);
 
 
 							// Check for errors
 							// Check for errors
-							GLenum glError = glGetError();
+							glError = glGetError();
 							// If compilation failed
 							// If compilation failed
 							if(shaderCompileResult == 0)
 							if(shaderCompileResult == 0)
 							{
 							{
@@ -688,8 +688,8 @@ protected:
 
 
 								// Convert vector of chars to a string
 								// Convert vector of chars to a string
 								std::string errorMessageTemp;
 								std::string errorMessageTemp;
-								for(int i = 0; shaderCompileErrorMessage[i]; i++)
-									errorMessageTemp += shaderCompileErrorMessage[i];
+								for(int j = 0; shaderCompileErrorMessage[j]; j++)
+									errorMessageTemp += shaderCompileErrorMessage[j];
 
 
 								// Log an error with a shader info log
 								// Log an error with a shader info log
 								p_command.m_objectData.m_shaderData.m_errorMessages[i].m_errorCode = ErrorCode::Shader_compile_failed;
 								p_command.m_objectData.m_shaderData.m_errorMessages[i].m_errorCode = ErrorCode::Shader_compile_failed;
@@ -710,7 +710,7 @@ protected:
 								glAttachShader(p_command.m_handle, shaderHandles[i]);
 								glAttachShader(p_command.m_handle, shaderHandles[i]);
 
 
 								// Check for errors
 								// Check for errors
-								GLenum glError = glGetError();
+								glError = glGetError();
 								if(glError != GL_NO_ERROR)
 								if(glError != GL_NO_ERROR)
 								{
 								{
 									// Reset the shader handle
 									// Reset the shader handle

+ 93 - 46
Praxis3D/Source/RendererFrontend.cpp

@@ -1,7 +1,10 @@
 
 
 #include "AtmScatteringPass.h"
 #include "AtmScatteringPass.h"
+#include "BloomCompositePass.h"
 #include "BlurPass.h"
 #include "BlurPass.h"
 #include "GeometryPass.h"
 #include "GeometryPass.h"
+#include "LenseFlareCompositePass.h"
+#include "LenseFlarePass.h"
 #include "LightingPass.h"
 #include "LightingPass.h"
 #include "FinalPass.h"
 #include "FinalPass.h"
 #include "HdrMappingPass.h"
 #include "HdrMappingPass.h"
@@ -10,6 +13,70 @@
 #include "RendererFrontend.h"
 #include "RendererFrontend.h"
 #include "SkyPass.h"
 #include "SkyPass.h"
 
 
+RendererFrontend::RendererFrontend()
+{
+	// Set up the order of the rendering passes
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Geometry);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_AtmScattering);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Lighting);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_AtmScattering);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_HdrMapping);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Blur);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_BloomComposite);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_LenseFlare);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Blur);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_LenseFlareComposite);
+	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Final);
+
+	// Make sure the entries of the rendering passes are set to nullptr
+	for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
+		m_initializedRenderingPasses[i] = nullptr;
+
+	// Create rendering passes
+	for(decltype(m_renderingPassesTypes.size()) i = 0, size = m_renderingPassesTypes.size(); i < size; i++)
+	{
+		switch(m_renderingPassesTypes[i])
+		{
+		case RenderPassType_Geometry:
+			if(m_initializedRenderingPasses[RenderPassType_Geometry] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Geometry] = new GeometryPass(*this);
+			break;
+		case RenderPassType_Lighting:
+			if(m_initializedRenderingPasses[RenderPassType_Lighting] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Lighting] = new LightingPass(*this);
+			break;
+		case RenderPassType_AtmScattering:
+			if(m_initializedRenderingPasses[RenderPassType_AtmScattering] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_AtmScattering] = new AtmScatteringPass(*this);
+			break;
+		case RenderPassType_HdrMapping:
+			if(m_initializedRenderingPasses[RenderPassType_HdrMapping] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_HdrMapping] = new HdrMappingPass(*this);
+			break;
+		case RenderPassType_Blur:
+			if(m_initializedRenderingPasses[RenderPassType_Blur] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Blur] = new BlurPass(*this);
+			break;
+		case RenderPassType_BloomComposite:
+			if(m_initializedRenderingPasses[RenderPassType_BloomComposite] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_BloomComposite] = new BloomCompositePass(*this);
+			break;
+		case RenderPassType_LenseFlare:
+			if(m_initializedRenderingPasses[RenderPassType_LenseFlare] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_LenseFlare] = new LenseFlarePass(*this);
+			break;
+		case RenderPassType_LenseFlareComposite:
+			if(m_initializedRenderingPasses[RenderPassType_LenseFlareComposite] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_LenseFlareComposite] = new LenseFlareCompositePass(*this);
+			break;
+		case RenderPassType_Final:
+			if(m_initializedRenderingPasses[RenderPassType_Final] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Final] = new FinalPass(*this);
+			break;
+		}
+	}
+}
+
 RendererFrontend::~RendererFrontend()
 RendererFrontend::~RendererFrontend()
 {
 {
 	// Delete rendering passes
 	// Delete rendering passes
@@ -37,53 +104,35 @@ ErrorCode RendererFrontend::init()
 	if(!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
 	if(!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
 		return returnCode;
 		return returnCode;
 
 
+	// Initialize rendering passes
+	for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
+	{
+		// Check if has been created
+		if(m_initializedRenderingPasses[i] != nullptr)
+		{
+			// Initialize the rendering pass and check if it was successfull
+			if(m_initializedRenderingPasses[i]->init() != ErrorCode::Success)
+			{
+				// Log an error and delete the rendering pass
+				ErrHandlerLoc::get().log(ErrorType::Error, ErrorSource::Source_Renderer, m_initializedRenderingPasses[i]->getName() + " failed to load.");
+				delete m_initializedRenderingPasses[i];
+				m_initializedRenderingPasses[i] = nullptr;
+			}
+		}
+	}
+
 	// Create the render pass data struct
 	// Create the render pass data struct
 	m_renderPassData = new RenderPassData();
 	m_renderPassData = new RenderPassData();
 
 
-	m_renderingPasses.reserve(7);
+	// Reserve the required space for rendering passes array
+	m_renderingPasses.reserve(m_renderingPassesTypes.size());
 
 
-	// Add geometry rendering pass, if it was initialized successfuly
-	GeometryPass *geometryPass = new GeometryPass(*this);
-	if(geometryPass->init() == ErrorCode::Success)
-		m_renderingPasses.push_back(geometryPass);
-	
-	// Add SKY atmospheric scattering pass, if it was initialized successfuly
-	AtmScatteringPass *atmScatteringPass = new AtmScatteringPass(*this);
-	ErrorCode atmScatPassError = atmScatteringPass->init();
-	if(atmScatPassError == ErrorCode::Success)
-		m_renderingPasses.push_back(atmScatteringPass);
-
-	// Add lighting rendering pass, if it was initialized successfuly
-	LightingPass *lightingPass = new LightingPass(*this);
-	if(lightingPass->init() == ErrorCode::Success)
-		m_renderingPasses.push_back(lightingPass);
-
-	// Add GROUND atmospheric scattering pass, if it was initialized successfuly
-	if(atmScatPassError == ErrorCode::Success)
-		m_renderingPasses.push_back(atmScatteringPass);
-
-	// Add HDR mapping rendering pass, if it was initialized successfully
-	HdrMappingPass *hdrPass = new HdrMappingPass(*this);
-	if(hdrPass->init() == ErrorCode::Success)
-		m_renderingPasses.push_back(hdrPass);
-
-	// 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 post process rendering pass, if it was initialized successfully
-	PostProcessPass *postProcessPass = new PostProcessPass(*this);
-	if(postProcessPass->init() == ErrorCode::Success)
-		m_renderingPasses.push_back(postProcessPass);
-
-	// Add final rendering pass, if it was initialized successfuly
-	FinalPass *finalPass = new FinalPass(*this);
-	if(finalPass->init() == ErrorCode::Success)
-		m_renderingPasses.push_back(finalPass);
-
-	//if(atmScatteringPass->init() == ErrorCode::Success)
-	//	m_renderingPasses.push_back(atmScatteringPass);
+	// Add required rendering passes to the main array
+	for(decltype(m_renderingPassesTypes.size()) i = 0, size = m_renderingPassesTypes.size(); i < size; i++)
+	{
+		if(m_initializedRenderingPasses[m_renderingPassesTypes[i]] != nullptr)
+			m_renderingPasses.push_back(m_initializedRenderingPasses[m_renderingPassesTypes[i]]);
+	}
 
 
 	updateProjectionMatrix();
 	updateProjectionMatrix();
 
 
@@ -112,9 +161,7 @@ void RendererFrontend::renderFrame(const SceneObjects &p_sceneObjects, const flo
 
 
 	// Clear draw commands at the beggining of each frame
 	// Clear draw commands at the beggining of each frame
 	m_drawCommands.clear();
 	m_drawCommands.clear();
-
-	//if(p_sceneObjects.m_staticSkybox.)
-
+	
 	// Load all the objects in the load-to-gpu queue. This needs to be done before any rendering, as objects in this
 	// Load all the objects in the load-to-gpu queue. This needs to be done before any rendering, as objects in this
 	// array might have been also added to objects-to-render arrays, so they need to be loaded first
 	// array might have been also added to objects-to-render arrays, so they need to be loaded first
 	for (decltype(p_sceneObjects.m_objectsToLoad.size()) i = 0, size = p_sceneObjects.m_objectsToLoad.size(); i < size; i++)
 	for (decltype(p_sceneObjects.m_objectsToLoad.size()) i = 0, size = p_sceneObjects.m_objectsToLoad.size(); i < size; i++)

+ 21 - 9
Praxis3D/Source/RendererFrontend.h

@@ -10,9 +10,12 @@ struct RenderPassData;
 class RendererFrontend
 class RendererFrontend
 {
 {
 	friend class AtmScatteringPass;
 	friend class AtmScatteringPass;
+	friend class BloomCompositePass;
 	friend class BlurPass;
 	friend class BlurPass;
 	friend class GeometryPass;
 	friend class GeometryPass;
 	friend class HdrMappingPass;
 	friend class HdrMappingPass;
+	friend class LenseFlareCompositePass;
+	friend class LenseFlarePass;
 	friend class LightingPass;
 	friend class LightingPass;
 	friend class PostProcessPass;
 	friend class PostProcessPass;
 	friend class FinalPass;
 	friend class FinalPass;
@@ -43,7 +46,7 @@ public:
 		const BufferUsageHint m_bufferUsage;
 		const BufferUsageHint m_bufferUsage;
 	};
 	};
 
 
-	RendererFrontend() { }
+	RendererFrontend();
 	~RendererFrontend();
 	~RendererFrontend();
 
 
 	ErrorCode init();
 	ErrorCode init();
@@ -123,11 +126,16 @@ protected:
 
 
 	inline void queueForLoading(ShaderLoader::ShaderProgram &p_shader)
 	inline void queueForLoading(ShaderLoader::ShaderProgram &p_shader)
 	{
 	{
-		m_loadCommands.emplace_back(p_shader.m_shaderFilename,
-									p_shader.m_programHandle,
-									p_shader.getUniformUpdater(),
-									p_shader.m_shaderSource, 
-									p_shader.m_errorMessages);
+		if(!p_shader.m_loadedToVideoMemory)
+		{
+			m_loadCommands.emplace_back(p_shader.m_shaderFilename,
+										p_shader.m_programHandle,
+										p_shader.getUniformUpdater(),
+										p_shader.m_shaderSource,
+										p_shader.m_errorMessages);
+
+			p_shader.m_loadedToVideoMemory = true;
+		}
 	}
 	}
 	inline void queueForLoading(ModelLoader::ModelHandle &p_model)
 	inline void queueForLoading(ModelLoader::ModelHandle &p_model)
 	{
 	{
@@ -253,12 +261,16 @@ protected:
 	RendererBackend::BufferUpdateCommands m_bufferUpdateCommands;
 	RendererBackend::BufferUpdateCommands m_bufferUpdateCommands;
 	RendererBackend::ScreenSpaceDrawCommands m_screenSpaceDrawCommands;
 	RendererBackend::ScreenSpaceDrawCommands m_screenSpaceDrawCommands;
 
 
-	// An array of all active rendering passes
-	std::vector<RenderPass*> m_renderingPasses;
-
 	// Holds info used between rendering passses
 	// Holds info used between rendering passses
 	RenderPassData *m_renderPassData;
 	RenderPassData *m_renderPassData;
 
 
 	// View - projection matrix
 	// View - projection matrix
 	Math::Mat4f m_viewProjMatrix;
 	Math::Mat4f m_viewProjMatrix;
+	
+	// An array of all active rendering passes
+	std::vector<RenderPass*> m_renderingPasses;
+
+	std::vector<RenderPassType> m_renderingPassesTypes;
+	RenderPass *m_initializedRenderingPasses[RenderPassType::RenderPassType_NumOfTypes];
+	bool m_renderPassBeingUsed[RenderPassType::RenderPassType_NumOfTypes];
 };
 };

+ 2 - 2
Praxis3D/Source/RendererScene.cpp

@@ -102,7 +102,7 @@ ErrorCode RendererScene::preload()
 	}
 	}
 	
 	
 	// Start loading Environment Map Objects 
 	// Start loading Environment Map Objects 
-	for (decltype(m_envMapPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_envMapPool.getNumAllocated(),
+	for(decltype(m_envMapPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_envMapPool.getNumAllocated(),
 		size = m_envMapPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
 		size = m_envMapPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
 	{
 	{
 		// If current object is allocated and is not loaded to memory already
 		// If current object is allocated and is not loaded to memory already
@@ -515,7 +515,7 @@ ModelObject *RendererScene::loadModelObject(const PropertySet &p_properties)
 
 
 	// If shaders are present
 	// If shaders are present
 	if(shaderProperty)
 	if(shaderProperty)
-	{	
+	{
 		// Try to add a new object to the pool
 		// Try to add a new object to the pool
 		objPoolError = m_shaderObjPool.add(
 		objPoolError = m_shaderObjPool.add(
 			this, p_properties.getPropertyByID(Properties::Name).getString(),
 			this, p_properties.getPropertyByID(Properties::Name).getString(),

+ 5 - 5
Praxis3D/Source/ScriptingScene.cpp

@@ -156,11 +156,11 @@ FreeCamera *ScriptingScene::loadFreeCamera(const PropertySet & p_properties)
 	const auto &keybindings = p_properties.getPropertySetByID(Properties::Keybindings);
 	const auto &keybindings = p_properties.getPropertySetByID(Properties::Keybindings);
 
 
 	// Declare keys
 	// Declare keys
-	Scancode forwardKey;
-	Scancode backwardKey;
-	Scancode leftStrafeKey;
-	Scancode rightStrafeKey;
-	Scancode sprintKey;
+	Scancode forwardKey = Key_Invalid;
+	Scancode backwardKey = Key_Invalid;
+	Scancode leftStrafeKey = Key_Invalid;
+	Scancode rightStrafeKey = Key_Invalid;
+	Scancode sprintKey = Key_Invalid;
 
 
 	// Check if key-bindings in the property are present
 	// Check if key-bindings in the property are present
 	if(keybindings.getPropertyID() != Properties::Null)
 	if(keybindings.getPropertyID() != Properties::Null)

+ 1 - 1
Praxis3D/Source/ShaderGraphicsObjects.h

@@ -47,7 +47,7 @@ public:
 		//if(!ErrHandlerLoc::get().ifSuccessful(m_shader->loadToVideoMemory(), error))
 		//if(!ErrHandlerLoc::get().ifSuccessful(m_shader->loadToVideoMemory(), error))
 		//{
 		//{
 			// Log an error on failure
 			// Log an error on failure
-			ErrHandlerLoc::get().log(error);
+			//ErrHandlerLoc::get().log(error);
 
 
 			// Replace the shader with a default one
 			// Replace the shader with a default one
 			m_shader = Loaders::shader().load();
 			m_shader = Loaders::shader().load();

+ 7 - 5
Praxis3D/Source/ShaderLoader.cpp

@@ -25,6 +25,8 @@ ErrorCode ShaderLoader::init()
 {
 {
 	// Initialize default shader program
 	// Initialize default shader program
 	m_defaultProgram.loadToMemory();
 	m_defaultProgram.loadToMemory();
+	m_defaultProgram.m_uniformUpdater = new ShaderUniformUpdater(m_defaultProgram);
+	m_defaultProgram.m_loadedToVideoMemory = true;
 
 
 	// Reserve space in the program pool, to speed up push_backs
 	// Reserve space in the program pool, to speed up push_backs
 	m_shaderPrograms.reserve(Config::rendererVar().shader_pool_size);
 	m_shaderPrograms.reserve(Config::rendererVar().shader_pool_size);
@@ -109,13 +111,13 @@ ShaderLoader::ShaderProgram *ShaderLoader::load(const PropertySet &p_properties)
 
 
 			// Iterate over all shader programs and match hash key and name; if match is found, return it
 			// Iterate over all shader programs and match hash key and name; if match is found, return it
 			for(decltype(m_shaderPrograms.size()) i = 0, size = m_shaderPrograms.size(); i < size; i++)
 			for(decltype(m_shaderPrograms.size()) i = 0, size = m_shaderPrograms.size(); i < size; i++)
-				if(m_shaderPrograms[i].m_filenameHash == programHashkey)
-					if(m_shaderPrograms[i].m_combinedFilename == programName)
-						return &m_shaderPrograms[i];
+				if(m_shaderPrograms[i]->m_filenameHash == programHashkey)
+					if(m_shaderPrograms[i]->m_combinedFilename == programName)
+						return m_shaderPrograms[i];
 
 
 			// Add the new program to the array
 			// Add the new program to the array
-			m_shaderPrograms.push_back(ShaderProgram(programName, programHashkey));
-			ShaderProgram *newProgram = &m_shaderPrograms[m_shaderPrograms.size() - 1];
+			ShaderProgram *newProgram = new ShaderProgram(programName, programHashkey);
+			m_shaderPrograms.push_back(newProgram);
 
 
 			// Iterate over shader types
 			// Iterate over shader types
 			for(unsigned int shaderType = 0; shaderType < ShaderType_NumOfTypes; shaderType++)
 			for(unsigned int shaderType = 0; shaderType < ShaderType_NumOfTypes; shaderType++)

+ 1 - 1
Praxis3D/Source/ShaderLoader.h

@@ -287,5 +287,5 @@ private:
 	// Mutex used to block calls from other threads while operation is in progress
 	// Mutex used to block calls from other threads while operation is in progress
 	SpinWait m_mutex;
 	SpinWait m_mutex;
 
 
-	std::vector<ShaderProgram> m_shaderPrograms;
+	std::vector<ShaderProgram*> m_shaderPrograms;
 };
 };

+ 8 - 0
Praxis3D/Source/ShaderUniformUpdater.cpp

@@ -76,6 +76,11 @@ ErrorCode ShaderUniformUpdater::generateTextureUpdateList()
 	uniformList.push_back(new AtmSingleMieTextureUniform(m_shaderHandle));
 	uniformList.push_back(new AtmSingleMieTextureUniform(m_shaderHandle));
 	uniformList.push_back(new AtmTransmittanceTextureUniform(m_shaderHandle));
 	uniformList.push_back(new AtmTransmittanceTextureUniform(m_shaderHandle));
 		
 		
+	// Lens flare effect textures
+	uniformList.push_back(new LensFlareDirtTextureUniform(m_shaderHandle));
+	uniformList.push_back(new LensFlareGhostGradientTextureUniform(m_shaderHandle));
+	uniformList.push_back(new LensFlareStarburstTextureUniform(m_shaderHandle));
+	
 	// Go through each uniform and check if it is valid
 	// Go through each uniform and check if it is valid
 	// If it is, add it to the update list, if not, delete it
 	// 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++)
 	for(decltype(uniformList.size()) i = 0, size = uniformList.size(); i < size; i++)
@@ -198,6 +203,9 @@ ErrorCode ShaderUniformUpdater::generateUniformBlockList()
 	// Atmospheric scattering buffer
 	// Atmospheric scattering buffer
 	uniformBlockList.push_back(new AtmScatParametersUniform(m_shaderHandle));
 	uniformBlockList.push_back(new AtmScatParametersUniform(m_shaderHandle));
 	
 	
+	// Lens flare effect parameters buffer
+	uniformBlockList.push_back(new LensFlareParametersUniform(m_shaderHandle));
+
 	// Go through each uniform and check if it is valid
 	// Go through each uniform and check if it is valid
 	// If it is, add it to the update list, if not, delete it
 	// If it is, add it to the update list, if not, delete it
 	for(decltype(uniformBlockList.size()) i = 0, size = uniformBlockList.size(); i < size; i++)
 	for(decltype(uniformBlockList.size()) i = 0, size = uniformBlockList.size(); i < size; i++)

+ 47 - 0
Praxis3D/Source/ShaderUniforms.h

@@ -811,6 +811,43 @@ public:
 	}
 	}
 };
 };
 
 
+class LensFlareDirtTextureUniform : public BaseUniform
+{
+public:
+	LensFlareDirtTextureUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().lensFlareDirtTextureUniform, p_shaderHandle)
+	{
+	}
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1i(m_uniformHandle, LensFlareTextureType::LensFlareTextureType_LenseDirt);
+	}
+};
+class LensFlareGhostGradientTextureUniform : public BaseUniform
+{
+public:
+	LensFlareGhostGradientTextureUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().lensFlareGhostGradientTextureUniform, p_shaderHandle)
+	{
+	}
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1i(m_uniformHandle, LensFlareTextureType::LensFlareTextureType_GhostGradient);
+	}
+};
+class LensFlareStarburstTextureUniform : public BaseUniform
+{
+public:
+	LensFlareStarburstTextureUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().lensFlareStarburstTextureUniform, p_shaderHandle)
+	{
+	}
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1i(m_uniformHandle, LensFlareTextureType::LensFlareTextureType_Starburst);
+	}
+};
+
 class DynamicEnvironmentMapUniform : public BaseUniform
 class DynamicEnvironmentMapUniform : public BaseUniform
 {
 {
 public:
 public:
@@ -969,6 +1006,16 @@ public:
 		updateBlockBinding(UniformBufferBinding_AtmScatParam);
 		updateBlockBinding(UniformBufferBinding_AtmScatParam);
 	}
 	}
 };
 };
+class LensFlareParametersUniform : public BaseUniformBlock
+{
+public:
+	LensFlareParametersUniform(unsigned int p_shaderHandle) : BaseUniformBlock(Config::shaderVar().lensFlareParametersBuffer, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		updateBlockBinding(UniformBufferBinding_LensFlareParam);
+	}
+};
 
 
 class HDRShaderStorageBuffer : public BaseShaderStorageBlock
 class HDRShaderStorageBuffer : public BaseShaderStorageBlock
 {
 {

+ 38 - 0
Praxis3D/Source/TextureLoader.cpp

@@ -179,6 +179,44 @@ TextureLoader2D::Texture2DHandle TextureLoader2D::load(const std::string &p_file
 	return Texture2DHandle(returnTexture);
 	return Texture2DHandle(returnTexture);
 }
 }
 
 
+TextureLoader2D::Texture2DHandle TextureLoader2D::load(const std::string & p_filename)
+{	
+	Texture2D *returnTexture;
+
+	// Make sure calls from other threads are locked, while current call is in progress
+	// This is needed to as the object that is being requested might be currently loading /
+	// being added to the pool. Mutex prevents duplicates being loaded, and same data being changed.
+	SpinWait::Lock lock(m_mutex);
+
+	// If the filename is empty, return a default texture instead
+	if(p_filename == "")
+	{
+		returnTexture = m_default2DTexture;
+	}
+	else
+	{
+		// Go through the texture pool and check if the texture hasn't been already loaded (to avoid duplicates)
+		for(decltype(m_objectPool.size()) size = m_objectPool.size(), i = 0; i < size; i++)
+		{
+			if(*m_objectPool[i] == p_filename)
+				return Texture2DHandle(m_objectPool[i]);
+		}
+
+		// Texture wasn't loaded before, so create a new one
+		// Assign default handle (as a placeholder to be used before the texture is loaded from HDD)
+		returnTexture = new Texture2D(this, p_filename, m_objectPool.size(), m_default2DTexture->m_handle);
+
+		// Set the loaded flag to true, because we have already provided the texture handle
+		returnTexture->setLoadedToVideoMemory(true);
+
+		// Add the new texture to the list
+		m_objectPool.push_back(returnTexture);
+	}
+
+	// Return the new texture
+	return Texture2DHandle(returnTexture);
+}
+
 TextureLoaderCubemap::TextureLoaderCubemap()
 TextureLoaderCubemap::TextureLoaderCubemap()
 {
 {
 	std::string defaultFilenames[CubemapFace_NumOfFaces];
 	std::string defaultFilenames[CubemapFace_NumOfFaces];

+ 2 - 0
Praxis3D/Source/TextureLoader.h

@@ -298,6 +298,7 @@ public:
 			return returnError;
 			return returnError;
 		}
 		}
 
 
+		// NOT USED
 		// Loads data from RAM to buffer and uploads them to VRAM
 		// Loads data from RAM to buffer and uploads them to VRAM
 		// WARNING: should probably only be called from rendering thread, since this code deals with graphics API
 		// WARNING: should probably only be called from rendering thread, since this code deals with graphics API
 		ErrorCode loadToVideoMemory()
 		ErrorCode loadToVideoMemory()
@@ -372,6 +373,7 @@ public:
 
 
 	Texture2DHandle load(const std::string &p_filename, MaterialType p_materialType, bool p_startBackgroundLoading = true);
 	Texture2DHandle load(const std::string &p_filename, MaterialType p_materialType, bool p_startBackgroundLoading = true);
 	Texture2DHandle load(const std::string &p_filename, unsigned int p_textureHandle);
 	Texture2DHandle load(const std::string &p_filename, unsigned int p_textureHandle);
+	Texture2DHandle load(const std::string &p_filename);
 };
 };
 
 
 class TextureCubemap : public LoaderBase<TextureLoaderCubemap, TextureCubemap>::UniqueObject
 class TextureCubemap : public LoaderBase<TextureLoaderCubemap, TextureCubemap>::UniqueObject