From 34b393334cb9ce585780921e2ac533fbd7220c66 Mon Sep 17 00:00:00 2001
From: Emmanuel Benoit <tseeker@nocternity.net>
Date: Sat, 30 Sep 2017 21:22:38 +0200
Subject: [PATCH] Tweaking bloom some more

---
 Makefile           |  2 +-
 bloom-combine.glsl |  8 +++--
 bloom.cc           | 90 ++++++++++++++++++++--------------------------
 bloom.hh           |  4 +--
 blur-pass.glsl     |  7 ++--
 downsample.glsl    | 18 ++++++++++
 6 files changed, 67 insertions(+), 62 deletions(-)
 create mode 100644 downsample.glsl

diff --git a/Makefile b/Makefile
index bbb0418..e1f7824 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CXXFLAGS += $(shell sdl2-config --cflags) -std=c++14 -Wall
+CXXFLAGS += $(shell sdl2-config --cflags) -std=c++14 -Wall -g
 CFLAGS += $(shell sdl2-config --cflags)
 CPPFLAGS += -I. -Iimgui -Iglm \
 	    -DREAL_BUILD -DGLM_ENABLE_EXPERIMENTAL
diff --git a/bloom-combine.glsl b/bloom-combine.glsl
index c8e5965..dda90fa 100644
--- a/bloom-combine.glsl
+++ b/bloom-combine.glsl
@@ -12,11 +12,13 @@ void main( void )
 	vec2 tmp = gl_FragCoord.xy / u_OutputSize;
 	float f = u_Parameters.x;
 	color = textureLod( u_MainInput , tmp , 0 ).rgb;
+	vec3 bloom = vec3( 0 );
 	for ( int i = 0 ; i < 5 ; i ++ ) {
-		color += f * textureLod( u_BlurInput , tmp , i ).rgb;
-		f *= u_Parameters.y;
+		bloom += f * textureLod( u_BlurInput , tmp , i ).rgb;
+		f = pow( f , u_Parameters.y + 1 );
 	}
+	color = color + bloom / 2.2;
 
 	color = color / ( color + 1. );
-	color = pow( color , vec3( 2.2 ) );
+	color = pow( color , vec3( 1.0 / 2.2 ) );
 }
diff --git a/bloom.cc b/bloom.cc
index 4a19d53..3860d67 100644
--- a/bloom.cc
+++ b/bloom.cc
@@ -12,12 +12,10 @@ T_BloomPass::T_BloomPass(
 		__rw__ T_Texture& input )
 	: input_( input ) ,
 		spHighpass_( GL_FRAGMENT_SHADER , watcher ) ,
+		spDownsample_( GL_FRAGMENT_SHADER , watcher ) ,
 		spBlur_( GL_FRAGMENT_SHADER , watcher ) ,
 		spCombine_( GL_FRAGMENT_SHADER , watcher ) ,
 		//
-		txInput_( width , height , E_TexType::RGB16F ) ,
-		rtInput_( T_RendertargetSetup( ).add( txInput_ , 0 ).create( ) ) ,
-		//
 		txBlur0_( width , height , E_TexType::RGB16F , BloomLevels ) ,
 		txBlur1_( width , height , E_TexType::RGB16F , BloomLevels ) ,
 		//
@@ -27,7 +25,6 @@ T_BloomPass::T_BloomPass(
 		combineStrength_( 0.7 ) ,
 		combineAttenuation_( 0.3 )
 {
-	txInput_.wrap( E_TexWrap::CLAMP_BORDER ).samplingMode( E_TexSampling::LINEAR );
 	txBlur0_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
 	txBlur1_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
 
@@ -37,10 +34,12 @@ T_BloomPass::T_BloomPass(
 	}
 
 	spHighpass_.addFile( "bloom-highpass.glsl" );
+	spDownsample_.addFile( "downsample.glsl" );
 	spBlur_.addFile( "blur-pass.glsl" );
 	spCombine_.addFile( "bloom-combine.glsl" );
 
 	spHighpass_.load( );
+	spDownsample_.load( );
 	spBlur_.load( );
 	spCombine_.load( );
 }
@@ -54,7 +53,7 @@ void T_BloomPass::render( )
 			U_INPUT_SIZE		= 2 ,
 			U_PARAMS		= 3 ,
 		};
-		rtInput_.activate( );
+		rtBlur0_[ 0 ].activate( );
 		T_TextureBinding tb( 0 );
 		tb.set( U_TEXTURE , input_ );
 		tb.bind( );
@@ -65,56 +64,45 @@ void T_BloomPass::render( )
 		glUniform3fv( U_PARAMS , 1 , filterParams_ );
 		glRectf( -1, -1 , 1 , 1 );
 	}
+	assert( glGetError( ) == GL_NO_ERROR );
 
-	if ( spBlur_.activate( ) ) {
-		enum {
-			U_TEXTURE		= 0 ,
-			U_OUTPUT_SIZE		= 1 ,
-			U_INPUT_SIZE		= 2 ,
-			U_SOURCE_LOD		= 3 ,
-			U_DIRECTION		= 4 ,
-			U_WEIGHTS		= 5 ,
-		};
-		glUniform4fv( U_WEIGHTS , 1 , blurWeights_ );
-		for ( int i = 0 ; i < 5 ; i ++ ) {
-			// IB		RMO	B0	B1	B0	B1	B0
-			// OB		B0/0	B1/0	B0/1	B1/1	B0/2	B1/2
-			// SLOD:	0	0	0	1 	1	2
-			// IW:		W	W	W	W/2	W/2	W/4
-			// OW:		W	W	W/2	W/2	W/4	W/4
-			T_TextureBinding tb( 0 );
-			uint32_t w , h;
-			if ( i == 0 ) {
-				tb.set( U_TEXTURE , txInput_ );
-				w = txInput_.width( );
-				h = txInput_.height( );
-			} else {
-				tb.set( U_TEXTURE , txBlur1_ );
-				w = txBlur1_.width( ) >> ( i - 1 );
-				h = txBlur1_.height( ) >> ( i - 1 );
-			}
-
-			const uint32_t slod = i > 0 ? ( i - 1 ) : 0;
+	enum {
+		U_TEXTURE		= 0 ,
+		U_OUTPUT_SIZE		= 1 ,
+		U_SOURCE_LOD		= 2 ,
+		U_DIRECTION		= 3 ,
+		U_WEIGHTS		= 4 ,
+	};
+	for ( auto i = 0u ; i < BloomLevels ; i ++ ) {
+		T_TextureBinding tb( 0 );
+		if ( i > 0 ) {
+			spDownsample_.activate( );
 			rtBlur0_[ i ].activate( );
-			glUniform2f( U_OUTPUT_SIZE , rtBlur0_[ i ].width( ) ,
-					rtBlur0_[ i ].height( ) );
-			glUniform1i( U_SOURCE_LOD , slod );
-			glUniform2f( U_INPUT_SIZE , w , h );
-
-			glUniform2f( U_DIRECTION , blurSize_ , 0 );
+			tb.set( 0 , txBlur0_ );
 			tb.bind( );
-			glRectf( -1 , -1 , 1 , 1 );
-
-			rtBlur1_[ i ].activate( );
-			tb.set( U_TEXTURE , txBlur0_ );
-			tb.bind( );
-			glUniform2f( U_DIRECTION , 0 , blurSize_ );
-			glUniform1i( U_SOURCE_LOD , i );
-			glUniform2f( U_INPUT_SIZE ,
-					rtBlur0_[ i ].width( ) ,
-					rtBlur0_[ i ].height( ) );
+			glUniform2f( 1 , txBlur0_.width( ) >> i ,
+					txBlur0_.height( ) >> i );
+			glUniform1i( 2 , i - 1 );
 			glRectf( -1 , -1 , 1 , 1 );
 		}
+
+		spBlur_.activate( );
+		glUniform4fv( U_WEIGHTS , 1 , blurWeights_ );
+		glUniform2f( U_OUTPUT_SIZE , rtBlur0_[ i ].width( ) ,
+				rtBlur0_[ i ].height( ) );
+		glUniform1i( U_SOURCE_LOD , i );
+
+		rtBlur1_[ i ].activate( );
+		glUniform2f( U_DIRECTION , blurSize_ , 0 );
+		tb.set( U_TEXTURE , txBlur0_ );
+		tb.bind( );
+		glRectf( -1 , -1 , 1 , 1 );
+
+		rtBlur0_[ i ].activate( );
+		glUniform2f( U_DIRECTION , 0 , blurSize_ );
+		tb.set( U_TEXTURE , txBlur1_ );
+		tb.bind( );
+		glRectf( -1 , -1 , 1 , 1 );
 	}
 
 	T_Rendertarget::MainOutput( );
@@ -124,7 +112,7 @@ void T_BloomPass::render( )
 		T_TextureBinding main( 0 ) , blur( 1 );
 		main.set( 0 , input_ );
 		main.bind( );
-		blur.set( 1 , txBlur1_ );
+		blur.set( 1 , txBlur0_ );
 		blur.bind( );
 		glUniform2f( 2 , input_.width( ) , input_.height( ) );
 		glUniform2f( 3 , combineStrength_ , 1 - combineAttenuation_ );
diff --git a/bloom.hh b/bloom.hh
index 45d3ea1..750a9ed 100644
--- a/bloom.hh
+++ b/bloom.hh
@@ -29,12 +29,10 @@ struct T_BloomPass
 	T_Texture& input_;
 
 	T_ShaderProgram spHighpass_;
+	T_ShaderProgram spDownsample_;
 	T_ShaderProgram spBlur_;
 	T_ShaderProgram spCombine_;
 
-	T_Texture txInput_;
-	T_Rendertarget rtInput_;
-
 	T_Texture txBlur0_ , txBlur1_;
 	std::vector< T_Rendertarget > rtBlur0_ , rtBlur1_;
 
diff --git a/blur-pass.glsl b/blur-pass.glsl
index 7b4299d..81f0abe 100644
--- a/blur-pass.glsl
+++ b/blur-pass.glsl
@@ -2,10 +2,9 @@
 
 layout( location = 0 ) uniform sampler2D u_InputTexture;
 layout( location = 1 ) uniform vec2 u_OutputSize;
-layout( location = 2 ) uniform vec2 u_InputSize;
-layout( location = 3 ) uniform int u_SourceLOD;
-layout( location = 4 ) uniform vec2 u_Direction;
-layout( location = 5 ) uniform vec4 u_Weights;
+layout( location = 2 ) uniform int u_SourceLOD;
+layout( location = 3 ) uniform vec2 u_Direction;
+layout( location = 4 ) uniform vec4 u_Weights;
 
 layout( location = 0 ) out vec3 color;
 
diff --git a/downsample.glsl b/downsample.glsl
new file mode 100644
index 0000000..60e0298
--- /dev/null
+++ b/downsample.glsl
@@ -0,0 +1,18 @@
+#version 450 core
+
+layout( location = 0 ) uniform sampler2D u_InputTexture;
+layout( location = 1 ) uniform vec2 u_OutputSize;
+layout( location = 2 ) uniform int u_SourceLOD;
+
+layout( location = 0 ) out vec3 color;
+
+void main( void )
+{
+	const vec2 c = gl_FragCoord.xy;
+	color = ( .25 * (
+			  textureLod( u_InputTexture , ( c + vec2( .5 , .5 ) ) / u_OutputSize , u_SourceLOD )
+			+ textureLod( u_InputTexture , ( c + vec2(-.5 , .5 ) ) / u_OutputSize , u_SourceLOD )
+			+ textureLod( u_InputTexture , ( c + vec2( .5 ,-.5 ) ) / u_OutputSize , u_SourceLOD )
+			+ textureLod( u_InputTexture , ( c + vec2(-.5 ,-.5 ) ) / u_OutputSize , u_SourceLOD )
+		) ).rgb;
+}