#include "externals.hh" #include "dof.hh" #include "profiling.hh" #include "globals.hh" #include "odbg.hh" #include "sync.hh" namespace { static char const* const Name_( "DoF" ); } #define PSTART() Globals::Profiler( ).start( Name_ ) #define PEND() do { glFinish( ); Globals::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( ) ) { txPass1_.wrap( E_TexWrap::CLAMP_EDGE ); Globals::ODbg( ).registerTexture( txPass1_ , E_ODbgMode::HDR , "DoF 1st pass" ); Globals::ODbg( ).registerTexture( txOutput_ , E_ODbgMode::HDR , "DoF output" ); 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 }; using namespace cops; auto& tm( Globals::Textures( ) ); const auto idPass1( spPass1_.program( E_ShaderType::FRAGMENT ) ); const auto idPass2( spPass2_.program( E_ShaderType::FRAGMENT ) ); const auto idSampler( tm.sampler( "linear-edge" )->id( ) ); T_Program program; program.function( "SetDofUniforms" , 1 ) << OPLoadVariable( "height" ) << OPLoadVariable( "width" ) << OPLoadConstant( 0 ) << OPLoadConstant( 0 ) << OPLoadVariable( "time" ) << OPLoadVariable( "height" ) << OPLoadVariable( "width" ) << OPLoadConstant( U_RES_TIME ) << OPDup( 8 ) << OPLoadInput( "dof-samples" ) << OPLoadConstant( U_SAMPLES ) << OPDup( 11 ) << OPLoadInput( "dof-max-blur" ) << OPLoadInput( "dof-falloff" ) << OPLoadInput( "dof-sharp-range" ) << OPLoadInput( "dof-sharp-distance" ) << OPLoadConstant( U_PARAMS ) << OPDup( 17 ) << OPLoadConstant( 1 ) << OPLoadConstant( U_DEPTH ) << OPDup( 20 ) << OPLoadConstant( 0 ) << OPLoadConstant( U_INPUT ) << OPDup( 23 ) << OPSetUniform( 1 , true ) << OPSetUniform( 1 , true ) << OPSetUniform( 4 , false ) << OPSetUniform( 1 , false ) << OPSetUniform( 3 , false ) << OPSetViewport( ) ; program.main // First pass << OPLoadConstant( idPass1 ) << OPCall( "SetDofUniforms" ) << OPUseTexture( 0 , imageInput_.id( ) , idSampler ) << OPUseTexture( 1 , depthInput_.id( ) , idSampler ) << OPUsePipeline( spPass1_.id( ) ) << OPUseFramebuffer( rtPass1_.id( ) ) << OPFullscreen( ) // Second pass << OPLoadConstant( idPass2 ) << OPCall( "SetDofUniforms" ) << OPUseTexture( 0 , txPass1_.id( ) , idSampler ) << OPUsePipeline( spPass2_.id( ) ) << OPUseFramebuffer( rtPass2_.id( ) ) << OPFullscreen( ) ; GL_CHECK( { printf( "GL fail in DoF" ); } ); T_Context ctx; ctx.store( "time" , Globals::Sync( ).time( ) ); ctx.store( "width" , imageInput_.width( ) ); ctx.store( "height" , imageInput_.height( ) ); program.execute( ctx ); PEND( ); } void T_DoFPass::makeUI( ) { #if 0 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 ); #endif }