#include "externals.hh" #include "utilities.hh" #include "texture.hh" #include "rendertarget.hh" #include "bloom.hh" T_BloomPass::T_BloomPass( __rd__ const uint32_t width , __rd__ const uint32_t height , __rw__ T_FilesWatcher& watcher , __rw__ T_Texture& input ) : input_( input ) , spHighpass_( 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 ) , // filterParams_{ 1.6 , 1.2 , .95 } , blurWeights_{ 0.324 , 0.232 , 0.0855 , 0.0205 } , blurSize_{ 2. } , 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 ); for ( int i = 0 ; i < 5 ; i ++ ) { rtBlur0_.push_back( T_RendertargetSetup( ).add( txBlur0_ , i ).create( ) ); rtBlur1_.push_back( T_RendertargetSetup( ).add( txBlur1_ , i ).create( ) ); } spHighpass_.addFile( "bloom-highpass.glsl" ); spBlur_.addFile( "blur-pass.glsl" ); spCombine_.addFile( "bloom-combine.glsl" ); spHighpass_.load( ); spBlur_.load( ); spCombine_.load( ); } void T_BloomPass::render( ) { if ( spHighpass_.activate( ) ) { enum { U_TEXTURE = 0 , U_LOD = 1 , U_INPUT_SIZE = 2 , U_PARAMS = 3 , }; rtInput_.activate( ); T_TextureBinding tb( 0 ); tb.set( U_TEXTURE , input_ ); tb.bind( ); glUniform1i( U_LOD , 0 ); glUniform2f( U_INPUT_SIZE , input_.width( ) , input_.height( ) ); glUniform3fv( U_PARAMS , 1 , filterParams_ ); glRectf( -1, -1 , 1 , 1 ); } 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; 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.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( ) ); glRectf( -1 , -1 , 1 , 1 ); } } T_Rendertarget::MainOutput( ); glClearColor( 1 , 0 , 1 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); if ( spCombine_.activate( ) ) { T_TextureBinding main( 0 ) , blur( 1 ); main.set( 0 , input_ ); main.bind( ); blur.set( 1 , txBlur1_ ); blur.bind( ); glUniform2f( 2 , input_.width( ) , input_.height( ) ); glUniform2f( 3 , combineStrength_ , 1 - combineAttenuation_ ); glRectf( -1, -1 , 1 , 1 ); glBindTexture( GL_TEXTURE_2D , 0 ); } } void T_BloomPass::makeUI( ) { if ( !ImGui::CollapsingHeader( "Bloom" ) ) { return; } ImGui::DragFloat3( "Filter" , filterParams_ , .01f , 0.1 , 10 ); ImGui::DragFloat4( "Weights" , blurWeights_ , .001f , 0. , 10 ); ImGui::DragFloat( "Blur size" , &blurSize_ , .001f , 0. , 10 ); ImGui::DragFloat( "Initial strength" , &combineStrength_ , .001f , 0. , 10 ); ImGui::DragFloat( "Attenuation" , &combineAttenuation_ , .001f , 0. , 1 ); }