125 lines
3.4 KiB
C++
125 lines
3.4 KiB
C++
#include "externals.hh"
|
|
#include "bloom.hh"
|
|
#include "profiling.hh"
|
|
#include "globals.hh"
|
|
|
|
namespace {
|
|
static const std::string Name_( "BLOOOOM!" );
|
|
}
|
|
|
|
#define PSTART() Globals::Profiler( ).start( Name_ )
|
|
#define PEND() do { glFinish( ); Globals::Profiler( ).end( Name_ ); } while ( 0 )
|
|
|
|
|
|
T_BloomPass::T_BloomPass(
|
|
__rw__ T_Texture& input )
|
|
: input_( input ) ,
|
|
//
|
|
txBlur0_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
|
txBlur1_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
|
//
|
|
filterParams_{ 1.6 , 1.2 , .95 } ,
|
|
blurWeights_{ 0.324 , 0.232 , 0.0855 , 0.0205 } ,
|
|
blurSize_{ 1.3 }
|
|
{
|
|
txBlur0_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
|
|
txBlur1_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
|
|
|
|
for ( auto i = 0u ; i < BloomLevels ; i ++ ) {
|
|
rtBlur0_.push_back( T_RendertargetSetup( ).add( txBlur0_ , i ).create( ) );
|
|
rtBlur1_.push_back( T_RendertargetSetup( ).add( txBlur1_ , i ).create( ) );
|
|
}
|
|
|
|
auto& sm( Globals::Shaders( ) );
|
|
spHighpass_ = sm.pipeline({ "fullscreen.v.glsl" , "bloom-highpass.f.glsl" });
|
|
spDownsample_ = sm.pipeline({ "fullscreen.v.glsl" , "downsample.f.glsl" });
|
|
spBlur_ = sm.pipeline({ "fullscreen.v.glsl" , "blur-pass.f.glsl" });
|
|
}
|
|
|
|
void T_BloomPass::render( )
|
|
{
|
|
if ( !( spHighpass_.valid( ) && spBlur_.valid( ) && spDownsample_.valid( ) ) ) {
|
|
return;
|
|
}
|
|
|
|
PSTART( );
|
|
auto& tm( Globals::Textures( ) );
|
|
{
|
|
rtBlur0_[ 0 ].activate( );
|
|
const auto hpf( spHighpass_.program( E_ShaderType::FRAGMENT ) );
|
|
enum {
|
|
U_TEXTURE = 0 ,
|
|
U_LOD = 1 ,
|
|
U_INPUT_SIZE = 2 ,
|
|
U_PARAMS = 3 ,
|
|
};
|
|
|
|
tm.bind( 0 , input_ );
|
|
spHighpass_.enable( );
|
|
|
|
glProgramUniform1i( hpf , U_TEXTURE , 0 );
|
|
glProgramUniform1i( hpf , U_LOD , 0 );
|
|
glProgramUniform2f( hpf , U_INPUT_SIZE ,
|
|
input_.width( ) ,
|
|
input_.height( ) );
|
|
glProgramUniform3fv( hpf , U_PARAMS , 1 , filterParams_ );
|
|
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
|
|
}
|
|
|
|
enum {
|
|
U_TEXTURE = 0 ,
|
|
U_OUTPUT_SIZE = 1 ,
|
|
U_SOURCE_LOD = 2 ,
|
|
U_DIRECTION = 3 ,
|
|
U_WEIGHTS = 4 ,
|
|
};
|
|
|
|
const auto dsf( spDownsample_.program( E_ShaderType::FRAGMENT ) );
|
|
const auto bpf( spBlur_.program( E_ShaderType::FRAGMENT ) );
|
|
glProgramUniform1i( dsf , 0 , 0 );
|
|
glProgramUniform4fv( bpf , U_WEIGHTS , 1 , blurWeights_ );
|
|
glProgramUniform1i( bpf , U_TEXTURE , 0 );
|
|
|
|
for ( auto i = 0u ; i < BloomLevels ; i ++ ) {
|
|
if ( i > 0 ) {
|
|
spDownsample_.enable( );
|
|
rtBlur0_[ i ].activate( );
|
|
|
|
tm.bind( 0 , txBlur0_ );
|
|
|
|
glProgramUniform2f( dsf , 1 , txBlur0_.width( ) >> i ,
|
|
txBlur0_.height( ) >> i );
|
|
glProgramUniform1i( dsf , 2 , i - 1 );
|
|
|
|
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
|
|
}
|
|
|
|
spBlur_.enable( );
|
|
glProgramUniform2f( bpf , U_OUTPUT_SIZE , rtBlur0_[ i ].width( ) ,
|
|
rtBlur0_[ i ].height( ) );
|
|
glProgramUniform1i( bpf , U_SOURCE_LOD , i );
|
|
|
|
rtBlur1_[ i ].activate( );
|
|
glProgramUniform2f( bpf , U_DIRECTION , blurSize_ , 0 );
|
|
tm.bind( 0 , txBlur0_ );
|
|
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
|
|
|
|
rtBlur0_[ i ].activate( );
|
|
glProgramUniform2f( bpf , U_DIRECTION , 0 , blurSize_ );
|
|
tm.bind( 0 , txBlur1_ );
|
|
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
|
|
}
|
|
|
|
PEND( );
|
|
}
|
|
|
|
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 );
|
|
}
|