Browse Source

Made HDR into a rendering pass, added comms between rendering passes

Made HDR mapping into a separate rendering pass, so it's easier to work on it, as it's decoupled now.
Added data sharing between rendering passes.
Added input/output buffer locations that are shared between rendering passes, so separate passes can be added/removed without modifying the buffer locations in subsequent passes.
Added emissive color mulptiplyer, HDR adaption rate and HDR intended brightness values to config and uniforms, so they can be modified without recompiling.
Added a post process rendering pass as a placeholder for future effects, which now just acts as pass-through.
Adjusted HDR mapping values for a better looking visual effect and faster eye adaption.
Paulcodedev 7 years ago
parent
commit
2ab8e13740

+ 2 - 0
.gitignore

@@ -18,3 +18,5 @@ Builds/x64/Release 64bit/Praxis3D\.ipdb
 *.dae
 
 Praxis3D/x64/
+
+Praxis3D/Data/Maps/default_lite backup\.pmap

+ 30 - 5
Praxis3D/Data/Maps/default_lite.pmap

@@ -21,7 +21,32 @@
 					"Name": "DirectionalLight 1",
 					"Color": "1.0f, 1.0f, 1.0f",
 					"Direction": "0.006461f, -0.707092f, -0.707092f",
-					"Intensity": "0.5f"
+					"Intensity": "0.1f"
+				},
+				{
+					"Type": "EnvironmentMapStatic",
+					"Position": "0.0f, 0.0f, 0.0f",
+					"Materials": 
+					[
+						{
+							"Filename": "posx.jpg"
+						},
+						{
+							"Filename": "negx.jpg"
+						},
+						{
+							"Filename": "posy.jpg"
+						},
+						{
+							"Filename": "negy.jpg"
+						},
+						{
+							"Filename": "posz.jpg"
+						},
+						{
+							"Filename": "negz.jpg"
+						}
+					]
 				},
 				{
 					"Type": "ModelObject",
@@ -871,7 +896,7 @@
 					"CutoffAngle": "60.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
 					"Direction": "-1.0f, 0.0f, 0.0f",
-					"Intensity": "20000.0f",
+					"Intensity": "500.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Position": "60.0f, 3.0f, 60.0f"
@@ -883,7 +908,7 @@
 					"CutoffAngle": "60.0f",
 					"Color": "0.0f, 1.0f, 0.0f",
 					"Direction": "-0.145991f, 0.0f, 0.989286f",
-					"Intensity": "500.0f",
+					"Intensity": "300.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Position": "-40.0f, 3.0f, 1.96449f"
@@ -895,7 +920,7 @@
 					"CutoffAngle": "60.0f",
 					"Color": "1.0f, 0.0f, 0.0f",
 					"Direction": "0.145991f, 0.0f, -0.989286f",
-					"Intensity": "500.0f",
+					"Intensity": "300.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Position": "-40.0f, 3.0f, 1.96449f"
@@ -907,7 +932,7 @@
 					"CutoffAngle": "60.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
 					"Direction": "0.707107f, 0.0f, 0.707107f",
-					"Intensity": "200.0f",
+					"Intensity": "500.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Position": "-20.0f, 3.0f, -20.0f"

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

@@ -8,8 +8,9 @@ out vec4 outputColor;
 
 uniform ivec2 screenSize;
 uniform float gamma;
+
 uniform sampler2D emissiveMap;
-uniform sampler2D finalColorMap;
+uniform sampler2D inputColorMap;
 
 vec3 gammaCorrection(vec3 p_color, float p_gamma)
 {
@@ -51,29 +52,29 @@ void main(void)
 	vec2 texCoord = calcTexCoord();
 	
 	// Perform gamma correction on the color from the final framebuffer
-	vec3 color = texture(finalColorMap, texCoord).xyz;
+	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
 	
 	// Add emissive color (which is generated in a blur pass)
-	color += texture(emissiveMap, texCoord).xyz;
+	fragmentColor += texture(emissiveMap, texCoord).xyz;
 		
 	#ifdef ENABLE_TONE_MAPPING
 	// Perform simple tonemapping on the final color
-	color = simpleToneMapping(color);
+	fragmentColor = simpleToneMapping(fragmentColor);
 	#endif
 	
 	#ifdef ENABLE_REINHARD_TONE_MAPPING
 	// Perform reinhard tonemapping on the final color
-	color = reinhardToneMapping(color);
+	fragmentColor = reinhardToneMapping(fragmentColor);
 	#endif
 	
 	#ifdef ENABLE_FILMIC_TONE_MAPPING
 	// Perform filmic tonemapping on the final color
-	color = filmicToneMapping(color);
+	fragmentColor = filmicToneMapping(fragmentColor);
 	#endif
 	
 	// Perform gamma correction as the last step of the fragment color
-	color = gammaCorrection(color, gamma);
+	fragmentColor = gammaCorrection(fragmentColor, gamma);
 	
 	// Write the color to the framebuffer
-	outputColor = vec4(color, 1.0);
+	outputColor = vec4(fragmentColor, 1.0);
 }

+ 1 - 47
Praxis3D/Data/Shaders/finalPass.vert

@@ -1,53 +1,7 @@
 #version 430 core
 
-#define ENABLE_HDR
-
-layout(std430, binding = 0) buffer HDRBuffer
-{
-	float screenBrightness;
-};
-
-uniform float eyeAdaptionRate;
-uniform float deltaTimeS;
-uniform ivec2 screenSize;
-uniform sampler2D finalColorMap;
-
-// Calculates the maximum texture mipmap level
-float calcMaxMipmapLevel(vec2 p_textureSize)
-{
-	return 1 + floor(log2(max(p_textureSize.x, p_textureSize.y)));
-}
-
-// Averages RGB color into a single brightness value
-float calcAverageBrightness(vec3 p_color)
-{
-	return (p_color.x + p_color.y + p_color.z) / 3.0;
-}
-
-// Calculates a brightness value from a color
-float calcBrightness(vec3 p_color)
-{
-	return dot(p_color, vec3(0.2126, 0.7152, 0.0722));
-}
-
 void main(void) 
-{
-	#ifdef ENABLE_HDR
-	
-	// Get maximum mipmap level (1x1) of a framebuffer
-	float exposureMipmapLevel = calcMaxMipmapLevel(screenSize);
-	// Get the current (previous frame) average brightness
-	float avgBrightnessPrevFrame = calcAverageBrightness(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);
-	
-	#else
-	
-	// Set the average brightness to 0.5 so it does not affect the scene
-	screenBrightness = 0.5;
-	
-	#endif
-	
+{	
 	// Determine texture coordinates
 	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
 	

+ 4 - 4
Praxis3D/Data/Shaders/gaussianBlurHorizontal.frag

@@ -5,7 +5,7 @@ in vec2 blurTexCoords[14];
 
 out vec4 outputColor;
 
-uniform sampler2D blurMap;
+uniform sampler2D inputColorMap;
 uniform ivec2 screenSize;
 
 uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
@@ -25,12 +25,12 @@ void main(void)
 	float blurOffset = 1.0;
 	
 	vec2 tex_offset = 1.0 / screenSize; // gets size of single texel
-    fragColor = texture(blurMap, texCoord).rgb * weight[0]; // current fragment's contribution
+    fragColor = texture(inputColorMap, texCoord).rgb * weight[0]; // current fragment's contribution
 	
 	for(int i = 1; i < 5; ++i)
 	{
-		fragColor += texture(blurMap, texCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
-		fragColor += texture(blurMap, texCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
+		fragColor += texture(inputColorMap, texCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
+		fragColor += texture(inputColorMap, texCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
 	}
 		
 	/*

+ 4 - 4
Praxis3D/Data/Shaders/gaussianBlurVertical.frag

@@ -7,7 +7,7 @@ in vec2 blurTexCoords[14];
 out vec4 outputColor;
 //layout(location = 0) out vec4 blurBuffer;
 
-uniform sampler2D emissiveMap;
+uniform sampler2D inputColorMap;
 uniform ivec2 screenSize;
 
 uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
@@ -27,12 +27,12 @@ void main(void)
 	float blurOffset = 1.0;
 	
 	vec2 tex_offset = 1.0 / screenSize; // gets size of single texel
-    fragColor = texture(emissiveMap, texCoord).rgb * weight[0]; // current fragment's contribution
+    fragColor = texture(inputColorMap, texCoord).rgb * weight[0]; // current fragment's contribution
 	
 	for(int i = 1; i < 5; ++i)
 	{
-		fragColor += texture(emissiveMap, texCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
-		fragColor += texture(emissiveMap, texCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
+		fragColor += texture(inputColorMap, texCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
+		fragColor += texture(inputColorMap, texCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
 	}
 		
 	/*

+ 9 - 8
Praxis3D/Data/Shaders/geometryPass.frag

@@ -3,8 +3,8 @@
 #define MIN_LOD_PARALLAX 0.0
 #define MAX_LOD_PARALLAX 10.0
 #define LOD_PARALLAX_THRESHOLD 0.0
-#define HEIGHT_SCALE_THRESHOLD 0.001
-#define ROUGHNESS_MIN 0.001
+#define PARALLAX_SCALE_THRESHOLD 0.001
+#define MIN_ROUGHNESS 0.001
 
 // Some drivers require the following
 //precision highp float;
@@ -44,6 +44,7 @@ uniform sampler2D normalTexture;
 uniform sampler2D emissiveTexture;
 
 uniform float alphaThreshold;
+uniform float emissiveMultiplier;
 uniform float emissiveThreshold;
 
 /*
@@ -89,7 +90,7 @@ float getHeight(const vec2 p_texCoords, const vec2 p_dPdx, const vec2 p_dPdy)
 
 float getRoughness(const vec2 p_texCoords)
 {
-	return max(texture(combinedTexture, p_texCoords).r, ROUGHNESS_MIN);
+	return max(texture(combinedTexture, p_texCoords).r, MIN_ROUGHNESS);
 }
 float getMetalness(const vec2 p_texCoords)
 {
@@ -325,14 +326,13 @@ void main(void)
 	
 	// This is to save performance by not performing the
 	// parallax mapping for objects that it was not intended for
-	if((1.0 - height) * parallaxScale > HEIGHT_SCALE_THRESHOLD)
+	if((1.0 - height) * parallaxScale > PARALLAX_SCALE_THRESHOLD)
 	{
 		vec3 viewDir = tangentCameraPos - tangentFragPos;
 		float distanceToFrag = length(viewDir);
 		viewDir = normalize(viewDir);
-		float LOD = min(((10.0 - distanceToFrag) / 10.0), 1.0);
 		
-		LOD = clamp(1.0 - ((distanceToFrag * distanceToFrag) / parallaxLOD), MIN_LOD_PARALLAX, MAX_LOD_PARALLAX);
+		float LOD = clamp(1.0 - ((distanceToFrag * distanceToFrag) / parallaxLOD), MIN_LOD_PARALLAX, MAX_LOD_PARALLAX);
 		
 		if(LOD > LOD_PARALLAX_THRESHOLD)
 			newCoords = parallaxOcclusionMapping(texCoord, viewDir, LOD);
@@ -343,7 +343,7 @@ void main(void)
 		//float LOD = min(((10.0 - distanceToFrag) / 10.0), 1.0);
 		//float LOD2 = clamp((distanceToFrag - 8.0) / 2.0, 0.0, 1.0);
 	
-		//if(parallaxScale > HEIGHT_SCALE_THRESHOLD)
+		//if(parallaxScale > PARALLAX_SCALE_THRESHOLD)
 		//	newCoords = mix(parallaxOcclusionMapping(texCoord, viewDir, LOD), texCoord, 1.0 - LOD);
 	//}
 	
@@ -362,13 +362,14 @@ void main(void)
 	// Get roughness and metalness values, and emissive color
 	float roughness = getRoughness(newCoords);
 	float metalness = getMetalness(newCoords);
+	//vec4 emissiveColor = pow(texture(emissiveTexture, newCoords), vec4(gamma, gamma, gamma, 1.0));
 	vec4 emissiveColor = texture(emissiveTexture, newCoords).rgba;
 	
 	// Apply emissive color only if it's above the threshold
 	if(emissiveColor.a > emissiveThreshold)
 	{
 		// Use emissive alpha channel as an intensity multiplier
-		emissiveColor *= emissiveColor.a * 10.0;
+		emissiveColor *= emissiveColor.a * emissiveMultiplier;
 	}
 	else
 	{

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

@@ -0,0 +1,79 @@
+#version 430 core
+
+//#define AVG_INTENDED_BRIGHTNESS 0.2
+#define MIN_INTENDED_BRIGHTNESS 0.01
+#define MAX_INTENDED_BRIGHTNESS 10.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 = 1) out vec4 colorBuffer;
+
+in float avgBrightness;
+
+uniform sampler2D emissiveMap;
+uniform sampler2D inputColorMap;
+
+uniform mat4 modelViewMat;
+uniform mat4 viewMat;
+uniform vec3 cameraPosVec;
+uniform ivec2 screenSize;
+uniform float eyeAdaptionIntBrightness;
+uniform float gamma;
+
+float getBrightestColor(vec3 p_color)
+{
+	return max(p_color.x, max(p_color.y, p_color.z));
+}
+
+// Calculates a brightness value from a color
+float calcBrightness(vec3 p_color)
+{
+	return dot(p_color, vec3(0.2126, 0.7152, 0.0722));
+}
+
+// Adjusts an RGB color based on the average brightness (exposure)
+// by making overall brightness match the average intended brightness (eyeAdaptionIntBrightness)
+vec3 brightnessMapping(vec3 p_color, float p_exposure)
+{
+	return p_color * clamp(eyeAdaptionIntBrightness / p_exposure, MIN_INTENDED_BRIGHTNESS, MAX_INTENDED_BRIGHTNESS);
+}
+
+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 emissive texture color
+	vec3 emissiveColor = /*pow(*/texture(emissiveMap, texCoord).xyz/*, vec3(gamma))*/;
+	// Get the emissive texture color
+	vec3 fragmentColor = texture(inputColorMap, texCoord).xyz;
+	
+	// Adjust the fragment brightness based on average
+	fragmentColor = brightnessMapping(fragmentColor, avgBrightness);
+	
+	// If a fragment brightness exceeds a value of 1.0 after an HDR Mapping, 
+	// add it to the emissive buffer, as a bloom effect
+	if(calcBrightness(fragmentColor) > 1.0)
+		emissiveColor += fragmentColor;
+	
+	emissiveBuffer = vec4(emissiveColor, 1.0);
+	colorBuffer = vec4(fragmentColor, 1.0);
+}

+ 68 - 0
Praxis3D/Data/Shaders/hdrMappingPass.vert

@@ -0,0 +1,68 @@
+#version 430 core
+
+#define ENABLE_HDR
+
+layout(std430, binding = 0) buffer HDRBuffer
+{
+	float screenBrightness;
+};
+
+out float avgBrightness;
+
+uniform float eyeAdaptionRate;
+uniform float deltaTimeS;
+uniform ivec2 screenSize;
+
+uniform sampler2D finalColorMap;
+
+// Calculates the maximum texture mipmap level
+float calcMaxMipmapLevel(vec2 p_textureSize)
+{
+	return 1 + floor(log2(max(p_textureSize.x, p_textureSize.y)));
+}
+
+// Returns the single brightest color
+float getBrightestColor(vec3 p_color)
+{
+	return max(p_color.r, max(p_color.g, p_color.b));
+}
+
+// Averages RGB color into a single brightness value
+float calcBrightnessLinear(vec3 p_color)
+{
+	return (p_color.x + p_color.y + p_color.z) / 3.0;
+}
+
+// Calculates a brightness value from a color
+float calcBrightness(vec3 p_color)
+{
+	return dot(p_color, vec3(0.2126, 0.7152, 0.0722));
+}
+
+void main(void) 
+{
+	#ifdef ENABLE_HDR
+	
+	// Get maximum mipmap level (1x1) of a framebuffer
+	float exposureMipmapLevel = calcMaxMipmapLevel(screenSize);
+	// Get the current (previous frame) average brightness
+	float avgBrightnessPrevFrame = calcBrightness(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);
+	
+	#else
+	
+	// Set the average brightness to 0.5 so it does not affect the scene
+	screenBrightness = 0.5;
+	
+	#endif
+	
+	// Send the average brightness value to the fragment shader
+	avgBrightness = screenBrightness;
+	
+	// Determine texture coordinates
+	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	
+	// Calculate the position, so that the triangle fills the whole screen
+	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);
+}

+ 1 - 1
Praxis3D/Data/Shaders/lightPass.vert

@@ -18,5 +18,5 @@ void main(void)
 	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.0, 1.0);
+	gl_Position = vec4(texCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 1.0, 1.0);
 }

+ 24 - 0
Praxis3D/Data/Shaders/postProcessPass.frag

@@ -0,0 +1,24 @@
+#version 430 core
+
+out vec4 outputColor;
+
+uniform ivec2 screenSize;
+
+uniform sampler2D inputColorMap;
+
+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;
+	
+	// Write the color to the framebuffer
+	outputColor = vec4(fragmentColor, 1.0);
+}

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

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

+ 3 - 0
Praxis3D/Praxis3D.vcxproj

@@ -362,6 +362,7 @@
     <ClInclude Include="Source\GeometryBuffer.h" />
     <ClInclude Include="Source\GeometryPass.h" />
     <ClInclude Include="Source\GraphicsDataSets.h" />
+    <ClInclude Include="Source\HdrMappingPass.h" />
     <ClInclude Include="Source\Input.h" />
     <ClInclude Include="Source\KeyCommand.h" />
     <ClInclude Include="Source\LightingGraphicsObjects.h" />
@@ -376,6 +377,7 @@
     <ClInclude Include="Source\ObjectPool.h" />
     <ClInclude Include="Source\ObserverBase.h" />
     <ClInclude Include="Source\PlayState.h" />
+    <ClInclude Include="Source\PostProcessPass.h" />
     <ClInclude Include="Source\PropertyLoader.h" />
     <ClInclude Include="Source\PropertySet.h" />
     <ClInclude Include="Source\ReflectionPass.h" />
@@ -397,6 +399,7 @@
     <ClInclude Include="Source\ShaderLoader.h" />
     <ClInclude Include="Source\ShaderUniforms.h" />
     <ClInclude Include="Source\ShaderUniformUpdater.h" />
+    <ClInclude Include="Source\SkyPass.h" />
     <ClInclude Include="Source\SolarTimeScript.h" />
     <ClInclude Include="Source\SpinWait.h" />
     <ClInclude Include="Source\System.h" />

+ 9 - 0
Praxis3D/Praxis3D.vcxproj.filters

@@ -500,6 +500,15 @@
     <ClInclude Include="Source\DebugRotateScript.h">
       <Filter>Scripting\Objects\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\SkyPass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\HdrMappingPass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\PostProcessPass.h">
+      <Filter>Renderer\Render Passes\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />

+ 6 - 6
Praxis3D/Source/BlurPass.h

@@ -53,18 +53,18 @@ public:
 		return returnError;
 	}
 
-	void update(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);
-
+		
 		// Set the default framebuffer to be drawn to
 		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
-
+		
 		// Bind emissive texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getEmissiveInputMap(), GeometryBuffer::GBufferInputTexture);
 
 		// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferBlur);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
 
 		// 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);
@@ -72,7 +72,7 @@ public:
 
 
 		// Bind intermediate blur texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferBlur, GeometryBuffer::GBufferBlur);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorOutputMap(), GeometryBuffer::GBufferInputTexture);
 
 		// 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);

+ 9 - 1
Praxis3D/Source/Config.cpp

@@ -113,8 +113,10 @@ void Config::init()
 	AddVariablePredef(m_graphicsVar, multisample_buffers);
 	AddVariablePredef(m_graphicsVar, multisample_samples);
 	AddVariablePredef(m_graphicsVar, alpha_threshold);
+	AddVariablePredef(m_graphicsVar, emissive_multiplier);
 	AddVariablePredef(m_graphicsVar, emissive_threshold);
 	AddVariablePredef(m_graphicsVar, eye_adaption_rate);
+	AddVariablePredef(m_graphicsVar, eye_adaption_intended_brightness);
 	AddVariablePredef(m_graphicsVar, fog_color_x);
 	AddVariablePredef(m_graphicsVar, fog_color_y);
 	AddVariablePredef(m_graphicsVar, fog_color_z);
@@ -223,6 +225,8 @@ void Config::init()
 	AddVariablePredef(m_rendererVar, light_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, final_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, final_pass_frag_shader);
+	AddVariablePredef(m_rendererVar, final_pass_vert_shader);
+	AddVariablePredef(m_rendererVar, final_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, reflection_pass_vert_shader);
 	AddVariablePredef(m_rendererVar, reflection_pass_frag_shader);
 	AddVariablePredef(m_rendererVar, dir_light_quad_offset_x);
@@ -256,6 +260,7 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, gammaUniform);
 	AddVariablePredef(m_shaderVar, alphaCullingUniform);
 	AddVariablePredef(m_shaderVar, alphaThresholdUniform);
+	AddVariablePredef(m_shaderVar, emissiveMultiplierUniform);
 	AddVariablePredef(m_shaderVar, emissiveThresholdUniform);
 	AddVariablePredef(m_shaderVar, heightScaleUniform);
 	AddVariablePredef(m_shaderVar, combinedTextureUniform);
@@ -280,8 +285,10 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, normalMapUniform);
 	AddVariablePredef(m_shaderVar, emissiveMapUniform);
 	AddVariablePredef(m_shaderVar, matPropertiesMapUniform);
-	AddVariablePredef(m_shaderVar, blurMapUniform);
+	AddVariablePredef(m_shaderVar, intermediateMapUniform);
 	AddVariablePredef(m_shaderVar, finalMapUniform);
+	AddVariablePredef(m_shaderVar, inputColorMapUniform);
+	AddVariablePredef(m_shaderVar, outputColorMapUniform);
 	AddVariablePredef(m_shaderVar, sunGlowTextureUniform);
 	AddVariablePredef(m_shaderVar, skyMapTextureUniform);
 	AddVariablePredef(m_shaderVar, dirShadowMapTextureUniform);
@@ -296,6 +303,7 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, billboardScaleUniform);
 	AddVariablePredef(m_shaderVar, depthTypeUniform);
 	AddVariablePredef(m_shaderVar, eyeAdaptionRateUniform);
+	AddVariablePredef(m_shaderVar, eyeAdaptionIntBrightnessUniform);
 	AddVariablePredef(m_shaderVar, HDRSSBuffer);
 	AddVariablePredef(m_shaderVar, testMatUniform);
 	AddVariablePredef(m_shaderVar, testVecUniform);

+ 23 - 5
Praxis3D/Source/Config.h

@@ -557,8 +557,10 @@ public:
 			rendering_res_x = 1600;
 			rendering_res_y = 900;
 			alpha_threshold = 0.0f;
+			emissive_multiplier = 10.0f;
 			emissive_threshold = 0.01f;
-			eye_adaption_rate = 0.5f;
+			eye_adaption_rate = 0.25f;
+			eye_adaption_intended_brightness = 0.2f;
 			fog_color_x = 0.55f;
 			fog_color_y = 0.55f;
 			fog_color_z = 0.55f;
@@ -593,8 +595,10 @@ public:
 		int rendering_res_x;
 		int rendering_res_y;
 		float alpha_threshold;
+		float emissive_multiplier;
 		float emissive_threshold;
 		float eye_adaption_rate;
+		float eye_adaption_intended_brightness;
 		float fog_color_x;
 		float fog_color_y;
 		float fog_color_z;
@@ -775,12 +779,16 @@ public:
 			gaussian_blur_vertical_vert_shader = "gaussianBlurVertical.vert";
 			gaussian_blur_horizontal_frag_shader = "gaussianBlurHorizontal.frag";
 			gaussian_blur_horizontal_vert_shader = "gaussianBlurHorizontal.vert";
+			hdr_mapping_pass_frag_shader = "hdrMappingPass.frag";
+			hdr_mapping_pass_vert_shader = "hdrMappingPass.vert";
 			blur_pass_vert_shader = "blurPass.vert";
 			blur_pass_frag_shader = "blurPass.frag";
 			light_pass_vert_shader = "lightPass.vert";
 			light_pass_frag_shader = "lightPass.frag";
 			final_pass_vert_shader = "finalPass.vert";
 			final_pass_frag_shader = "finalPass.frag";
+			postProcess_pass_vert_shader = "postProcessPass.vert";
+			postProcess_pass_frag_shader = "postProcessPass.frag";
 			reflection_pass_vert_shader = "reflectionPass.vert";
 			reflection_pass_frag_shader = "reflectionPass.frag";
 			dir_light_quad_offset_x = 0.0f;
@@ -821,12 +829,16 @@ public:
 		std::string gaussian_blur_vertical_vert_shader;
 		std::string gaussian_blur_horizontal_frag_shader;
 		std::string gaussian_blur_horizontal_vert_shader;
+		std::string hdr_mapping_pass_frag_shader;
+		std::string hdr_mapping_pass_vert_shader;
 		std::string blur_pass_vert_shader;
 		std::string blur_pass_frag_shader;
 		std::string light_pass_vert_shader;
 		std::string light_pass_frag_shader;
 		std::string final_pass_vert_shader;
 		std::string final_pass_frag_shader;
+		std::string postProcess_pass_vert_shader;
+		std::string postProcess_pass_frag_shader;
 		std::string reflection_pass_vert_shader;
 		std::string reflection_pass_frag_shader;
 		float dir_light_quad_offset_x;
@@ -863,6 +875,7 @@ public:
 			gammaUniform = "gamma";
 			alphaCullingUniform = "alphaCulling";
 			alphaThresholdUniform = "alphaThreshold";
+			emissiveMultiplierUniform = "emissiveMultiplier";
 			emissiveThresholdUniform = "emissiveThreshold";
 			heightScaleUniform = "heightScale";
 			textureTilingFactorUniform = "textureTilingFactor";
@@ -892,8 +905,10 @@ public:
 			normalMapUniform = "normalMap";
 			emissiveMapUniform = "emissiveMap";
 			matPropertiesMapUniform = "matPropertiesMap";
-			blurMapUniform = "blurMap";
+			intermediateMapUniform = "intermediateMap";
 			finalMapUniform = "finalColorMap";
+			inputColorMapUniform = "inputColorMap";
+			outputColorMapUniform = "outputColorMap";
 
 			sunGlowTextureUniform = "sunGlowMap";
 			skyMapTextureUniform = "skyMap";
@@ -902,7 +917,6 @@ public:
 			normalTextureUniform = "normalTexture";
 			specularTextureUniform = "specularTexture";
 			emissiveTextureUniform = "emissiveTexture";
-			blurTextureUniform = "blurTexture";
 			glossTextureUniform = "glossTexture";
 			heightTextureUniform = "heightTexture";
 			combinedTextureUniform = "combinedTexture";
@@ -916,6 +930,7 @@ public:
 			depthTypeUniform = "depthType";
 
 			eyeAdaptionRateUniform = "eyeAdaptionRate";
+			eyeAdaptionIntBrightnessUniform = "eyeAdaptionIntBrightness";
 			HDRSSBuffer = "HDRBuffer";
 
 			testMatUniform = "testMat";
@@ -936,6 +951,7 @@ public:
 		std::string gammaUniform;
 		std::string alphaCullingUniform;
 		std::string alphaThresholdUniform;
+		std::string emissiveMultiplierUniform;
 		std::string emissiveThresholdUniform;
 		std::string heightScaleUniform;
 		std::string textureTilingFactorUniform;
@@ -965,8 +981,10 @@ public:
 		std::string normalMapUniform;
 		std::string emissiveMapUniform;
 		std::string matPropertiesMapUniform;
-		std::string blurMapUniform;
+		std::string intermediateMapUniform;
 		std::string finalMapUniform;
+		std::string inputColorMapUniform;
+		std::string outputColorMapUniform;
 
 		std::string sunGlowTextureUniform;
 		std::string skyMapTextureUniform;
@@ -975,7 +993,6 @@ public:
 		std::string normalTextureUniform;
 		std::string specularTextureUniform;
 		std::string emissiveTextureUniform;
-		std::string blurTextureUniform;
 		std::string glossTextureUniform;
 		std::string heightTextureUniform;
 		std::string combinedTextureUniform;
@@ -989,6 +1006,7 @@ public:
 		std::string depthTypeUniform;
 
 		std::string eyeAdaptionRateUniform;
+		std::string eyeAdaptionIntBrightnessUniform;
 		std::string HDRSSBuffer;
 
 		std::string testMatUniform;

+ 8 - 32
Praxis3D/Source/FinalPass.h

@@ -7,8 +7,7 @@ class FinalPass : public RenderPass
 {
 public:
 	FinalPass(RendererFrontend &p_renderer) : 
-		RenderPass(p_renderer),
-		m_HDRSSBuffer(BufferType_ShaderStorage, BufferUsageHint_DynamicCopy) { }
+		RenderPass(p_renderer) { }
 
 	~FinalPass() { }
 
@@ -18,14 +17,6 @@ public:
 
 		m_name = "Final Rendering Pass";
 		
-		// SetHDR binding index
-		m_HDRSSBuffer.m_bindingIndex = SSBOBinding_HDR;
-		
-		m_HDRSSBuffer.m_data = &m_HDRDataSet;
-
-		// Set the HDR buffer size
-		m_HDRSSBuffer.m_size = sizeof(HDRDataSet);
-
 		// Create a property-set used to load geometry shader
 		PropertySet finalShaderProperties(Properties::Shaders);
 		finalShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().final_pass_vert_shader);
@@ -42,14 +33,11 @@ public:
 			// Queue the shaders to be loaded to GPU
 			m_renderer.queueForLoading(*m_shaderFinalPass);
 		}
-
-		// Queue HDR buffer to be created
-		m_renderer.queueForLoading(m_HDRSSBuffer);
-
+		
 		return returnError;
 	}
 
-	void update(const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
 	{
 #ifdef SETTING_USE_BLIT_FRAMEBUFFER
 
@@ -68,34 +56,22 @@ public:
 		//m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal, GeometryBuffer::GBufferFinal);
 
 		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
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal, GeometryBuffer::GBufferFinal);
-
 		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(GeometryBuffer::GBufferNormal, GeometryBuffer::GBufferInputTexture);
 
 		// Set the default framebuffer to be drawn to
 		m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
 
-
-#endif // SETTING_USE_BLIT_FRAMEBUFFER
-
 		// Queue and render a full screen quad using a final pass shader
 		m_renderer.queueForDrawing(m_shaderFinalPass->getShaderHandle(), m_shaderFinalPass->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
+
+#endif // SETTING_USE_BLIT_FRAMEBUFFER
 	}
 
 private:
 	ShaderLoader::ShaderProgram	*m_shaderFinalPass;
-
-	HDRDataSet m_HDRDataSet;
-
-	// HDR shader storage buffer
-	RendererFrontend::ShaderBuffer m_HDRSSBuffer;
 };

+ 34 - 31
Praxis3D/Source/GeometryBuffer.cpp

@@ -4,7 +4,7 @@
 GeometryBuffer::GeometryBuffer(unsigned int p_bufferWidth, unsigned int p_bufferHeight) : Framebuffer(p_bufferWidth, p_bufferHeight)
 {
 
-	m_blurBuffer = 0;
+	m_intermediateBuffer = 0;
 	m_depthBuffer = 0;
 	m_finalBuffer = 0;
 	m_finalPassBuffer = GBufferFinal;
@@ -30,8 +30,8 @@ GeometryBuffer::~GeometryBuffer()
 	if(m_depthBuffer != 0)
 		glDeleteTextures(1, &m_depthBuffer);
 
-	if(m_blurBuffer != 0)
-		glDeleteTextures(1, &m_blurBuffer);
+	if(m_intermediateBuffer != 0)
+		glDeleteTextures(1, &m_intermediateBuffer);
 
 	if(m_finalBuffer != 0)
 		glDeleteTextures(1, &m_finalBuffer);
@@ -50,7 +50,7 @@ ErrorCode GeometryBuffer::init()
 		// Create geometry pass buffers
 		glGenTextures(GBufferNumTextures, m_GBTextures);
 		glGenTextures(1, &m_depthBuffer);
-		glGenTextures(1, &m_blurBuffer);
+		glGenTextures(1, &m_intermediateBuffer);
 		glGenTextures(1, &m_finalBuffer);
 
 		// Set up texture formats
@@ -95,15 +95,15 @@ ErrorCode GeometryBuffer::init()
 					 Config::FramebfrVariables().gl_depth_buffer_texture_format, Config::FramebfrVariables().gl_depth_buffer_texture_type, NULL);
 		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0);
 
-		// Create the blur buffer, that acts as an intermediate buffer between vertical and horizontal blur passes
-		glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+		// Create the intermediate buffer, that acts as an intermediate buffer between vertical and horizontal blur passes
+		glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_blur_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0, 
 					 Config::FramebfrVariables().gl_blur_buffer_texture_format, Config::FramebfrVariables().gl_blur_buffer_texture_type, NULL);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Config::FramebfrVariables().gl_blur_buffer_min_filter);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Config::FramebfrVariables().gl_blur_buffer_mag_filter);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Config::FramebfrVariables().gl_blur_buffer_wrap_s_method);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Config::FramebfrVariables().gl_blur_buffer_wrap_t_method);
-		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBufferBlur, GL_TEXTURE_2D, m_blurBuffer, 0);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Config::FramebfrVariables().gl_buffers_min_filter);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Config::FramebfrVariables().gl_buffers_mag_filter);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Config::FramebfrVariables().gl_buffers_wrap_s_method);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Config::FramebfrVariables().gl_buffers_wrap_t_method);
+		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBufferIntermediate, GL_TEXTURE_2D, m_intermediateBuffer, 0);
 
 		// Create the final buffer, that gets renderred to the screen
 		glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
@@ -115,6 +115,8 @@ ErrorCode GeometryBuffer::init()
 		else
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Config::FramebfrVariables().gl_final_buffer_min_filter);
 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Config::FramebfrVariables().gl_final_buffer_mag_filter);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Config::FramebfrVariables().gl_buffers_wrap_s_method);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Config::FramebfrVariables().gl_buffers_wrap_t_method);
 		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBufferFinal, GL_TEXTURE_2D, m_finalBuffer, 0);
 		
 		// Check for errors and return an error in case of one
@@ -125,7 +127,7 @@ ErrorCode GeometryBuffer::init()
 		// Restore the default FBO, so it doesn't get changed from the outside of the class
 		//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 
-		glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+		//glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
 	}
 	return returnCode;
 }
@@ -145,14 +147,8 @@ void GeometryBuffer::setBufferSize(unsigned int p_bufferWidth, unsigned int p_bu
 			glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormats[i], m_bufferWidth, m_bufferHeight, 0, m_textureFormats[i], m_textureTypes[i], NULL);
 		}
 
-		// Create depth buffer
-		glBindTexture(GL_TEXTURE_2D, m_depthBuffer);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_bufferWidth, m_bufferHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
-		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_depth_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0,
-			Config::FramebfrVariables().gl_depth_buffer_texture_format, Config::FramebfrVariables().gl_depth_buffer_texture_type, NULL);
-
-		// Create the blur buffer, that acts as an intermediate buffer between vertical and horizontal blur passes
-		glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+		// Create the intermediate buffer, that acts as an intermediate buffer between vertical and horizontal blur passes
+		glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_blur_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0,
 			Config::FramebfrVariables().gl_blur_buffer_texture_format, Config::FramebfrVariables().gl_blur_buffer_texture_type, NULL);
 
@@ -160,6 +156,13 @@ void GeometryBuffer::setBufferSize(unsigned int p_bufferWidth, unsigned int p_bu
 		glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
 		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_final_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0,
 			Config::FramebfrVariables().gl_final_buffer_texture_format, Config::FramebfrVariables().gl_final_buffer_texture_type, NULL);
+		
+		// Create depth buffer
+		glBindTexture(GL_TEXTURE_2D, m_depthBuffer);
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_bufferWidth, m_bufferHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
+		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_depth_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0,
+			Config::FramebfrVariables().gl_depth_buffer_texture_format, Config::FramebfrVariables().gl_depth_buffer_texture_type, NULL);
+
 	}
 }
 void GeometryBuffer::setBufferSize(GLuint p_buffer, unsigned int p_bufferWidth, unsigned int p_bufferHeight)
@@ -194,9 +197,9 @@ void GeometryBuffer::setBufferSize(GLuint p_buffer, unsigned int p_bufferWidth,
 			m_bufferHeight = p_bufferHeight;
 
 			break;
-		case GBufferBlur:
+		case GBufferIntermediate:
 			// Resize the blur buffer
-			glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+			glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 			glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_blur_buffer_internal_format, p_bufferWidth, p_bufferHeight, 0, 
 						 Config::FramebfrVariables().gl_blur_buffer_texture_format, Config::FramebfrVariables().gl_blur_buffer_texture_type, NULL);
 			
@@ -210,14 +213,14 @@ void GeometryBuffer::setBufferSize(GLuint p_buffer, unsigned int p_bufferWidth,
 void GeometryBuffer::initFrame()
 {
 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
-	glDrawBuffer(GL_COLOR_ATTACHMENT0 + GBufferBlur);	// Bind blur buffer
-	glClear(GL_COLOR_BUFFER_BIT);						// and clear it
-	glDrawBuffer(GL_COLOR_ATTACHMENT0 + GBufferFinal);	// Bind final buffer
-	glClear(GL_COLOR_BUFFER_BIT);						// and clear it
+	glDrawBuffer(GL_COLOR_ATTACHMENT0 + GBufferIntermediate);	// Bind intermediate buffer
+	glClear(GL_COLOR_BUFFER_BIT);								// and clear it
+	glDrawBuffer(GL_COLOR_ATTACHMENT0 + GBufferFinal);			// Bind final buffer
+	glClear(GL_COLOR_BUFFER_BIT);								// and clear it
 }
 void GeometryBuffer::initGeometryPass()
 {
-	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
+	//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
 	glDrawBuffers(GBufferNumTextures, m_texBuffers);		// Bind geometry pass buffers to write to
 	glClear(GL_COLOR_BUFFER_BIT);
 }
@@ -271,8 +274,8 @@ void GeometryBuffer::bindForReading(GBufferTextureType p_buffer, int p_activeTex
 	case GeometryBuffer::GBufferFinal:
 		glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
 		break;
-	case GeometryBuffer::GBufferBlur:
-		glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+	case GeometryBuffer::GBufferIntermediate:
+		glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 		break;
 	}
 }
@@ -290,8 +293,8 @@ void GeometryBuffer::bindForReading(GBufferTextureType p_buffer)
 	case GeometryBuffer::GBufferFinal:
 		glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
 		break;
-	case GeometryBuffer::GBufferBlur:
-		glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+	case GeometryBuffer::GBufferIntermediate:
+		glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 		break;
 	}
 }

+ 9 - 7
Praxis3D/Source/GeometryBuffer.h

@@ -21,8 +21,10 @@ public:
 		GBufferMatProperties,
 		GBufferNumTextures,
 		GBufferFinal = GBufferNumTextures,
-		GBufferBlur,
-		GBufferTotalNumTextures
+		GBufferIntermediate,
+		GBufferTotalNumTextures,
+		GBufferInputTexture = GBufferTotalNumTextures,
+		GbufferOutputTexture
 	};
 
 	typedef unsigned int GBufferTexture;
@@ -60,8 +62,8 @@ public:
 		case GeometryBuffer::GBufferFinal:
 			glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
 			break;
-		case GeometryBuffer::GBufferBlur:
-			glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+		case GeometryBuffer::GBufferIntermediate:
+			glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 			break;
 		}
 	}
@@ -82,8 +84,8 @@ public:
 		case GeometryBuffer::GBufferFinal:
 			glBindTexture(GL_TEXTURE_2D, m_finalBuffer);
 			break;
-		case GeometryBuffer::GBufferBlur:
-			glBindTexture(GL_TEXTURE_2D, m_blurBuffer);
+		case GeometryBuffer::GBufferIntermediate:
+			glBindTexture(GL_TEXTURE_2D, m_intermediateBuffer);
 			break;
 		}
 	}
@@ -144,7 +146,7 @@ public:
 protected:
 
 	GLuint  m_GBTextures[GBufferNumTextures],	// Geometry pass textures
-			m_blurBuffer,						// Intermediate buffer between vertical and horizontal blur passes
+			m_intermediateBuffer,				// Intermediate buffer between vertical and horizontal blur passes
 			m_finalBuffer,						// Final buffer that gets copied to the screen
 			m_depthBuffer,
 			m_internalFormats[GBufferNumTextures];

+ 5 - 1
Praxis3D/Source/GeometryPass.h

@@ -35,8 +35,12 @@ public:
 		return returnError;
 	}
 
-	void update(const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
 	{
+		// Set input and output color maps for this frame
+		p_renderPassData.setColorInputMap(GeometryBuffer::GBufferIntermediate);
+		p_renderPassData.setColorOutputMap(GeometryBuffer::GBufferFinal);
+
 		// Bind the geometry framebuffer to be used
 		m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferGeometry);
 

+ 110 - 0
Praxis3D/Source/HdrMappingPass.h

@@ -0,0 +1,110 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class HdrMappingPass : public RenderPass
+{
+public:
+	HdrMappingPass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer),
+		m_HDRSSBuffer(BufferType_ShaderStorage, BufferUsageHint_DynamicCopy) { }
+
+	~HdrMappingPass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError;
+
+		m_name = "HDR Mapping Pass";
+
+		// Set HDR buffer binding index
+		m_HDRSSBuffer.m_bindingIndex = SSBOBinding_HDR;
+
+		// Assign HDR buffer data
+		m_HDRSSBuffer.m_data = &m_HDRDataSet;
+
+		// Set the HDR buffer size
+		m_HDRSSBuffer.m_size = sizeof(HDRDataSet);
+
+		// Set buffer values
+		m_emissiveAndOutputBuffers.resize(2);
+		m_emissiveAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferDiffuse);
+		m_emissiveAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferFinal);
+
+		// Create a property-set used to load blur vertical shaders
+		PropertySet hdrMappingShaderProperties(Properties::Shaders);
+		hdrMappingShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().hdr_mapping_pass_vert_shader);
+		hdrMappingShaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().hdr_mapping_pass_frag_shader);
+
+		// Create shaders
+		m_hdrMappingShader = Loaders::shader().load(hdrMappingShaderProperties);
+
+		//		 _______________________________
+		//		| LOAD HDR MAPPING PASS SHADER	|
+		//		|_______________________________|
+		shaderError = m_hdrMappingShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)					// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_hdrMappingShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+
+		// Queue HDR buffer to be created
+		m_renderer.queueForLoading(m_HDRSSBuffer);
+
+		return returnError;
+	}
+
+	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	{
+		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);
+		}
+
+		p_renderPassData.setEmissiveInputMap(GeometryBuffer::GBufferDiffuse);
+
+		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_renderer.m_backend.getGeometryBuffer()->generateMipmap(GeometryBuffer::GBufferFinal);
+
+		// Set the default framebuffer to be drawn to
+		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
+		
+		// Bind final texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal, GeometryBuffer::GBufferFinal);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(p_renderPassData.getColorInputMap(), GeometryBuffer::GBufferInputTexture);
+
+		// Bind intermediate texture for writing to, so HDR mapping is outputed to it
+		//m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferEmissive);
+		//m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferIntermediate);
+
+		// Bind textures for writing
+		m_renderer.m_backend.getGeometryBuffer()->bindBuffersForWriting(m_emissiveAndOutputBuffers);
+
+		// Perform HDR mapping. Queue and render a full screen quad using an HDR pass shader
+		m_renderer.queueForDrawing(m_hdrMappingShader->getShaderHandle(), m_hdrMappingShader->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_emissiveAndOutputBuffers;
+
+	// HDR shader
+	ShaderLoader::ShaderProgram	*m_hdrMappingShader;
+
+	// HDR shader storage buffer
+	RendererFrontend::ShaderBuffer m_HDRSSBuffer;
+
+	// HDR shader storage buffer data set
+	HDRDataSet m_HDRDataSet;
+};

+ 13 - 7
Praxis3D/Source/LightingPass.h

@@ -27,9 +27,9 @@ public:
 		m_spotLightBuffer.m_size = sizeof(SpotLightDataSet) * Config::graphicsVar().max_num_spot_lights;
 		
 		// Set buffer values
-		m_emissiveAndFinalBuffers.resize(2);
-		m_emissiveAndFinalBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferEmissive);
-		m_emissiveAndFinalBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferFinal);
+		m_emissiveAndOutputBuffers.resize(2);
+		m_emissiveAndOutputBuffers[0] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferEmissive);
+		m_emissiveAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(GeometryBuffer::GBufferFinal);
 
 		// Create a property-set used to load lighting shader
 		PropertySet lightShaderProperties(Properties::Shaders);
@@ -55,8 +55,12 @@ public:
 		return returnError;
 	}
 
-	void update(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);
+		//glEnable(GL_DEPTH_TEST);
+		//glDepthFunc(GL_NOTEQUAL);
+
 		// Setup point light buffer values
 		m_pointLightBuffer.m_size = sizeof(PointLightDataSet) * p_sceneObjects.m_pointLights.size();
 		m_pointLightBuffer.m_data = (void*)p_sceneObjects.m_pointLights.data();
@@ -72,8 +76,8 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferMatProperties, GeometryBuffer::GBufferMatProperties);
 
-		// Bind textures for writing
-		m_renderer.m_backend.getGeometryBuffer()->bindBuffersForWriting(m_emissiveAndFinalBuffers);
+		// Bind texture for writing
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
 
 		// Queue light buffer updates (so that new values that were just setup are sent to the GPU)
 		m_renderer.queueForUpdate(m_pointLightBuffer);
@@ -87,13 +91,15 @@ public:
 
 		// Pass the draw command so it is executed
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
+
+		p_renderPassData.swapColorInputOutputMaps();
 	}
 
 private:
 	ShaderLoader::ShaderProgram	*m_shaderLightPass;
 
 	// Buffer handles used for binding
-	std::vector<GeometryBuffer::GBufferTexture> m_emissiveAndFinalBuffers;
+	std::vector<GeometryBuffer::GBufferTexture> m_emissiveAndOutputBuffers;
 
 	// Light buffers
 	RendererFrontend::ShaderBuffer	m_pointLightBuffer, 

+ 60 - 0
Praxis3D/Source/PostProcessPass.h

@@ -0,0 +1,60 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class PostProcessPass : public RenderPass
+{
+public:
+	PostProcessPass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer) { }
+
+	~PostProcessPass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError;
+
+		m_name = "Post Process Rendering Pass";
+
+		// Create a property-set used to load blur vertical shaders
+		PropertySet postProcessShaderProperties(Properties::Shaders);
+		postProcessShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().postProcess_pass_vert_shader);
+		postProcessShaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().postProcess_pass_frag_shader);
+
+		// Create shaders
+		m_postProcessShader = Loaders::shader().load(postProcessShaderProperties);
+
+		//		 _______________________________
+		//		|	LOAD POST PROCESS SHADER	|
+		//		|_______________________________|
+		shaderError = m_postProcessShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)					// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_postProcessShader);	// 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);
+
+		// 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());
+
+		// 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.passScreenSpaceDrawCommandsToBackend();
+
+		p_renderPassData.swapColorInputOutputMaps();
+	}
+
+private:
+	ShaderLoader::ShaderProgram	*m_postProcessShader;
+};

+ 34 - 1
Praxis3D/Source/RenderPassBase.h

@@ -4,6 +4,39 @@
 #include "Config.h"
 #include "RendererFrontend.h"
 
+// Used to share data between rendering passes
+struct RenderPassData
+{
+	RenderPassData()
+	{
+		m_colorInputMap = GeometryBuffer::GBufferDiffuse;
+		m_colorOutputMap = GeometryBuffer::GBufferFinal;
+		m_emissiveInputMap = GeometryBuffer::GBufferEmissive;
+	}
+
+	inline void swapColorInputOutputMaps()
+	{
+		auto inputColorMap = getColorInputMap();
+		setColorInputMap(getColorOutputMap());
+		setColorOutputMap(inputColorMap);
+	}
+
+	// Setters
+	inline void setColorInputMap(GeometryBuffer::GBufferTextureType p_inputColorMap)		{ m_colorInputMap = p_inputColorMap;		}
+	inline void setColorOutputMap(GeometryBuffer::GBufferTextureType p_outputColorMap)		{ m_colorOutputMap = p_outputColorMap;		}
+	inline void setEmissiveInputMap(GeometryBuffer::GBufferTextureType p_emissiveInputMap)	{ m_emissiveInputMap = p_emissiveInputMap;	}
+
+	// Getters
+	const inline GeometryBuffer::GBufferTextureType getColorInputMap() const	{ return m_colorInputMap;		}
+	const inline GeometryBuffer::GBufferTextureType getColorOutputMap() const	{ return m_colorOutputMap;		}
+	const inline GeometryBuffer::GBufferTextureType getEmissiveInputMap() const { return m_emissiveInputMap;	}
+
+	// Remember which color maps to write to and read from, in different rendering passes.
+	GeometryBuffer::GBufferTextureType	m_colorInputMap,
+										m_colorOutputMap,
+										m_emissiveInputMap;
+};
+
 class RenderPass
 {
 public:
@@ -12,7 +45,7 @@ public:
 
 	virtual ErrorCode init() = 0;
 
-	virtual void update(const SceneObjects &p_sceneObjects, const float p_deltaTime) = 0;
+	virtual void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime) = 0;
 
 	inline CommandBuffer::Commands &getCommands() { return m_commandBuffer.getCommands(); }
 

+ 1 - 1
Praxis3D/Source/Renderer.h

@@ -95,7 +95,7 @@ public:
 	const virtual Math::Vec3f getFogColor()				const { return m_emptyVec; }
 	const virtual float getFogDensity()					const { return 0.0f; }
 
-	const unsigned int getBlurMapPosition()				const { return GeometryBuffer::GBufferTextureType::GBufferBlur;			 }
+	const unsigned int getBlurMapPosition()				const { return GeometryBuffer::GBufferTextureType::GBufferIntermediate;			 }
 	const unsigned int getDiffuseMapPosition()			const { return GeometryBuffer::GBufferTextureType::GBufferDiffuse;		 }
 	const unsigned int getEmissiveMapPosition()			const { return GeometryBuffer::GBufferTextureType::GBufferEmissive;		 }
 	const unsigned int getMatPropertiesMapPosition()	const { return GeometryBuffer::GBufferTextureType::GBufferMatProperties; }

+ 17 - 2
Praxis3D/Source/RendererFrontend.cpp

@@ -3,6 +3,8 @@
 #include "GeometryPass.h"
 #include "LightingPass.h"
 #include "FinalPass.h"
+#include "HdrMappingPass.h"
+#include "PostProcessPass.h"
 #include "ReflectionPass.h"
 #include "RendererFrontend.h"
 
@@ -33,6 +35,9 @@ ErrorCode RendererFrontend::init()
 	if(!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
 		return returnCode;
 
+	// Create the render pass data struct
+	m_renderPassData = new RenderPassData();
+
 	// Add geometry rendering pass, if it was initialized successfuly
 	GeometryPass *geometryPass = new GeometryPass(*this);
 	if(geometryPass->init() == ErrorCode::Success)
@@ -43,11 +48,21 @@ ErrorCode RendererFrontend::init()
 	if(lightingPass->init() == ErrorCode::Success)
 		m_renderingPasses.push_back(lightingPass);
 
+	// 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)
@@ -110,7 +125,7 @@ void RendererFrontend::renderFrame(const SceneObjects &p_sceneObjects, const flo
 	
 	// Prepare the geometry buffer for a new frame and a geometry pass
 	m_backend.getGeometryBuffer()->initFrame();
-	m_backend.getGeometryBuffer()->initGeometryPass();
+	//m_backend.getGeometryBuffer()->initGeometryPass();
 
 	glEnable(GL_DEPTH_TEST);		// Enable depth testing, as this is much like a regular forward render pass
 	glClear(GL_DEPTH_BUFFER_BIT);	// Make sure to clear the depth buffer for the new frame
@@ -120,7 +135,7 @@ void RendererFrontend::renderFrame(const SceneObjects &p_sceneObjects, const flo
 
 	for(decltype(m_renderingPasses.size()) i = 0, size = m_renderingPasses.size(); i < size; i++)
 	{
-		m_renderingPasses[i]->update(p_sceneObjects, p_deltaTime);
+		m_renderingPasses[i]->update(*m_renderPassData, p_sceneObjects, p_deltaTime);
 	}
 }
 

+ 11 - 1
Praxis3D/Source/RendererFrontend.h

@@ -5,14 +5,18 @@
 #include "RendererScene.h"
 
 class RenderPass;
+struct RenderPassData;
 
 class RendererFrontend
 {
 	friend class BlurPass;
 	friend class GeometryPass;
+	friend class HdrMappingPass;
 	friend class LightingPass;
+	friend class PostProcessPass;
 	friend class FinalPass;
 	friend class ReflectionPass;
+	friend class SkyPass;
 public:
 	// A handle for a uniform or shader storage buffer
 	struct ShaderBuffer
@@ -43,7 +47,7 @@ public:
 
 	// Renders a complete frame
 	void renderFrame(const SceneObjects &p_sceneObjects, const float p_deltaTime);
-
+	
 protected:
 	inline void queueForDrawing(const RenderableObjectData &p_object, const unsigned int p_shaderHandle, const ShaderUniformUpdater &p_uniformUpdater, const Math::Mat4f &p_viewProjMatrix)
 	{
@@ -231,6 +235,7 @@ protected:
 	// Renderer backend, serves as an interface layer to GPU
 	RendererBackend m_backend;
 	
+	// Holds information about the current frame, that is used in the shaders
 	UniformFrameData m_frameData;
 	
 	// Renderer commands
@@ -239,7 +244,12 @@ protected:
 	RendererBackend::BufferUpdateCommands m_bufferUpdateCommands;
 	RendererBackend::ScreenSpaceDrawCommands m_screenSpaceDrawCommands;
 
+	// An array of all active rendering passes
 	std::vector<RenderPass*> m_renderingPasses;
 
+	// Holds info used between rendering passses
+	RenderPassData *m_renderPassData;
+
+	// View - projection matrix
 	Math::Mat4f m_viewProjMatrix;
 };

+ 5 - 2
Praxis3D/Source/ShaderUniformUpdater.cpp

@@ -48,9 +48,10 @@ ErrorCode ShaderUniformUpdater::generateTextureUpdateList()
 	uniformList.push_back(new NormalMapUniform(m_shaderHandle));
 	uniformList.push_back(new EmissiveMapUniform(m_shaderHandle));
 	uniformList.push_back(new MatPropertiesMapUniform(m_shaderHandle));
-	uniformList.push_back(new BlurMapUniform(m_shaderHandle));
+	uniformList.push_back(new IntermediateMapUniform(m_shaderHandle));
 	uniformList.push_back(new FinalMapUniform(m_shaderHandle));
-	uniformList.push_back(new BlurTextureUniform(m_shaderHandle));
+	uniformList.push_back(new InputMapUniform(m_shaderHandle));
+	uniformList.push_back(new OutputMapUniform(m_shaderHandle));
 
 	// Cubemap texture uniforms
 	uniformList.push_back(new DynamicEnvironmentMapUniform(m_shaderHandle));
@@ -119,6 +120,8 @@ ErrorCode ShaderUniformUpdater::generatePerFrameList()
 	uniformList.push_back(new ElapsedTimeUniform(m_shaderHandle));
 	uniformList.push_back(new GammaUniform(m_shaderHandle));
 	uniformList.push_back(new EyeAdaptionRateUniform(m_shaderHandle));
+	uniformList.push_back(new EyeAdaptionIntendedBrightnessUniform(m_shaderHandle));
+	uniformList.push_back(new EmissiveMultiplierUniform(m_shaderHandle));
 	uniformList.push_back(new LODParallaxMappingUniform(m_shaderHandle));
 
 	// Go through each uniform and check if it is valid

+ 62 - 15
Praxis3D/Source/ShaderUniforms.h

@@ -275,6 +275,25 @@ public:
 private:
 	float m_currentAlphaThreshold;
 };
+class EmissiveMultiplierUniform : public BaseUniform
+{
+public:
+	EmissiveMultiplierUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().emissiveMultiplierUniform, p_shaderHandle), m_currentEmissiveMultiplier(-1.0) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		// Check if the same value is not already assigned (a small optimization)
+		if(m_currentEmissiveMultiplier != Config::graphicsVar().emissive_multiplier)
+		{
+			m_currentEmissiveMultiplier = Config::graphicsVar().emissive_multiplier;
+
+			glUniform1f(m_uniformHandle, m_currentEmissiveMultiplier);
+		}
+	}
+
+private:
+	float m_currentEmissiveMultiplier;
+};
 class EmissiveThresholdUniform : public BaseUniform
 {
 public:
@@ -351,6 +370,25 @@ public:
 private:
 	float eyeAdaptionRateUniform;
 };
+class EyeAdaptionIntendedBrightnessUniform : public BaseUniform
+{
+public:
+	EyeAdaptionIntendedBrightnessUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().eyeAdaptionIntBrightnessUniform, p_shaderHandle), eyeAdaptionIntendedBrightnessUniform(-1.0f) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		// Check if the same value is not already assigned (a small optimization)
+		if(eyeAdaptionIntendedBrightnessUniform != Config::graphicsVar().eye_adaption_intended_brightness)
+		{
+			eyeAdaptionIntendedBrightnessUniform = Config::graphicsVar().eye_adaption_intended_brightness;
+
+			glUniform1f(m_uniformHandle, eyeAdaptionIntendedBrightnessUniform);
+		}
+	}
+
+private:
+	float eyeAdaptionIntendedBrightnessUniform;
+};
 class LODParallaxMappingUniform : public BaseUniform
 {
 public:
@@ -371,7 +409,6 @@ private:
 	float parallaxLOD;
 };
 
-
 class DirLightColorUniform : public BaseUniform
 {
 public:
@@ -584,14 +621,14 @@ public:
 		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferMatProperties);
 	}
 };
-class BlurMapUniform : public BaseUniform
+class IntermediateMapUniform : public BaseUniform
 {
 public:
-	BlurMapUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().blurMapUniform, p_shaderHandle) { }
+	IntermediateMapUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().intermediateMapUniform, p_shaderHandle) { }
 
 	void update(const UniformData &p_uniformData)
 	{
-		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferBlur);
+		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferIntermediate);
 	}
 };
 class FinalMapUniform : public BaseUniform
@@ -604,6 +641,26 @@ public:
 		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferFinal);
 	}
 };
+class InputMapUniform : public BaseUniform
+{
+public:
+	InputMapUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().inputColorMapUniform, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferInputTexture);
+	}
+};
+class OutputMapUniform : public BaseUniform
+{
+public:
+	OutputMapUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().outputColorMapUniform, p_shaderHandle) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GbufferOutputTexture);
+	}
+};
 
 /* Unused */ class SunGlowTextureUniform : public BaseUniform
 {
@@ -667,16 +724,6 @@ public:
 		glUniform1i(m_uniformHandle, MaterialType_Emissive);
 	}
 };
-class BlurTextureUniform : public BaseUniform
-{
-public:
-	BlurTextureUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().blurTextureUniform, p_shaderHandle) { }
-
-	void update(const UniformData &p_uniformData)
-	{
-		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferBlur);
-	}
-};
 class CombinedTextureUniform : public BaseUniform
 {
 public:
@@ -706,7 +753,7 @@ public:
 
 	void update(const UniformData &p_uniformData)
 	{
-		glUniform1i(m_uniformHandle, p_uniformData.getStaticEnvMapPos());
+//		glUniform1i(m_uniformHandle, p_uniformData.m_objectData.);
 	}
 };
 

+ 62 - 0
Praxis3D/Source/SkyPass.h

@@ -0,0 +1,62 @@
+#pragma once
+
+#include "GraphicsDataSets.h"
+#include "RenderPassBase.h"
+
+class SkyPass : public RenderPass
+{
+public:
+	SkyPass(RendererFrontend &p_renderer) :
+		RenderPass(p_renderer) { }
+
+	~SkyPass() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnError = ErrorCode::Success;
+		ErrorCode shaderError;
+
+		m_name = "Blur Rendering Pass";
+
+		// Create a property-set used to load blur vertical shaders
+		PropertySet skyPassShaderShaderProperties(Properties::Shaders);
+		skyPassShaderShaderProperties.addProperty(Properties::VertexShader, Config::rendererVar().gaussian_blur_vertical_vert_shader);
+		skyPassShaderShaderProperties.addProperty(Properties::FragmentShader, Config::rendererVar().gaussian_blur_vertical_frag_shader);
+
+		// Create shaders
+		m_skyPassShader = Loaders::shader().load(skyPassShaderShaderProperties);
+
+		//		 _______________________________
+		//		|	  LOAD SKY PASS SHADER		|
+		//		|_______________________________|
+		shaderError = m_skyPassShader->loadToMemory();		// Load shader to memory
+		if(shaderError == ErrorCode::Success)					// Check if shader was loaded successfully
+			m_renderer.queueForLoading(*m_skyPassShader);	// Queue the shader to be loaded to GPU
+		else
+			returnError = shaderError;
+
+
+		return returnError;
+	}
+
+	void update(const SceneObjects &p_sceneObjects, const float p_deltaTime)
+	{
+		glDisable(GL_DEPTH_TEST);
+
+		// Set the default framebuffer to be drawn to
+		//m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
+
+		// Bind final texture for reading so it can be accessed in the shaders
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal, GeometryBuffer::GBufferFinal);
+
+		// Bind intermediate texture for writing to, so HDR mapping is outputed to it
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferIntermediate);
+
+		// Perform HDR mapping. Queue and render a full screen quad using an HDR pass shader
+		m_renderer.queueForDrawing(m_skyPassShader->getShaderHandle(), m_skyPassShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.passScreenSpaceDrawCommandsToBackend();
+	}
+
+private:
+	ShaderLoader::ShaderProgram	*m_skyPassShader;
+};