Quellcode durchsuchen

*Bloom is now HDR
*Added SSAO blur filter

Panagiotis Christopoulos Charitos vor 16 Jahren
Ursprung
Commit
2365f31bc9

+ 3 - 59
shaders/final.glsl

@@ -4,8 +4,6 @@
 
 #pragma anki frag_shader_begins
 
-#pragma anki include "shaders/median_filter.glsl"
-
 #pragma anki uniform raster_image 0
 uniform sampler2D raster_image;
 varying vec2 tex_coords;
@@ -14,62 +12,8 @@ void main()
 {
 	//if( gl_FragCoord.x > 0.5 ) discard;
 
-	//gl_FragColor.rgb = texture2D( raster_image, tex_coords ).rgb;
-	gl_FragColor.rgb = MedianFilter( raster_image, tex_coords );
+	gl_FragColor.rgb = texture2D( raster_image, tex_coords ).rgb;
+	//gl_FragColor.rgb = MedianFilter( raster_image, tex_coords );
 	//gl_FragColor.rgb = vec3( gl_FragCoord.xy/tex_size_, 0.0 );
 	//gl_FragColor.rgb = vec3( gl_FragCoord.xy*vec2( 1.0/R_W, 1.0/R_H ), 0.0 );
-}
-
-/*
-3x3 Median
-Morgan McGuire and Kyle Whitson
-http://graphics.cs.williams.edu
-*
-
-// Input texture
-
-vec2 Tinvsize = vec2( 1/R_W*R_Q, 1/R_H*R_Q );
-
-
-// Change these 2 defines to change precision,
-#define vec vec3
-#define toVec(x) x.rgb
-
-//#define vec vec4
-//#define toVec(x) x.rgba
-
-#define s2(a, b)				temp = a; a = min(a, b); b = max(temp, b);
-#define mn3(a, b, c)			s2(a, b); s2(a, c);
-#define mx3(a, b, c)			s2(b, c); s2(a, c);
-
-#define mnmx3(a, b, c)			mx3(a, b, c); s2(a, b);                                   // 3 exchanges
-#define mnmx4(a, b, c, d)		s2(a, b); s2(c, d); s2(a, c); s2(b, d);                   // 4 exchanges
-#define mnmx5(a, b, c, d, e)	s2(a, b); s2(c, d); mn3(a, c, e); mx3(b, d, e);           // 6 exchanges
-#define mnmx6(a, b, c, d, e, f) s2(a, d); s2(b, e); s2(c, f); mn3(a, b, c); mx3(d, e, f); // 7 exchanges
-
-void main() {
-
-  vec v[9];
-
-  // Add the pixels which make up our window to the pixel array.
-  for(int dX = -1; dX <= 1; ++dX) {
-    for(int dY = -1; dY <= 1; ++dY) {
-      vec2 offset = vec2(float(dX), float(dY));
-
-      // If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + (dY + R) of the
-      // pixel array. This will fill the pixel array, with the top left pixel of the window at pixel[0] and the
-      // bottom right pixel of the window at pixel[N-1].
-      v[(dX + 1) * 3 + (dY + 1)] = texture2D(raster_image, tex_coords + offset * Tinvsize).rgb;
-    }
-  }
-
-  vec temp;
-
-  // Starting with a subset of size 6, remove the min and max each time
-  mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]);
-  mnmx5(v[1], v[2], v[3], v[4], v[6]);
-  mnmx4(v[2], v[3], v[4], v[7]);
-  mnmx3(v[3], v[4], v[8]);
-  gl_FragColor.rgb = v[4];
-}*/
-
+}

+ 32 - 2
shaders/median_filter.glsl

@@ -15,7 +15,7 @@ http://graphics.cs.williams.edu
 
 vec3 MedianFilter( in sampler2D tex, in vec2 tex_coords )
 {
-	vec2 tex_inv_size = 1.0/textureSize(tex, 0);
+	vec2 tex_inv_size = 1.0/vec2(textureSize(tex, 0));
   vec3 v[9];
 
   // Add the pixels which make up our window to the pixel array.
@@ -40,4 +40,34 @@ vec3 MedianFilter( in sampler2D tex, in vec2 tex_coords )
   mnmx4(v[2], v[3], v[4], v[7]);
   mnmx3(v[3], v[4], v[8]);
   return v[4];
-}
+}
+
+
+float MedianFilterAlpha( in sampler2D tex, in vec2 tex_coords )
+{
+	vec2 tex_inv_size = 1.0/vec2(textureSize(tex, 0));
+  float v[9];
+
+  // Add the pixels which make up our window to the pixel array.
+	for(int dX = -1; dX <= 1; ++dX)
+	{
+		for(int dY = -1; dY <= 1; ++dY)
+		{
+			vec2 offset = vec2(float(dX), float(dY));
+
+			// If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + (dY + R) of the
+			// pixel array. This will fill the pixel array, with the top left pixel of the window at pixel[0] and the
+			// bottom right pixel of the window at pixel[N-1].
+			v[(dX + 1) * 3 + (dY + 1)] = texture2D(tex, tex_coords + offset * tex_inv_size).a;
+		}
+	}
+
+  float temp;
+
+  // Starting with a subset of size 6, remove the min and max each time
+  mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]);
+  mnmx5(v[1], v[2], v[3], v[4], v[6]);
+  mnmx4(v[2], v[3], v[4], v[7]);
+  mnmx3(v[3], v[4], v[8]);
+  return v[4];
+}

+ 5 - 6
shaders/pps.glsl

@@ -9,7 +9,7 @@
 uniform sampler2D is_fai;
 uniform sampler2D pps_ssao_fai;
 uniform sampler2D ms_normal_fai;
-uniform sampler2D pps_boom_fai;
+uniform sampler2D pps_hdr_fai;
 uniform sampler2D pps_lscatt_fai;
 
 varying vec2 tex_coords;
@@ -178,10 +178,9 @@ void main (void)
 		color += lscatt;
 	#endif
 
-	#if defined(_BLOOM_)
-		//float bloom_factor = texture2D( pps_boom_fai, tex_coords ).r; // ORIGINAL BLOOM CODE
-		vec3 bloom = texture2D( pps_boom_fai, tex_coords ).rgb;
-		color += bloom;
+	#if defined(_HDR_)
+		vec3 hdr = texture2D( pps_hdr_fai, tex_coords ).rgb;
+		color += hdr;
 	#endif
 
 	color = BlendHardLight( vec3(0.6, 0.62, 0.4), color );
@@ -197,6 +196,6 @@ void main (void)
 	//gl_FragColor = texture2D( pps_boom_fai, tex_coords );
 	//gl_FragColor = texture2D( is_fai, tex_coords );
 	//gl_FragData[0].rgb = UnpackNormal( texture2D( ms_normal_fai, tex_coords ).rg );
-	//gl_FragData[0] = vec4( bloom*2, 1.0 );
+	//gl_FragData[0] = vec4( hdr, 1.0 );
 }
 

+ 0 - 3
shaders/pps_bloom_final.glsl

@@ -1,3 +0,0 @@
-#define _BLOOM_FINAL_
-#pragma anki uniform bloom_final_fai 0
-#pragma anki include "shaders/pps_bloom_generic.glsl"

+ 0 - 78
shaders/pps_bloom_generic.glsl

@@ -1,78 +0,0 @@
-#pragma anki vert_shader_begins
-
-#pragma anki include "shaders/simple_vert.glsl"
-
-#pragma anki frag_shader_begins
-
-// the first pass is for horizontal blur and the second for vertical
-
-varying vec2 tex_coords;
-
-#if defined( _BLOOM_VBLUR_ )
-	uniform sampler2D is_fai;
-#elif defined ( _BLOOM_FINAL_ )
-	uniform sampler2D bloom_final_fai; // ToDo: rename
-#else
-	#error "something is wrong"
-#endif
-
-
-
-/*
-=======================================================================================================================================
-main                                                                                                                                  =
-=======================================================================================================================================
-*/
-void main (void)
-{
-	const float super_offset = 1.;
-	#if defined( _BLOOM_VBLUR_ )
-		const float offset = 1.0 / (R_W*R_Q*BLOOM_RENDERING_QUALITY) * super_offset; // 1 / width_of_the_IS_FAI     !!!!!!!!!!!!!!!!!!!!!!!
-	#else
-		const float offset = 1.0 / (R_H*R_Q*BLOOM_RENDERING_QUALITY) * super_offset; // 1 / height_of_the_BLOOM_FAI
-	#endif
-
-	const int kernel_size = 7;
-	float kernel[kernel_size];
-	kernel[0] = -3.0 * offset;
-	kernel[1] = -2.0 * offset;
-	kernel[2] = -1.0 * offset;
-	kernel[3] = 0.0 * offset;
-	kernel[4] = 1.0 * offset;
-	kernel[5] = 2.0 * offset;
-	kernel[6] = 3.0 * offset;
-	/*kernel[7] = -4.0 * offset;
-	kernel[8] = 4.0 * offset;
-	kernel[9] = -5.0 * offset;
-	kernel[10] = 5.0 * offset;*/
-
-	//float bloom_factor = 0.0; // ORIGINAL BLOOM CODE
-	vec3 bloom = vec3(0.0);
-
-	for( int i=0; i<kernel_size; i++ )
-	{
-		#if defined( _BLOOM_VBLUR_ )
-			vec3 color = texture2D( is_fai, tex_coords + vec2(kernel[i], 0.0) ).rgb;
-
-			float Y = dot(vec3(0.30, 0.59, 0.11), color);
-			const float exposure = 4.0;
-			const float brightMax = 4.0;
-			float YD = exposure * (exposure/brightMax + 1.0) / (exposure + 1.0) * Y;
-			color *= YD;
-
-			bloom += color;
-			//vec3 color = texture2D( is_fai, tex_coords + vec2(kernel[i], 0.0) ).rgb; // ORIGINAL BLOOM CODE
-			//bloom_factor += dot(tex,tex); // ORIGINAL BLOOM CODE
-		#else
-			vec3 color = texture2D( bloom_final_fai, tex_coords + vec2(0.0, kernel[i]) ).rgb;
-			bloom += color;
-
-			//float factor = texture2D( bloom_final_fai, tex_coords + vec2(0.0, kernel[i]) ).r; // ORIGINAL BLOOM CODE
-			//bloom_factor += factor; // ORIGINAL BLOOM CODE
-		#endif
-	}
-
-	gl_FragColor.rgb = bloom * (1.0/kernel_size);
-	//gl_FragColor.r = bloom_factor * (1.0/7.0); // ORIGINAL BLOOM CODE
-}
-

+ 0 - 3
shaders/pps_bloom_vblur.glsl

@@ -1,3 +0,0 @@
-#define _BLOOM_VBLUR_
-#pragma anki uniform is_fai 0
-#pragma anki include "shaders/pps_bloom_generic.glsl"

+ 71 - 0
shaders/pps_hdr_generic.glsl

@@ -0,0 +1,71 @@
+#pragma anki vert_shader_begins
+
+#pragma anki include "shaders/simple_vert.glsl"
+
+#pragma anki frag_shader_begins
+
+#pragma anki include "shaders/median_filter.glsl"
+
+varying vec2 tex_coords;
+
+#pragma anki uniform tex 0
+uniform sampler2D tex;
+
+void main()
+{
+	//gl_FragData[0].rgb = texture2D( tex, tex_coords).rgb;return;
+
+	/*if( tex_coords.x*R_W > textureSize(tex,0).x/2 )
+		gl_FragData[0].rgb = vec3( 1, 0, 0 );
+	else
+		gl_FragData[0].rgb = vec3( 0, 1, 0 );
+	return;*/
+
+	#if defined( _PPS_HDR_PASS_0_ ) || defined( _PPS_HDR_PASS_1_ )
+		const float super_offset = 1.5;
+
+		#if defined( _PPS_HDR_PASS0_ )
+			float offset = 1.0 / float(textureSize(tex,0).x) * super_offset;
+		#else
+			float offset = 1.0 / float(textureSize(tex,0).y) * super_offset;
+		#endif
+
+		const int KERNEL_SIZE = 9;
+		float kernel[KERNEL_SIZE];
+		kernel[0] = -3.0 * offset;
+		kernel[1] = -2.0 * offset;
+		kernel[2] = -1.0 * offset;
+		kernel[3] = 0.0 * offset;
+		kernel[4] = 1.0 * offset;
+		kernel[5] = 2.0 * offset;
+		kernel[6] = 3.0 * offset;
+		kernel[7] = -4.0 * offset;
+		kernel[8] = 4.0 * offset;
+		/*kernel[9] = -5.0 * offset;
+		kernel[10] = 5.0 * offset;*/
+
+		vec3 color = vec3(0.0);
+
+		for( int i=0; i<KERNEL_SIZE; i++ )
+		{
+			#if defined( _PPS_HDR_PASS_0_ )
+				color += texture2D( tex, tex_coords + vec2(kernel[i], 0.0) ).rgb;
+			#else // _PPS_HDR_PASS_1_
+				color += texture2D( tex, tex_coords + vec2(0.0, kernel[i]) ).rgb;
+			#endif
+		}
+
+		gl_FragData[0].rgb = color / KERNEL_SIZE;
+
+	#else // _PPS_HDR_PASS_2_
+		vec3 color = MedianFilter( tex, tex_coords );
+		//vec3 color = texture2D( tex, tex_coords ).rgb;
+
+		float Y = dot(vec3(0.30, 0.59, 0.11), color);
+		const float exposure = 4.0;
+		const float brightMax = 4.0;
+		float YD = exposure * (exposure/brightMax + 1.0) / (exposure + 1.0) * Y;
+		color *= YD;
+		gl_FragData[0].rgb = color;
+	#endif
+}

+ 3 - 0
shaders/pps_hdr_pass0.glsl

@@ -0,0 +1,3 @@
+#define _PPS_HDR_PASS_0_
+
+#pragma anki include "shaders/pps_hdr_generic.glsl"

+ 3 - 0
shaders/pps_hdr_pass1.glsl

@@ -0,0 +1,3 @@
+#define _PPS_HDR_PASS_1_
+
+#pragma anki include "shaders/pps_hdr_generic.glsl"

+ 3 - 0
shaders/pps_hdr_pass2.glsl

@@ -0,0 +1,3 @@
+#define _PPS_HDR_PASS_2_
+
+#pragma anki include "shaders/pps_hdr_generic.glsl"

+ 1 - 1
shaders/pps_ssao.glsl

@@ -17,7 +17,7 @@ uniform sampler2D noise_map;
 uniform sampler2D ms_normal_fai;
 
 varying vec2 tex_coords;
-const float totStrength = 1.0;
+const float totStrength = 1.7;
 const float strength = 0.07;
 const float offset = 18.0;
 const float falloff = 0.000002;

+ 17 - 0
shaders/pps_ssao_blur.glsl

@@ -0,0 +1,17 @@
+#pragma anki vert_shader_begins
+
+#pragma anki include "shaders/simple_vert.glsl"
+
+#pragma anki frag_shader_begins
+
+#pragma anki include "shaders/median_filter.glsl"
+
+varying vec2 tex_coords;
+
+#pragma anki uniform tex 0
+uniform sampler2D tex;
+
+void main()
+{
+	gl_FragColor.a = MedianFilterAlpha( tex, tex_coords );
+}

+ 3 - 3
src/main.cpp

@@ -274,9 +274,9 @@ int main( int /*argc*/, char* /*argv*/[] )
 		// std stuff follow
 		SDL_GL_SwapBuffers();
 		r::PrintLastError();
-		//if( r::frames_num == 10 ) r::TakeScreenshot("gfx/screenshot.tga");
-		//hndl::WaitForNextFrame();
-		if( r::frames_num == 5000 ) break;
+		if( r::frames_num == 10 ) r::TakeScreenshot("gfx/screenshot.tga");
+		hndl::WaitForNextFrame();
+		//if( r::frames_num == 5000 ) break;
 	}while( true );
 	PRINT( "Exiting main loop (" << hndl::GetTicks()-ticks << ")" );
 

+ 10 - 10
src/renderer/r_pps.cpp

@@ -29,7 +29,7 @@ namespace shdr_vars
 	int is_fai;
 	int pps_ssao_fai;
 	int ms_normal_fai;
-	int bloom_fai;
+	int hdr_fai;
 	int lscatt_fai;
 }
 
@@ -73,10 +73,10 @@ void Init()
 		shdr_vars::pps_ssao_fai = shdr_post_proc_stage->GetUniformLocation( "pps_ssao_fai" );
 	}
 
-	if( r::pps::bloom::enabled )
+	if( r::pps::hdr::enabled )
 	{
-		r::pps::bloom::Init();
-		shdr_vars::bloom_fai = shdr_post_proc_stage->GetUniformLocation( "pps_boom_fai" );
+		r::pps::hdr::Init();
+		shdr_vars::hdr_fai = shdr_post_proc_stage->GetUniformLocation( "pps_hdr_fai" );
 	}
 
 	if( r::pps::edgeaa::enabled )
@@ -101,8 +101,8 @@ void RunStage( const camera_t& cam )
 	if( r::pps::ssao::enabled )
 		r::pps::ssao::RunPass( cam );
 
-	if( r::pps::bloom::enabled )
-		r::pps::bloom::RunPass( cam );
+	if( r::pps::hdr::enabled )
+		r::pps::hdr::RunPass( cam );
 
 	if( r::pps::lscatt::enabled )
 		r::pps::lscatt::RunPass( cam );
@@ -124,7 +124,7 @@ void RunStage( const camera_t& cam )
 
 	if( r::pps::ssao::enabled )
 	{
-		r::pps::ssao::fai.Bind(1);
+		r::pps::ssao::blured_fai.Bind(1);
 		glUniform1i( shdr_vars::pps_ssao_fai, 1 );
 	}
 
@@ -134,10 +134,10 @@ void RunStage( const camera_t& cam )
 		glUniform1i( shdr_vars::ms_normal_fai, 2 );
 	}
 
-	if( r::pps::bloom::enabled )
+	if( r::pps::hdr::enabled )
 	{
-		r::pps::bloom::final_fai.Bind(3);
-		glUniform1i( shdr_vars::bloom_fai, 3 );
+		r::pps::hdr::pass2_fai.Bind(3);
+		glUniform1i( shdr_vars::hdr_fai, 3 );
 	}
 
 	if( r::pps::lscatt::enabled )

+ 40 - 33
src/renderer/r_pps_bloom.cpp → src/renderer/r_pps_hdr.cpp

@@ -11,7 +11,7 @@ The file contains functions and vars used for the deferred shading/post-processi
 
 namespace r {
 namespace pps {
-namespace bloom {
+namespace hdr {
 
 
 /*
@@ -21,24 +21,25 @@ VARS
 */
 bool enabled = true;
 
-static fbo_t vblur_fbo, final_fbo; // yet another FBO and another, damn
+static fbo_t pass0_fbo, pass1_fbo, pass2_fbo; // yet another FBO and another, damn
 
 float rendering_quality = 0.25; // 1/4 of the image
 static uint wwidth, wheight; // render width and height
 
-// bloom images
-texture_t vbrur_fai; // for vertical blur pass
-texture_t final_fai; // with the horizontal blur
+// hdr images
+texture_t pass0_fai; // for vertical blur pass
+texture_t pass1_fai; // with the horizontal blur
+texture_t pass2_fai;
 
-static shader_prog_t* shdr_pps_bloom_vblur, * shdr_pps_bloom_final; // bloom pass 0 and pass 1 shaders
+static shader_prog_t* pass0_shdr, * pass1_shdr, * pass2_shdr; // hdr pass 0 and pass 1 shaders
 
 
 /*
 =======================================================================================================================================
-InitFBOP0                                                                                                                             =
+InitFBOs                                                                                                                              =
 =======================================================================================================================================
 */
-static void InitFBOs( fbo_t& fbo, texture_t& fai )
+static void InitFBOs( fbo_t& fbo, texture_t& fai, int internal_format )
 {
 	// create FBO
 	fbo.Create();
@@ -48,9 +49,7 @@ static void InitFBOs( fbo_t& fbo, texture_t& fai )
 	fbo.SetNumOfColorAttachements(1);
 
 	// create the texes
-	// we need one chanel onle (red) because the output is grayscale
-	//fai_bloom.CreateEmpty( wwidth, wheight, 1, GL_RED, GL_UNSIGNED_BYTE ); // ORIGINAL BLOOM CODE
-	fai.CreateEmpty( wwidth, wheight, GL_RGB, GL_RGB );
+	fai.CreateEmpty( wwidth, wheight, internal_format, GL_RGB );
 	fai.TexParameter( GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 	fai.TexParameter( GL_TEXTURE_MIN_FILTER, GL_NEAREST );
 
@@ -59,7 +58,7 @@ static void InitFBOs( fbo_t& fbo, texture_t& fai )
 
 	// test if success
 	if( !fbo.CheckStatus() )
-		FATAL( "Cannot create deferred shading post-processing stage bloom passes FBO" );
+		FATAL( "Cannot create deferred shading post-processing stage HDR passes FBO" );
 
 	// unbind
 	fbo.Unbind();
@@ -73,16 +72,17 @@ Init
 */
 void Init()
 {
-	DEBUG_ERR( rendering_quality<0.0 || rendering_quality>1.0 );
-	wwidth = r::rendering_quality * r::pps::ssao::rendering_quality * r::w;
-	wheight = r::rendering_quality * r::pps::ssao::rendering_quality * r::h;
+	wwidth = r::rendering_quality * r::pps::hdr::rendering_quality * r::w;
+	wheight = r::rendering_quality * r::pps::hdr::rendering_quality * r::h;
 
-	InitFBOs( vblur_fbo, vbrur_fai );
-	InitFBOs( final_fbo, final_fai );
+	InitFBOs( pass0_fbo, pass0_fai, GL_RGB );
+	InitFBOs( pass1_fbo, pass1_fai, GL_RGB );
+	InitFBOs( pass2_fbo, pass2_fai, GL_RGB );
 
 	// init shaders
-	shdr_pps_bloom_vblur = rsrc::shaders.Load( "shaders/pps_bloom_vblur.glsl" );
-	shdr_pps_bloom_final = rsrc::shaders.Load( "shaders/pps_bloom_final.glsl" );
+	pass0_shdr = rsrc::shaders.Load( "shaders/pps_hdr_pass0.glsl" );
+	pass1_shdr = rsrc::shaders.Load( "shaders/pps_hdr_pass1.glsl" );
+	pass2_shdr = rsrc::shaders.Load( "shaders/pps_hdr_pass2.glsl" );
 }
 
 
@@ -100,42 +100,49 @@ void RunPass( const camera_t& /*cam*/ )
 
 
 	// pass 0
-	vblur_fbo.Bind();
+	pass0_fbo.Bind();
 
-	shdr_pps_bloom_vblur->Bind();
+	pass0_shdr->Bind();
 
-	shdr_pps_bloom_vblur->LocTexUnit( shdr_pps_bloom_vblur->GetUniformLocation(0), r::is::fai, 0 );
+	pass0_shdr->LocTexUnit( pass0_shdr->GetUniformLocation(0), r::is::fai, 0 );
 
 	// Draw quad
 	glEnableClientState( GL_VERTEX_ARRAY );
-	glEnableClientState( GL_TEXTURE_COORD_ARRAY );
-
 	glVertexPointer( 2, GL_FLOAT, 0, quad_vert_cords );
-
 	glDrawArrays( GL_QUADS, 0, 4 );
-
 	glDisableClientState( GL_VERTEX_ARRAY );
 
 
 	// pass 1
-	final_fbo.Bind();
+	pass1_fbo.Bind();
 
-	shdr_pps_bloom_final->Bind();
+	pass1_shdr->Bind();
 
-	shdr_pps_bloom_final->LocTexUnit( shdr_pps_bloom_final->GetUniformLocation(0), vbrur_fai, 0 );
+	pass1_shdr->LocTexUnit( pass1_shdr->GetUniformLocation(0), pass0_fai, 0 );
 
 	// Draw quad
 	glEnableClientState( GL_VERTEX_ARRAY );
-	glEnableClientState( GL_TEXTURE_COORD_ARRAY );
-
 	glVertexPointer( 2, GL_FLOAT, 0, quad_vert_cords );
-
 	glDrawArrays( GL_QUADS, 0, 4 );
+	glDisableClientState( GL_VERTEX_ARRAY );
+
+
+	// pass 2
+	pass2_fbo.Bind();
 
+	pass2_shdr->Bind();
+
+	pass2_shdr->LocTexUnit( pass2_shdr->GetUniformLocation(0), pass1_fai, 0 );
+
+	// Draw quad
+	glEnableClientState( GL_VERTEX_ARRAY );
+	glVertexPointer( 2, GL_FLOAT, 0, quad_vert_cords );
+	glDrawArrays( GL_QUADS, 0, 4 );
 	glDisableClientState( GL_VERTEX_ARRAY );
 
+
 	// end
-	final_fbo.Unbind();
+	fbo_t::Unbind();
 }
 
 

+ 47 - 4
src/renderer/r_pps_ssao.cpp

@@ -19,20 +19,49 @@ namespace ssao {
 VARS                                                                                                                                  =
 =======================================================================================================================================
 */
-static fbo_t fbo; // yet another FBO
+static fbo_t fbo, blur_fbo; // yet another FBO
 
 float rendering_quality = 0.25; // the rendering_quality of the SSAO fai. Chose low so it can blend
 bool enabled = true;
 
 static uint wwidth, wheight; // window width and height
 
-texture_t fai; // SSAO factor
+texture_t fai, blured_fai; // SSAO factor
 
-static shader_prog_t* shdr_ppp_ssao;
+static shader_prog_t* shdr_ppp_ssao, * blur_shdr;
 
 static texture_t* noise_map;
 
 
+//=====================================================================================================================================
+// InitBlurFBO                                                                                                                        =
+//=====================================================================================================================================
+static void InitBlurFBO()
+{
+	// create FBO
+	blur_fbo.Create();
+	blur_fbo.Bind();
+
+	// inform in what buffers we draw
+	blur_fbo.SetNumOfColorAttachements(1);
+
+	// create the texes
+	blured_fai.CreateEmpty( wwidth, wheight, GL_ALPHA8, GL_ALPHA );
+	blured_fai.TexParameter( GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+	blured_fai.TexParameter( GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+
+	// attach
+	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, blured_fai.GetGLID(), 0 );
+
+	// test if success
+	if( !blur_fbo.CheckStatus() )
+		FATAL( "Cannot create deferred shading post-processing stage SSAO blur FBO" );
+
+	// unbind
+	blur_fbo.Unbind();
+}
+
+
 /*
 =======================================================================================================================================
 Init                                                                                                                                  =
@@ -82,6 +111,10 @@ void Init()
 	//noise_map->TexParameter( GL_TEXTURE_MIN_FILTER, GL_NEAREST );
 	r::texture_compression = tex_compr;
 	r::mipmaping = mipmaping;
+
+	// blur FBO
+	InitBlurFBO();
+	blur_shdr = rsrc::shaders.Load( "shaders/pps_ssao_blur.glsl" );
 }
 
 
@@ -113,8 +146,18 @@ void RunPass( const camera_t& cam )
 	glDrawArrays( GL_QUADS, 0, 4 );
 	glDisableClientState( GL_VERTEX_ARRAY );
 
+
+	// second pass. blur
+	blur_fbo.Bind();
+	blur_shdr->Bind();
+	blur_shdr->LocTexUnit( blur_shdr->GetUniformLocation(0), fai, 0 );
+	glEnableClientState( GL_VERTEX_ARRAY );
+	glVertexPointer( 2, GL_FLOAT, 0, quad_vert_cords );
+	glDrawArrays( GL_QUADS, 0, 4 );
+	glDisableClientState( GL_VERTEX_ARRAY );
+
 	// end
-	fbo.Unbind();
+	fbo_t::Unbind();
 }
 
 

+ 5 - 3
src/renderer/r_private.h

@@ -66,15 +66,17 @@ namespace pps
 		extern void Init();
 		extern void RunPass( const camera_t& cam );
 		extern texture_t fai;
+		extern texture_t blured_fai;
 		extern float rendering_quality;
 	}
 
-	namespace bloom
+	namespace hdr
 	{
 		extern void Init();
 		extern void RunPass( const camera_t& cam );
-		extern texture_t vbrur_fai;
-		extern texture_t final_fai;
+		extern texture_t pass0_fai;
+		extern texture_t pass1_fai;
+		extern texture_t pass2_fai;
 		extern float rendering_quality;
 	}
 

+ 3 - 3
src/renderer/renderer.cpp

@@ -70,10 +70,10 @@ static void BuildStdShaderPreProcStr()
 	}
 	if( r::pps::edgeaa::enabled )
 		tmp += "#define _EDGEAA_\n";
-	if( r::pps::bloom::enabled )
+	if( r::pps::hdr::enabled )
 	{
-		tmp += "#define _BLOOM_\n";
-		tmp += "#define BLOOM_RENDERING_QUALITY " + FloatToStr(r::pps::bloom::rendering_quality) + "\n";
+		tmp += "#define _HDR_\n";
+		tmp += "#define HDR_RENDERING_QUALITY " + FloatToStr(r::pps::hdr::rendering_quality) + "\n";
 	}
 	if( r::pps::lscatt::enabled )
 	{

+ 1 - 1
src/renderer/renderer.h

@@ -100,7 +100,7 @@ namespace pps
 	{
 		extern bool enabled; ///< EdgeAA on/of
 	}
-	namespace bloom
+	namespace hdr
 	{
 		extern bool enabled; ///< Bloom on/of
 	}