#include "externals.hh" #include "dof.hh" #include "profiling.hh" #include "globals.hh" namespace { static const std::string Name_( "DoF" ); } #define PSTART() T_Profiler::Profiler.start( Name_ ) #define PEND() do { glFinish( ); T_Profiler::Profiler.end( Name_ ); } while ( 0 ) T_DoFPass::T_DoFPass( __rw__ T_Texture& imageInput , __rw__ T_Texture& depthInput ) : imageInput_( imageInput ) , depthInput_( depthInput ) , txPass1_( imageInput.width( ) , imageInput.height( ) , E_TexType::RGB16F ) , txOutput_( imageInput.width( ) , imageInput.height( ) , E_TexType::RGB16F ) , rtPass1_( T_RendertargetSetup( ).add( txPass1_ ).create( ) ) , rtPass2_( T_RendertargetSetup( ).add( txOutput_ ).create( ) ) , filterParams_{ 15 , 25 , 100 , 16 } , nSamples_( 16 ) { txPass1_.wrap( E_TexWrap::CLAMP_EDGE ); spPass1_ = Globals::Shaders( ).pipeline({ "fullscreen.v.glsl" , "dof-pass1.f.glsl" }); spPass2_ = Globals::Shaders( ).pipeline({ "fullscreen.v.glsl" , "dof-pass2.f.glsl" }); } void T_DoFPass::render( ) { PSTART( ); enum { U_INPUT = 0 , U_DEPTH = 1 , U_PARAMS = 2 , U_SAMPLES = 3 , U_RES_TIME = 4 }; auto& tm( Globals::Textures( ) ); rtPass1_.activate( ); if ( spPass1_.valid( ) ) { const auto id( spPass1_.program( E_ShaderType::FRAGMENT ) ); spPass1_.enable( ); glProgramUniform1i( id , U_INPUT , 0 ); glProgramUniform1i( id , U_DEPTH , 1 ); glProgramUniform4fv( id , U_PARAMS , 1 , filterParams_ ); glProgramUniform1f( id , U_SAMPLES , nSamples_ ); glProgramUniform3f( id , U_RES_TIME , imageInput_.width( ) , imageInput_.height( ) , 0 ); tm.bind( 0 , imageInput_ , *tm.sampler( "linear-edge" ) ); tm.bind( 1 , depthInput_ , *tm.sampler( "linear-edge" ) ); glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 ); } rtPass2_.activate( ); if ( spPass2_.valid( ) ) { const auto id( spPass2_.program( E_ShaderType::FRAGMENT ) ); spPass2_.enable( ); glProgramUniform1i( id , U_INPUT , 0 ); glProgramUniform1i( id , U_DEPTH , 1 ); glProgramUniform4fv( id , U_PARAMS , 1 , filterParams_ ); glProgramUniform1f( id , U_SAMPLES , nSamples_ ); glProgramUniform3f( id , U_RES_TIME , imageInput_.width( ) , imageInput_.height( ) , 0 ); tm.bind( 0 , txPass1_ , *tm.sampler( "linear-edge" ) ); glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 ); } PEND( ); } void T_DoFPass::makeUI( ) { if ( !ImGui::CollapsingHeader( "Depth of field" ) ) { return; } ImGui::DragFloat( "Sharp distance" , filterParams_ , .25 , 0.25 , 1000 ); ImGui::DragFloat( "Sharp range" , &filterParams_[ 1 ] , .1 , 0.1 , 100 ); ImGui::DragFloat( "Blur falloff" , &filterParams_[ 2 ] , .5 , 0.5 , 1000 ); ImGui::DragFloat( "Max blur" , &filterParams_[ 3 ] , .1 , .1 , 100 ); ImGui::DragInt( "Samples" , &nSamples_ , .2 , 1 , 32 ); }