浏览代码

Added bloom effect. Optimized parallax mapping.

Added bloom effect and emissive texture support. Rewrote gaussian blur shader to remove artifacts. Moved HDR tonemapping (eye adaption) to the lighting shader to accommodate the bloom effect.
Modified parallax mapping, introduced LOD for better performance.
Fixed exporting a scene to a map file.
Paulcodedev 7 年之前
父节点
当前提交
6d9407026a

+ 222 - 53
Praxis3D/Data/Maps/default_lite.pmap

@@ -21,37 +21,12 @@
 					"Name": "DirectionalLight 1",
 					"Color": "1.0f, 1.0f, 1.0f",
 					"Direction": "0.006461f, -0.707092f, -0.707092f",
-					"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"
-						}
-					]
+					"Intensity": "0.5f"
 				},
 				{
 					"Type": "ModelObject",
 					"Name": "Terrain2",
-					"Position": "-100.0f, 0.0f, 0.0f",
+					"Position": "-570.0f, 0.0f, 0.0f",
 					"Rotation": "0.0f, 0.0f, 0.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
@@ -95,11 +70,11 @@
 				{
 					"Type": "ModelObject",
 					"Name": "Plane 1",
-					"Position": "-30.0f, 1.0f, 0.0f",
+					"Position": "30.0f, 0.0f, 0.0f",
 					"Rotation": "0.0f, 0.0f, 0.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
-					"Scale": "2.0f, 2.0f, 2.0f",
+					"Scale": "1.0f, 1.0f, 1.0f",
 					"AlphaThreshold": "0.0f",
 					"HeightScale": "0.04f",
 					"Lighting": "1",
@@ -136,6 +111,142 @@
 						]
 					}
 				},
+				{
+					"Type": "ModelObject",
+					"Name": "Barrel 1",
+					"Position": "-75.0f, 0.0f, 0.0f",
+					"Rotation": "270.0f, 0.0f, 0.0f",
+					"OffsetPosition": "0.0f, 0.0f, 0.0f",
+					"OffsetRotation": "0.0f, 0.0f, 0.0f",
+					"Scale": "2.0f, 2.0f, 2.0f",
+					"AlphaThreshold": "0.0f",
+					"HeightScale": "0.0f",
+					"Lighting": "1",
+					"TextureTilingFactor": "1.0f",
+					"Models": 
+					{
+						"Filename": "RadioactiveBarrel_01.fbx"
+					},
+					"Materials": 
+					{
+						"Diffuse": 
+						[
+							{
+								"Filename": "SciFi_Barrels_Mat_SciFi_Barrels_02_BaseColor.png",
+								"Index": "0"
+							}
+						],
+						"Normal": 
+						[
+							{
+								"Filename": "SciFi_Barrels_Mat_SciFi_Barrels_02_Normal.png",
+								"Index": "0"
+							}
+						],
+						"Emissive": 
+						[
+							{
+								"Filename": "SciFi_Barrels_Mat_SciFi_Barrels_02_Emissive.png",
+								"Index": "0"
+							}
+						],
+						"RMHAO": 
+						[
+							{
+								"Filename": "SciFi_Barrels_Mat_SciFi_Barrels_02_RMHAO.png",
+								"Index": "0"
+							}
+						]
+					}
+				},
+				{
+					"Type": "ModelObject",
+					"Name": "Tree 1",
+					"Position": "-75.0f, -2.0f, 30.0f",
+					"Rotation": "270.0f, 0.0f, 0.0f",
+					"OffsetPosition": "0.0f, 0.0f, 0.0f",
+					"OffsetRotation": "0.0f, 0.0f, 0.0f",
+					"Scale": "10.0f, 10.0f, 10.0f",
+					"AlphaThreshold": "0.0001f",
+					"HeightScale": "0.0f",
+					"Lighting": "1",
+					"TextureTilingFactor": "1.0f",
+					"Models": 
+					{
+						"Filename": "CocosNucifera_025_100_3698_LOD0.3ds"
+					},
+					"Materials": 
+					{
+						"Diffuse": 
+						[
+							{
+								"Filename": "CocosNucifera_BaseColor.png",
+								"Index": "0"
+							}
+						],
+						"Normal": 
+						[
+							{
+								"Filename": "CocosNucifera_Normal_OpenGL.png",
+								"Index": "0"
+							}
+						],
+						"Emissive": 
+						{
+						},
+						"RMHAO": 
+						[
+							{
+								"Filename": "CocosNucifera_RMHAO.png",
+								"Index": "0"
+							}
+						]
+					}
+				},
+				{
+					"Type": "ModelObject",
+					"Name": "Table 1",
+					"Position": "-75.0f, 0.0f, 20.0f",
+					"Rotation": "270.0f, 0.0f, 0.0f",
+					"OffsetPosition": "0.0f, 0.0f, 0.0f",
+					"OffsetRotation": "0.0f, 0.0f, 0.0f",
+					"Scale": "0.05f, 0.05f, 0.05f",
+					"AlphaThreshold": "0.0f",
+					"HeightScale": "0.0f",
+					"Lighting": "1",
+					"TextureTilingFactor": "1.0f",
+					"Models": 
+					{
+						"Filename": "Table.FBX"
+					},
+					"Materials": 
+					{
+						"Diffuse": 
+						[
+							{
+								"Filename": "Table_BaseColor.tga",
+								"Index": "0"
+							}
+						],
+						"Normal": 
+						[
+							{
+								"Filename": "Table_Normal.tga",
+								"Index": "0"
+							}
+						],
+						"Emissive": 
+						{
+						},
+						"RMHAO": 
+						[
+							{
+								"Filename": "Table_RMHAO.tga",
+								"Index": "0"
+							}
+						]
+					}
+				},
 				{
 					"Type": "ModelObject",
 					"Name": "Cube 1",
@@ -423,11 +534,11 @@
 				{
 					"Type": "ModelObject",
 					"Name": "light 1",
-					"Position": "-19.2421f, 10.0f, 5.45328f",
+					"Position": "12.971f, 5.0f, -68.7851f",
 					"Rotation": "0.0f, 0.0f, 0.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
-					"Scale": "1.0f, 1.0f, 1.0f",
+					"Scale": "0.5f, 0.5f, 0.5f",
 					"AlphaThreshold": "0.0f",
 					"HeightScale": "0.0f",
 					"Lighting": "1",
@@ -439,14 +550,22 @@
 					"Materials": 
 					{
 						"Diffuse": 
-						{
-						},
+						[
+							{
+								"Filename": "white.png",
+								"Index": "0"
+							}
+						],
 						"Normal": 
 						{
 						},
 						"Emissive": 
-						{
-						},
+						[
+							{
+								"Filename": "white.png",
+								"Index": "0"
+							}
+						],
 						"RMHAO": 
 						{
 						}
@@ -552,7 +671,7 @@
 					"Type": "ModelObject",
 					"Name": "light 5",
 					"Position": "-40.0f, 3.0f, 1.96449f",
-					"Rotation": "0.0f, 0.0f, 0.0f",
+					"Rotation": "-0.145991f, 0.0f, 0.989286f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Scale": "1.0f, 1.0f, 1.0f",
@@ -584,7 +703,7 @@
 					"Type": "ModelObject",
 					"Name": "light 6",
 					"Position": "-20.0f, 3.0f, -20.0f",
-					"Rotation": "0.0f, 0.0f, 0.0f",
+					"Rotation": "0.145991f, 0.0f, -0.989286f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Scale": "1.0f, 1.0f, 1.0f",
@@ -664,8 +783,8 @@
 				{
 					"Type": "ModelObject",
 					"Name": "Skybox 1",
-					"Position": "-117.386f, 11.1996f, -70.2678f",
-					"Rotation": "0.0f, 0.0f, 0.0f",
+					"Position": "-90.6898f, 7.4709f, 11.0952f",
+					"Rotation": "0.0f, -0.14598f, 26.727f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Scale": "20000.0f, 20000.0f, 20000.0f",
@@ -698,8 +817,6 @@
 					},
 					"Shaders": 
 					{
-						"FragmentShader": "skybox.frag",
-						"VertexShader": "skybox.vert"
 					}
 				},
 				{
@@ -707,16 +824,16 @@
 					"Name": "PointLight 1",
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
-					"Intensity": "10.0f",
+					"Intensity": "100.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
-					"Position": "-19.2421f, 10.0f, 5.45328f"
+					"Position": "12.971f, 5.0f, -68.7851f"
 				},
 				{
 					"Type": "PointLight",
 					"Name": "PointLight 2",
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
-					"Intensity": "10.0f",
+					"Intensity": "100.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"Position": "9.12898f, 7.98369f, 9.59357f"
 				},
@@ -725,10 +842,28 @@
 					"Name": "PointLight 3",
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
-					"Intensity": "10.0f",
+					"Intensity": "100.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"Position": "-6.94746f, 8.59811f, 7.54629f"
 				},
+				{
+					"Type": "PointLight",
+					"Name": "PointLight 45",
+					"Attenuation": "0.0f, 0.0f, 1.0f",
+					"Color": "1.0f, 1.0f, 1.0f",
+					"Intensity": "100.0f",
+					"OffsetPosition": "0.0f, 0.0f, 0.0f",
+					"Position": "-100.0f, 10.0f, 20.0f"
+				},
+				{
+					"Type": "PointLight",
+					"Name": "Barrel 1 Point Light",
+					"Attenuation": "0.0f, 0.0f, 1.0f",
+					"Color": "0.0f, 1.0f, 0.0f",
+					"Intensity": "0.1f",
+					"OffsetPosition": "0.0f, 1.8f, 0.0f",
+					"Position": "-75.0f, 1.8f, 0.0f"
+				},
 				{
 					"Type": "SpotLight",
 					"Name": "SpotLight 1",
@@ -736,7 +871,7 @@
 					"CutoffAngle": "60.0f",
 					"Color": "1.0f, 1.0f, 1.0f",
 					"Direction": "-1.0f, 0.0f, 0.0f",
-					"Intensity": "200.0f",
+					"Intensity": "20000.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Position": "60.0f, 3.0f, 60.0f"
@@ -747,8 +882,20 @@
 					"Attenuation": "0.0f, 0.0f, 1.0f",
 					"CutoffAngle": "60.0f",
 					"Color": "0.0f, 1.0f, 0.0f",
-					"Direction": "0.577353f, 0.577173f, 0.577525f",
-					"Intensity": "200.0f",
+					"Direction": "-0.145991f, 0.0f, 0.989286f",
+					"Intensity": "500.0f",
+					"OffsetPosition": "0.0f, 0.0f, 0.0f",
+					"OffsetRotation": "0.0f, 0.0f, 0.0f",
+					"Position": "-40.0f, 3.0f, 1.96449f"
+				},
+				{
+					"Type": "SpotLight",
+					"Name": "SpotLight 3",
+					"Attenuation": "0.0f, 0.0f, 1.0f",
+					"CutoffAngle": "60.0f",
+					"Color": "1.0f, 0.0f, 0.0f",
+					"Direction": "0.145991f, 0.0f, -0.989286f",
+					"Intensity": "500.0f",
 					"OffsetPosition": "0.0f, 0.0f, 0.0f",
 					"OffsetRotation": "0.0f, 0.0f, 0.0f",
 					"Position": "-40.0f, 3.0f, 1.96449f"
@@ -777,9 +924,9 @@
 				{
 					"Type": "FreeCamera",
 					"Name": "Free Camera 1",
-					"Position": "-117.387f, 11.2024f, -70.272f",
-					"Angle": "25.5279f, -0.56376f",
-					"Speed": "1.0f",
+					"Position": "-90.6949f, 7.47164f, 11.0953f",
+					"Angle": "26.727f, -0.14598f",
+					"Speed": "2.0f",
 					"SprintSpeed": "50.0f",
 					"LowerLimit": "0.0f",
 					"UpperLimit": "500.0f",
@@ -806,11 +953,25 @@
 				{
 					"Type": "DebugMoveScript",
 					"Name": "Debug Move Script 1",
-					"Position": "0.0f, 10.0f, 0.0f",
-					"Radius": "20.0f",
+					"Position": "0.0f, 5.0f, 0.0f",
+					"Radius": "70.0f",
 					"Rotation": "0.0f, 1.0f, 0.0f",
 					"Speed": "20.0f"
 				},
+				{
+					"Type": "DebugRotateScript",
+					"Name": "Debug Rotate Script 1",
+					"Axis": "0.0f, 1.0f, 0.0f",
+					"Rotation": "-0.141616f, 0.0f, 0.989922f",
+					"Speed": "100.0f"
+				},
+				{
+					"Type": "DebugRotateScript",
+					"Name": "Debug Rotate Script 2",
+					"Axis": "0.0f, 1.0f, 0.0f",
+					"Rotation": "0.141616f, 0.0f, -0.989922f",
+					"Speed": "100.0f"
+				},
 				{
 					"Type": "WorldEditScript",
 					"Name": "World Edit Script 1",
@@ -865,6 +1026,14 @@
 			"Subject": "Debug Move Script 1",
 			"Observer": "light 1"
 		},
+		{
+			"Subject": "Debug Rotate Script 1",
+			"Observer": "SpotLight 2"
+		},
+		{
+			"Subject": "Debug Rotate Script 2",
+			"Observer": "SpotLight 3"
+		},
 		{
 			"Subject": "PointLight 2",
 			"Observer": "light 2"

+ 7 - 54
Praxis3D/Data/Shaders/finalPass.frag

@@ -4,37 +4,18 @@
 //#define ENABLE_REINHARD_TONE_MAPPING
 #define ENABLE_FILMIC_TONE_MAPPING
 
-#define AVG_INTENDED_BRIGHTNESS 0.5
-#define MIN_INTENDED_BRIGHTNESS 0.005
-#define MAX_INTENDED_BRIGHTNESS 5.0
-
-
-in float avgBrightness;
-
 out vec4 outputColor;
 
-uniform sampler2D finalColorMap;
 uniform ivec2 screenSize;
 uniform float gamma;
-
-// Averages RGB color into a single brightness value
-float averageColors(vec3 p_color)
-{
-	return (p_color.x + p_color.y + p_color.z) / 3.0;
-}
+uniform sampler2D emissiveMap;
+uniform sampler2D finalColorMap;
 
 vec3 gammaCorrection(vec3 p_color, float p_gamma)
 {
 	return pow(p_color, vec3(1.0 / p_gamma));
 }
 
-// Adjusts an RGB color based on the average brightness (exposure)
-// by making overall brightness match the average intended brightness (AVG_INTENDED_BRIGHTNESS)
-vec3 brightnessMapping(vec3 p_color, float p_exposure)
-{
-	return p_color * clamp(AVG_INTENDED_BRIGHTNESS / p_exposure, MIN_INTENDED_BRIGHTNESS, MAX_INTENDED_BRIGHTNESS);
-}
-
 vec3 simpleToneMapping(vec3 p_color)
 {
     return exp(-1.0 / (2.72 * p_color + 0.15));
@@ -71,10 +52,10 @@ void main(void)
 	
 	// Perform gamma correction on the color from the final framebuffer
 	vec3 color = texture(finalColorMap, texCoord).xyz;
-		
-	// Adjust the fragment brightness based on average
-	color = brightnessMapping(color, avgBrightness);
 	
+	// Add emissive color (which is generated in a blur pass)
+	color += texture(emissiveMap, texCoord).xyz;
+		
 	#ifdef ENABLE_TONE_MAPPING
 	// Perform simple tonemapping on the final color
 	color = simpleToneMapping(color);
@@ -93,34 +74,6 @@ void main(void)
 	// Perform gamma correction as the last step of the fragment color
 	color = gammaCorrection(color, gamma);
 	
-	// Write the color to the default framebuffer
+	// Write the color to the framebuffer
 	outputColor = vec4(color, 1.0);
-}
-
-	//vec3 filmicToneMapping2(vec3 p_fragmentColor)
-	//{
-	//float3 texColor = tex2D(Texture0, texCoord ); // Tex Read
-	// Filmic Curve
-	//vec3 color = max(vec3(0.0), p_fragmentColor - 0.004); 
-	//vec3 retColor = (color * (6.2 * color + .5)) / (color * (6.2 * color + 1.7) + 0.06);
-	//return retColor;
-	//}
-	//vec3 color = pow(texture(finalColorMap, texCoord).xyz, vec3(1.0 / gamma));
-	//vec3 lumVec = textureLod(finalColorMap, texCoord, exposureMipmapLevel).xyz;
-	//float lum = (lumVec.x + lumVec.y + lumVec.z) / 3.0;
-	//lum = max(lumVec.x, max(lumVec.y, lumVec.z));
-	//float lum = lumVec.x;
-	//color = pow(uncharted2Tonemap(color), vec3(1.0 / gamma));
-	//color = uncharted2Tonemap(color);
-    // Exposure tone mapping
-    //color = vec3(1.0) - exp(-color * min(1.0 - lum, 0.5));
-    //color = vec3(1.0) - exp(-color * (0.5 / max(lum, 0.2)));
-	//color = vec3(0.5) / lum;
-	//color = color * (1.0 / max(lum, 1.0));
-	//color = color * clamp(0.5 / lum, 0.05, 5.0);
-	//color = color / (color + vec3(1.0));
-    //color = vec3(1.0) - exp(-color * (0.5 / lum));
-	//color = color / max(lum, 1.0);
-	//color = color / lum;
-	//color = filmicToneMapping(color);
-	//color = color * clamp(0.5 / lum, 0.05, 5.0);
+}

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

@@ -6,8 +6,6 @@ layout(std430, binding = 0) buffer HDRBuffer
 {
 	float screenBrightness;
 };
- 
-out float avgBrightness;
 
 uniform float eyeAdaptionRate;
 uniform float deltaTimeS;
@@ -21,11 +19,17 @@ float calcMaxMipmapLevel(vec2 p_textureSize)
 }
 
 // Averages RGB color into a single brightness value
-float averageColors(vec3 p_color)
+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
@@ -33,16 +37,14 @@ void main(void)
 	// Get maximum mipmap level (1x1) of a framebuffer
 	float exposureMipmapLevel = calcMaxMipmapLevel(screenSize);
 	// Get the current (previous frame) average brightness
-	float avgBrightnessPrevFrame = averageColors(textureLod(finalColorMap, vec2(0.0), exposureMipmapLevel).xyz);
+	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);
-	// Send average brightness to the fragment shader
-	avgBrightness = screenBrightness;
 	
 	#else
 	
 	// Set the average brightness to 0.5 so it does not affect the scene
-	avgBrightness = 0.5;
+	screenBrightness = 0.5;
 	
 	#endif
 	

+ 51 - 2
Praxis3D/Data/Shaders/gaussianBlurHorizontal.frag

@@ -5,8 +5,10 @@ in vec2 blurTexCoords[14];
 
 out vec4 outputColor;
 
-uniform sampler2D blurTexture;
+uniform sampler2D blurMap;
 uniform ivec2 screenSize;
+
+uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
  
 vec2 calcTexCoord(void)
 {
@@ -20,6 +22,51 @@ void main(void)
 	
     vec3 fragColor = vec3(0.0);
 	
+	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
+	
+	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];
+	}
+		
+	/*
+    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;
@@ -35,6 +82,8 @@ void main(void)
     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(0.0, 1.0, 1.0, 1.0);
+	//outputColor = vec4(texture(blurMap, texCoord).xyz, 1.0);
 }

+ 17 - 15
Praxis3D/Data/Shaders/gaussianBlurHorizontal.vert

@@ -6,23 +6,25 @@ uniform float blurOffset;
 
 void main(void)
 {
-    blurTexCoords[ 0] = texCoord + vec2(-0.028*blurOffset, 0.0);
-    blurTexCoords[ 1] = texCoord + vec2(-0.024*blurOffset, 0.0);
-    blurTexCoords[ 2] = texCoord + vec2(-0.020*blurOffset, 0.0);
-    blurTexCoords[ 3] = texCoord + vec2(-0.016*blurOffset, 0.0);
-    blurTexCoords[ 4] = texCoord + vec2(-0.012*blurOffset, 0.0);
-    blurTexCoords[ 5] = texCoord + vec2(-0.008*blurOffset, 0.0);
-    blurTexCoords[ 6] = texCoord + vec2(-0.004*blurOffset, 0.0);
-    blurTexCoords[ 7] = texCoord + vec2( 0.004*blurOffset, 0.0);
-    blurTexCoords[ 8] = texCoord + vec2( 0.008*blurOffset, 0.0);
-    blurTexCoords[ 9] = texCoord + vec2( 0.012*blurOffset, 0.0);
-    blurTexCoords[10] = texCoord + vec2( 0.016*blurOffset, 0.0);
-    blurTexCoords[11] = texCoord + vec2( 0.020*blurOffset, 0.0);
-    blurTexCoords[12] = texCoord + vec2( 0.024*blurOffset, 0.0);
-    blurTexCoords[13] = texCoord + vec2( 0.028*blurOffset, 0.0);
+	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
-	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	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);

+ 54 - 2
Praxis3D/Data/Shaders/gaussianBlurVertical.frag

@@ -3,11 +3,15 @@
 
 in vec2 blurTexCoords[14];
 
+//out vec4 blurBuffer;
 out vec4 outputColor;
+//layout(location = 0) out vec4 blurBuffer;
 
-uniform sampler2D emissiveTexture;
+uniform sampler2D emissiveMap;
 uniform ivec2 screenSize;
 
+uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
+
 vec2 calcTexCoord(void)
 {
     return gl_FragCoord.xy / screenSize;
@@ -20,6 +24,51 @@ void main(void)
 	
     vec3 fragColor = vec3(0.0);
 	
+	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
+	
+	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];
+	}
+		
+	/*
+    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;
@@ -35,6 +84,9 @@ void main(void)
     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(1.0, 0.0, 0.0, 1.0);
+    //blurBuffer = vec4(texture(emissiveMap, texCoord).xyz, 1.0);
 }

+ 19 - 16
Praxis3D/Data/Shaders/gaussianBlurVertical.vert

@@ -6,24 +6,27 @@ uniform float blurOffset;
 
 void main(void)
 {
-    blurTexCoords[ 0] = texCoord + vec2(0.0, -0.028*blurOffset);
-    blurTexCoords[ 1] = texCoord + vec2(0.0, -0.024*blurOffset);
-    blurTexCoords[ 2] = texCoord + vec2(0.0, -0.020*blurOffset);
-    blurTexCoords[ 3] = texCoord + vec2(0.0, -0.016*blurOffset);
-    blurTexCoords[ 4] = texCoord + vec2(0.0, -0.012*blurOffset);
-    blurTexCoords[ 5] = texCoord + vec2(0.0, -0.008*blurOffset);
-    blurTexCoords[ 6] = texCoord + vec2(0.0, -0.004*blurOffset);
-    blurTexCoords[ 7] = texCoord + vec2(0.0,  0.004*blurOffset);
-    blurTexCoords[ 8] = texCoord + vec2(0.0,  0.008*blurOffset);
-    blurTexCoords[ 9] = texCoord + vec2(0.0,  0.012*blurOffset);
-    blurTexCoords[10] = texCoord + vec2(0.0,  0.016*blurOffset);
-    blurTexCoords[11] = texCoord + vec2(0.0,  0.020*blurOffset);
-    blurTexCoords[12] = texCoord + vec2(0.0,  0.024*blurOffset);
-    blurTexCoords[13] = texCoord + vec2(0.0,  0.028*blurOffset);
+	vec2 texCoord = vec2(0.0);
 	
 	// Determine texture coordinates
-	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
+	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);
+	
 	
 	// 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);
-}
+}

+ 31 - 44
Praxis3D/Data/Shaders/geometryPass.frag

@@ -1,5 +1,8 @@
 #version 430 core
 
+#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
 
@@ -13,13 +16,6 @@ layout(location = 2) out vec3 normalBuffer;
 layout(location = 3) out vec4 emissiveBuffer;
 layout(location = 4) out vec4 matPropertiesBuffer;
 
-
-uniform mat4 MVP;
-uniform mat4 modelMat;
-uniform mat4 viewMat;
-uniform mat4 modelViewMat;
-uniform mat4 projMat;
-
 // Variables from vertex shader
 in mat3 TBN;
 in vec2 texCoord;
@@ -28,6 +24,13 @@ in vec3 normal;
 in vec3 tangentFragPos;
 in vec3 tangentCameraPos;
 in float parallaxScale;
+in float parallaxLOD;
+
+uniform mat4 MVP;
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 modelViewMat;
+uniform mat4 projMat;
 
 /* Current combined texture channels:
 	Red: Roughness
@@ -150,7 +153,7 @@ vec2 reliefParallaxMapping(vec2 p_texCoords, vec3 p_viewDir)
 	  // new depth from heightmap
 	  heightFromTexture = getHeight(currentTextureCoords);
 
-	  // shift along or agains vector V
+	  // shift along or against vector V
 	  if(heightFromTexture > currentLayerHeight) // below the surface
 	  {
 		 currentTextureCoords -= deltaTexCoord;
@@ -259,23 +262,6 @@ vec2 parallaxMappingNew(vec2 T, vec3 V)
 	// Calculate the final texture coordinate at the intersection point.
 	vec2 vFinalCoords = T + vCurrOffset;
 
-	// Use the final texture coordinates to get the normal vector, then 
-	// expand it from [0,1] to [-1,1] range.
-	//vec4 vFinalNormal = NormalHeightMap.Sample( LinearSampler, vFinalCoords ); //.a;
-		
-	// Sample the colormap at the final intersection point.
-	//vec4 vFinalColor = ColorMap.Sample( LinearSampler, vFinalCoords );
-
-	// Expand the final normal vector from [0,1] to [-1,1] range.
-	//vFinalNormal = vFinalNormal * 2.0f - 1.0f;
-
-	// Shade the fragment based on light direction and normal.
-	//vec3 vAmbient = vFinalColor.rgb * 0.1f;
-	//vec3 vDiffuse = vFinalColor.rgb * max( 0.0f, dot( L, vFinalNormal.xyz ) ) * 0.5f;
-	//vFinalColor.rgb = vAmbient + vDiffuse;
-
-	//OUT.color = vFinalColor;
-
 	return vFinalCoords;
 }
 
@@ -334,31 +320,32 @@ vec2 simpleParallaxMapping(vec2 p_texCoords, vec3 p_viewDir)
 
 void main(void)
 { 	
-	vec3 viewDir = tangentCameraPos - tangentFragPos;
-	float distanceToFrag = length(viewDir);
-	viewDir = normalize(viewDir);
-	
+	float height = getHeight(texCoord);
 	vec2 newCoords = texCoord;
 	
-	//if(distanceToFrag > 29.0)
-	//	return p_texCoords;
-	
-    // number of depth layers
-	
-	//if(distanceToFrag > 5.0)
-	//	numLayers = min(((20.0 - distanceToFrag) / 20.0), 1.0) * numLayers;
-	newCoords = parallaxOcclusionMapping(texCoord, viewDir, 1.0);
-	if(distanceToFrag < 9.90)
+	// 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)
 	{
+		vec3 viewDir = tangentCameraPos - tangentFragPos;
+		float distanceToFrag = length(viewDir);
+		viewDir = normalize(viewDir);
 		float LOD = min(((10.0 - distanceToFrag) / 10.0), 1.0);
-		float LOD2 = clamp((distanceToFrag - 8.0) / 2.0, 0.0, 1.0);
+		
+		LOD = clamp(1.0 - ((distanceToFrag * distanceToFrag) / parallaxLOD), MIN_LOD_PARALLAX, MAX_LOD_PARALLAX);
+		
+		if(LOD > LOD_PARALLAX_THRESHOLD)
+			newCoords = parallaxOcclusionMapping(texCoord, viewDir, LOD);
+	}
+	
+	//if(distanceToFrag < 9.90)
+	//{
+		//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)
 		//	newCoords = mix(parallaxOcclusionMapping(texCoord, viewDir, LOD), texCoord, 1.0 - LOD);
-	}
-	//if(distanceToFrag < 30.0)
-	//	newCoords = parallaxMappingNew2(texCoord, viewDir);
-	//vec2 newCoords = texCoord;
+	//}
 	
 	// discards a fragment when sampling outside default texture region (fixes border artifacts)
     //if(newCoords.x > 1.0 || newCoords.y > 1.0 || newCoords.x < 0.0 || newCoords.y < 0.0)
@@ -381,7 +368,7 @@ void main(void)
 	if(emissiveColor.a > emissiveThreshold)
 	{
 		// Use emissive alpha channel as an intensity multiplier
-		emissiveColor *= emissiveColor.a;
+		emissiveColor *= emissiveColor.a * 10.0;
 	}
 	else
 	{

+ 5 - 0
Praxis3D/Data/Shaders/geometryPass.vert

@@ -15,6 +15,7 @@ out vec3 normal;
 out vec3 tangentFragPos;
 out vec3 tangentCameraPos;
 out float parallaxScale;
+out float parallaxLOD;
 
 uniform mat4 MVP;
 uniform mat4 modelMat;
@@ -24,6 +25,7 @@ uniform mat4 projMat;
 uniform vec3 cameraPosVec;
 uniform float textureTilingFactor;
 uniform float heightScale;
+uniform float parallaxMappingLOD;
 
 void main(void)
 {		
@@ -31,6 +33,9 @@ void main(void)
     fragPos = vec3(modelMat * vec4(vertexPosition, 1.0));
 	normal = normalize(mat3(modelMat) * vertexNormal);
 	
+	// Square the parallax LOD distance, so there's no need to do that in the fragment shader
+	parallaxLOD = parallaxMappingLOD * parallaxMappingLOD;
+	
 	// Copy the height scale value
 	parallaxScale = heightScale;
 	

+ 12 - 0
Praxis3D/Data/Shaders/lightPass.vert

@@ -1,7 +1,19 @@
 #version 430 core
 
+#define ENABLE_HDR
+
+layout(std430, binding = 0) buffer HDRBuffer
+{
+	float screenBrightness;
+};
+
+out float avgBrightness;
+
 void main(void) 
 {
+	// Send average screen brightness to fragment shader for HDR Mapping
+	avgBrightness = screenBrightness;
+
 	// Determine texture coordinates
 	vec2 texCoord = vec2((gl_VertexID == 2) ?  2.0 :  0.0, (gl_VertexID == 1) ?  2.0 :  0.0);
 	

+ 1 - 1
Praxis3D/Data/config.ini

@@ -13,7 +13,7 @@ default_texture default.png
 generate_mipmaps 1
 gl_texture_anisotropy 16
 camera_freelook_speed 25
-face_culling 1
+face_culling 0
 eye_adaption 1
 mouse_captured 1
 mouse_warp_mode 0

+ 1 - 0
Praxis3D/Praxis3D.vcxproj

@@ -346,6 +346,7 @@
     <ClInclude Include="Source\Config.h" />
     <ClInclude Include="Source\ConfigLoader.h" />
     <ClInclude Include="Source\DebugMoveScript.h" />
+    <ClInclude Include="Source\DebugRotateScript.h" />
     <ClInclude Include="Source\DebugUIScript.h" />
     <ClInclude Include="Source\DeferredRenderer.h" />
     <ClInclude Include="Source\Engine.h" />

+ 3 - 0
Praxis3D/Praxis3D.vcxproj.filters

@@ -497,6 +497,9 @@
     <ClInclude Include="Source\BlurPass.h">
       <Filter>Renderer\Render Passes\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\DebugRotateScript.h">
+      <Filter>Scripting\Objects\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />

+ 6 - 4
Praxis3D/Source/BlurPass.h

@@ -55,25 +55,27 @@ public:
 
 	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 emissive texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
 
 		// Bind blur texture for writing to, so it can be used as an intermediate buffer between blur passes
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferBlur);
 
 		// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
-		m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
+		m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera->getBaseObjectData().m_modelMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 
 		// Bind intermediate blur texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferBlur);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferBlur, GeometryBuffer::GBufferBlur);
 
 		// Bind emissive texture for writing to, so the second pass populates it with the final blur result
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferBlur);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(GeometryBuffer::GBufferEmissive);
 
 		// 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);

+ 0 - 1
Praxis3D/Source/CommonDefinitions.h

@@ -68,7 +68,6 @@ enum MaterialType : unsigned int
 	MaterialType_Roughness = MaterialType_NumOfTypes,
 	MaterialType_Metalness,
 	MaterialType_Height,
-	MaterialType_Blur,
 	MaterialType_AmbientOcclusion,
 	MaterialType_NumOfTypes_Extended
 };

+ 1 - 1
Praxis3D/Source/Config.cpp

@@ -295,7 +295,7 @@ void Config::init()
 	AddVariablePredef(m_shaderVar, fogColorUniform);
 	AddVariablePredef(m_shaderVar, billboardScaleUniform);
 	AddVariablePredef(m_shaderVar, depthTypeUniform);
-	AddVariablePredef(m_shaderVar, eyeAdaptionRate);
+	AddVariablePredef(m_shaderVar, eyeAdaptionRateUniform);
 	AddVariablePredef(m_shaderVar, HDRSSBuffer);
 	AddVariablePredef(m_shaderVar, testMatUniform);
 	AddVariablePredef(m_shaderVar, testVecUniform);

+ 11 - 3
Praxis3D/Source/Config.h

@@ -182,9 +182,11 @@ namespace Properties
 	Code(Subject,) \
 	/* Scripting */ \
 	Code(Angle,) \
+	Code(Axis,) \
 	Code(BaseUIScript,) \
 	Code(DayOfYear,) \
 	Code(DebugMoveScript,) \
+	Code(DebugRotateScript,) \
 	Code(DebugUIScript,) \
 	Code(FreeCamera,) \
 	Code(Latitude,) \
@@ -303,9 +305,11 @@ namespace Properties
 		GetString(Observer),
 		GetString(Subject),
 		GetString(Angle),
+		GetString(Axis),
 		GetString(BaseUIScript),
 		GetString(DayOfYear),
 		GetString(DebugMoveScript),
+		GetString(DebugRotateScript),
 		GetString(DebugUIScript),
 		GetString(FreeCamera),
 		GetString(Latitude),
@@ -553,7 +557,7 @@ public:
 			rendering_res_x = 1600;
 			rendering_res_y = 900;
 			alpha_threshold = 0.0f;
-			emissive_threshold = 0.3f;
+			emissive_threshold = 0.01f;
 			eye_adaption_rate = 0.5f;
 			fog_color_x = 0.55f;
 			fog_color_y = 0.55f;
@@ -567,6 +571,7 @@ public:
 			light_color_r = 1.0f;
 			light_color_g = 1.0f;
 			light_color_b = 1.0f;
+			LOD_prallax_mapping = 100.0f;
 			height_scale = 0.0f;
 			texture_tiling_factor = 1.0f;
 			z_far = 8000.0f;
@@ -602,6 +607,7 @@ public:
 		float light_color_r;
 		float light_color_g;
 		float light_color_b;
+		float LOD_prallax_mapping;
 		float height_scale;
 		float texture_tiling_factor;
 		float z_far;
@@ -860,6 +866,7 @@ public:
 			emissiveThresholdUniform = "emissiveThreshold";
 			heightScaleUniform = "heightScale";
 			textureTilingFactorUniform = "textureTilingFactor";
+			LODParallaxUniform = "parallaxMappingLOD";
 
 			dirLightColor = "directionalLight.m_color";
 			dirLightDirection = "directionalLight.m_direction";
@@ -908,7 +915,7 @@ public:
 			billboardScaleUniform = "billboardScale";
 			depthTypeUniform = "depthType";
 
-			eyeAdaptionRate = "eyeAdaptionRate";
+			eyeAdaptionRateUniform = "eyeAdaptionRate";
 			HDRSSBuffer = "HDRBuffer";
 
 			testMatUniform = "testMat";
@@ -932,6 +939,7 @@ public:
 		std::string emissiveThresholdUniform;
 		std::string heightScaleUniform;
 		std::string textureTilingFactorUniform;
+		std::string LODParallaxUniform;
 
 		std::string dirLightColor;
 		std::string dirLightDirection;
@@ -980,7 +988,7 @@ public:
 		std::string billboardScaleUniform;
 		std::string depthTypeUniform;
 
-		std::string eyeAdaptionRate;
+		std::string eyeAdaptionRateUniform;
 		std::string HDRSSBuffer;
 
 		std::string testMatUniform;

+ 77 - 0
Praxis3D/Source/DebugRotateScript.h

@@ -0,0 +1,77 @@
+#pragma once
+
+#include "BaseScriptObject.h"
+
+// Provides bare object rotation functionality for debugging purposes (like making a spotlight rotate)
+class DebugRotateScript : public BaseScriptObject
+{
+	friend class ScriptingScene;
+public:
+	DebugRotateScript(SystemScene *p_systemScene, std::string p_name)
+		: BaseScriptObject(p_systemScene, p_name, Properties::DebugRotateScript)
+	{
+		m_speed = 10.0f;
+		m_axis = Math::normalize(Math::Vec3f(1.0f, 0.0f, 1.0f));
+		m_rotation = Math::normalize(Math::Vec3f(1.0f, 0.0f, 1.0f));
+	}
+	~DebugRotateScript() { }
+
+
+	virtual ErrorCode init()
+	{
+		return ErrorCode::Success;
+	}
+
+	void loadToMemory()
+	{
+
+	}
+
+	// Exports all the data of the object as a PropertySet
+	virtual PropertySet exportObject()
+	{
+		// Create the root property set
+		PropertySet propertySet(Properties::ArrayEntry);
+
+		// Add variables
+		propertySet.addProperty(Properties::Type, Properties::DebugRotateScript);
+		propertySet.addProperty(Properties::Name, m_name);
+		propertySet.addProperty(Properties::Axis, m_axis);
+		propertySet.addProperty(Properties::Rotation, m_rotation);
+		propertySet.addProperty(Properties::Speed, m_speed);
+
+		return propertySet;
+	}
+
+	virtual void update(const float p_deltaTime)
+	{
+		m_rotation.rotate(m_speed * p_deltaTime, m_axis);
+		m_rotation.normalize();
+		
+		postChanges(Systems::Changes::Spacial::Rotation);
+	}
+
+	const virtual Math::Vec3f &getVec3(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		switch (p_changedBits)
+		{
+		case Systems::Changes::Spacial::Rotation:
+			return m_rotation;
+			break;
+		}
+
+		return ObservedSubject::getVec3(p_observer, p_changedBits);
+	}
+
+	// Setters
+	inline void setMovementSpeed(float p_speed) { m_speed = p_speed; }
+	inline void setRotation(Math::Vec3f p_rotation) { m_rotation = p_rotation; }
+	inline void setRotationAxis(Math::Vec3f p_axis) { m_axis = p_axis; }
+
+protected:
+	float m_speed;
+
+	Math::Mat4f m_modelMatrix;
+	Math::Vec3f m_rotation,
+				m_axis;
+};

+ 0 - 2
Praxis3D/Source/EnvironmentMapObjects.h

@@ -9,8 +9,6 @@
 class EnvironmentMapObject : public BaseGraphicsObject
 {
 public:
-//	EnvironmentMapObject(SystemScene *p_systemScene, TextureLoaderCubemap::TextureCubemapHandle &p_cubemap)
-//		: BaseGraphicsObject(p_systemScene, "Null", Properties::EnvironmentMapObject), m_cubemap(p_cubemap) { }
 	EnvironmentMapObject(SystemScene *p_systemScene, const std::string &p_name, TextureLoaderCubemap::TextureCubemapHandle &p_cubemap, Properties::PropertyID p_objectType = Properties::EnvironmentMapObject)
 		: BaseGraphicsObject(p_systemScene, p_name, p_objectType), m_cubemap(p_cubemap) 
 	{ 

+ 3 - 1
Praxis3D/Source/FinalPass.h

@@ -76,7 +76,9 @@ public:
 		}
 
 		// Bind final texture for reading so it can be accessed in the shaders
-		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferFinal, GeometryBuffer::GBufferFinal);
+
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
 
 		// Set the default framebuffer to be drawn to
 		m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);

+ 2 - 1
Praxis3D/Source/GeometryBuffer.h

@@ -89,11 +89,12 @@ public:
 	}
 	inline void bindBufferForWriting(GBufferTextureType p_buffer)
 	{
+		//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
 		glDrawBuffer(GL_COLOR_ATTACHMENT0 + p_buffer);
 	}
 	inline void bindBuffersForWriting(const std::vector<GLenum> &p_buffers)
 	{
-		glDrawBuffers((GLsizei)p_buffers.size(), p_buffers.data() );
+		glDrawBuffers((GLsizei)p_buffers.size(), p_buffers.data());
 	}
 	
 	// Framebuffer binding functions

+ 1 - 0
Praxis3D/Source/LightingPass.h

@@ -69,6 +69,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferPosition, GeometryBuffer::GBufferPosition);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferDiffuse, GeometryBuffer::GBufferDiffuse);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferNormal, GeometryBuffer::GBufferNormal);
+		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferEmissive, GeometryBuffer::GBufferEmissive);
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForReading(GeometryBuffer::GBufferMatProperties, GeometryBuffer::GBufferMatProperties);
 
 		// Bind textures for writing

+ 4 - 4
Praxis3D/Source/RendererFrontend.cpp

@@ -44,9 +44,9 @@ ErrorCode RendererFrontend::init()
 		m_renderingPasses.push_back(lightingPass);
 
 	// Add blur rendering pass, if it was initialized successfully
-	//BlurPass *blurPass = new BlurPass(*this);
-	//if(blurPass->init() == ErrorCode::Success)
-	//	m_renderingPasses.push_back(blurPass);
+	BlurPass *blurPass = new BlurPass(*this);
+	if(blurPass->init() == ErrorCode::Success)
+		m_renderingPasses.push_back(blurPass);
 
 	// Add final rendering pass, if it was initialized successfuly
 	FinalPass *finalPass = new FinalPass(*this);
@@ -114,7 +114,7 @@ void RendererFrontend::renderFrame(const SceneObjects &p_sceneObjects, const flo
 
 	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
-	glDisable(GL_CULL_FACE);
+	//glDisable(GL_CULL_FACE);
 
 	//m_renderingPasses[0]->update(p_sceneObjects, p_deltaTime);
 

+ 3 - 0
Praxis3D/Source/RendererScene.cpp

@@ -187,6 +187,9 @@ PropertySet RendererScene::exportObject()
 	// Add directional light property set
 	objects.addPropertySet(m_directionalLight->exportObject());
 
+	// Add static environment map property set
+	objects.addPropertySet(m_skybox->exportObject());
+
 	// Add model object property sets
 	for(decltype(m_modelObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_modelObjPool.getNumAllocated(),
 		size = m_modelObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)

+ 29 - 0
Praxis3D/Source/ScriptingScene.cpp

@@ -100,6 +100,9 @@ SystemObject *ScriptingScene::createObject(const PropertySet &p_properties)
 	case Properties::DebugMoveScript:
 		newObject = loadDebugMove(p_properties);
 		break;
+	case Properties::DebugRotateScript:
+		newObject = loadDebugRotate(p_properties);
+		break;
 	case Properties::SolarTimeScript:
 		newObject = loadSolarTime(p_properties);
 		break;
@@ -301,6 +304,32 @@ DebugMoveScript *ScriptingScene::loadDebugMove(const PropertySet &p_properties)
 	return debugMove;
 }
 
+DebugRotateScript *ScriptingScene::loadDebugRotate(const PropertySet &p_properties)
+{
+	DebugRotateScript *debugRotate = new DebugRotateScript(this, p_properties.getPropertyByID(Properties::Name).getString());
+
+	// Load property data
+	for (decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+	{
+		switch (p_properties[i].getPropertyID())
+		{
+		case Properties::Axis:
+			debugRotate->setRotationAxis(p_properties[i].getVec3f());
+			break;
+		case Properties::Rotation:
+			debugRotate->setRotation(p_properties[i].getVec3f());
+			break;
+		case Properties::Speed:
+			debugRotate->setMovementSpeed(p_properties[i].getFloat());
+			break;
+		}
+	}
+
+	m_scriptObjects.push_back(debugRotate);
+
+	return debugRotate;
+}
+
 SolarTimeScript *ScriptingScene::loadSolarTime(const PropertySet & p_properties)
 {
 	SolarTimeScript *solarTimeScript = new SolarTimeScript(this, p_properties.getPropertyByID(Properties::Name).getString());

+ 2 - 0
Praxis3D/Source/ScriptingScene.h

@@ -4,6 +4,7 @@
 #include "CameraScript.h"
 #include "DebugUIScript.h"
 #include "DebugMoveScript.h"
+#include "DebugRotateScript.h"
 #include "NullSystemObjects.h"
 #include "ScriptingTask.h"
 #include "SolarTimeScript.h"
@@ -53,6 +54,7 @@ private:
 	FreeCamera *loadFreeCamera(const PropertySet &p_properties);
 	DebugUIScript *loadDebugUI(const PropertySet &p_properties);
 	DebugMoveScript *loadDebugMove(const PropertySet &p_properties);
+	DebugRotateScript *loadDebugRotate(const PropertySet &p_properties);
 	SolarTimeScript *loadSolarTime(const PropertySet &p_properties);
 	WorldEditScript *loadWorldEdit(const PropertySet &p_properties);
 

+ 7 - 5
Praxis3D/Source/ShaderLoader.h

@@ -224,13 +224,15 @@ public:
 		// Returns a filename of a shader of specific type
 		const inline std::string getShaderFilename(const unsigned int p_shaderType)
 		{
-			// Check if the shader type passed is valid (in bounds)
-			//if(p_shaderType >= 0 && p_shaderType < ShaderType_NumOfTypes + 1)
+			return m_shaderFilename[p_shaderType];
+
+			/*/ Check if the shader type passed is valid (in bounds)
+			if(p_shaderType >= 0 && p_shaderType < ShaderType_NumOfTypes + 1)
 				// If the shader is valid, return its filename, otherwise return an empty string
-				//if(m_shaders[p_shaderType] != nullptr)
-				//	return m_shaders[p_shaderType]->getFilename();
+				if(!m_shaderFilename[p_shaderType].empty())
+					return m_shaderFilename[p_shaderType];
 
-			return std::string();
+			return std::string();*/
 		}
 
 	private:

+ 1 - 0
Praxis3D/Source/ShaderUniformUpdater.cpp

@@ -119,6 +119,7 @@ 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 LODParallaxMappingUniform(m_shaderHandle));
 
 	// Go through each uniform and check if it is valid
 	// If it is, add it to the update list, if not, delete it

+ 1 - 1
Praxis3D/Source/ShaderUniformUpdater.h

@@ -84,7 +84,7 @@ private:
 	const inline void updateSSBBindingPoints(const UniformData &p_uniformData = m_defaultUniformData) const
 	{
 		for(decltype(m_numSSBBBlockUpdates) i = 0; i < m_numSSBBBlockUpdates; i++)
-			m_uniformBlockUpdates[i]->update(p_uniformData);
+			m_SSBBlockUpdates[i]->update(p_uniformData);
 	}
 
 	ErrorCode generateTextureUpdateList();

+ 29 - 9
Praxis3D/Source/ShaderUniforms.h

@@ -335,22 +335,42 @@ private:
 class EyeAdaptionRateUniform : public BaseUniform
 {
 public:
-	EyeAdaptionRateUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().eyeAdaptionRate, p_shaderHandle), eyeAdaptionRate(0.0f) { }
+	EyeAdaptionRateUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().eyeAdaptionRateUniform, p_shaderHandle), eyeAdaptionRateUniform(-1.0f) { }
 
 	void update(const UniformData &p_uniformData)
 	{
 		// Check if the same value is not already assigned (a small optimization)
-		if(eyeAdaptionRate != Config::graphicsVar().eye_adaption_rate)
+		if(eyeAdaptionRateUniform != Config::graphicsVar().eye_adaption_rate)
 		{
-			eyeAdaptionRate = Config::graphicsVar().eye_adaption_rate;
+			eyeAdaptionRateUniform = Config::graphicsVar().eye_adaption_rate;
 
-			glUniform1f(m_uniformHandle, eyeAdaptionRate);
+			glUniform1f(m_uniformHandle, eyeAdaptionRateUniform);
 		}
 	}
 
 private:
-	float eyeAdaptionRate;
+	float eyeAdaptionRateUniform;
 };
+class LODParallaxMappingUniform : public BaseUniform
+{
+public:
+	LODParallaxMappingUniform(unsigned int p_shaderHandle) : BaseUniform(Config::shaderVar().LODParallaxUniform, p_shaderHandle), parallaxLOD(-1.0f) { }
+
+	void update(const UniformData &p_uniformData)
+	{
+		// Check if the same value is not already assigned (a small optimization)
+		if(parallaxLOD != Config::graphicsVar().LOD_prallax_mapping)
+		{
+			parallaxLOD = Config::graphicsVar().LOD_prallax_mapping;
+
+			glUniform1f(m_uniformHandle, parallaxLOD);
+		}
+	}
+
+private:
+	float parallaxLOD;
+};
+
 
 class DirLightColorUniform : public BaseUniform
 {
@@ -581,7 +601,7 @@ public:
 
 	void update(const UniformData &p_uniformData)
 	{
-		//glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferDiffuse);
+		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferFinal);
 	}
 };
 
@@ -654,7 +674,7 @@ public:
 
 	void update(const UniformData &p_uniformData)
 	{
-		glUniform1i(m_uniformHandle, MaterialType_Blur);
+		glUniform1i(m_uniformHandle, GeometryBuffer::GBufferTextureType::GBufferBlur);
 	}
 };
 class CombinedTextureUniform : public BaseUniform
@@ -686,7 +706,7 @@ public:
 
 	void update(const UniformData &p_uniformData)
 	{
-		//glUniform1i(m_uniformHandle, p_uniformData.getStaticEnvMapPos());
+		glUniform1i(m_uniformHandle, p_uniformData.getStaticEnvMapPos());
 	}
 };
 
@@ -820,7 +840,7 @@ public:
 class HDRShaderStorageBuffer : public BaseShaderStorageBlock
 {
 public:
-	HDRShaderStorageBuffer(unsigned int p_shaderHandle) : BaseShaderStorageBlock(Config::shaderVar().spotLightBuffer, p_shaderHandle) { }
+	HDRShaderStorageBuffer(unsigned int p_shaderHandle) : BaseShaderStorageBlock(Config::shaderVar().HDRSSBuffer, p_shaderHandle) { }
 
 	void update(const UniformData &p_uniformData)
 	{

+ 3 - 3
Praxis3D/Source/WorldEditObject.h

@@ -177,12 +177,12 @@ public:
 					m_modifierKey.deactivate();
 					m_saveKey.deactivate();
 
-					if(WindowLocator::get().spawnYesNoErrorBox("World Editor", "Export the scene to \"test.pmap\"?"))
-						m_sceneLoader->saveToFile();
+					if(WindowLocator::get().spawnYesNoErrorBox("World Editor", "Export the scene to \"" + Config::gameplayVar().default_map + "\"?"))
+						m_sceneLoader->saveToFile(Config::gameplayVar().default_map);
 				}
 			}
 
-			// If an object is selected, update the its data
+			// If an object is selected, update its data
 			//if(m_selectedObject != nullptr)
 			//	m_sceneLoader->getChangeController()->sendChange(this, m_selectedObject, Systems::Changes::Spacial::Position);
 		}