#include "externals.hh" #include "ui-rendertarget.hh" #include "ui-texture.hh" T_RendertargetSetup::T_RendertargetSetup( ) : hasAttachments_( false ) { } T_RendertargetSetup& T_RendertargetSetup::add( T_Texture& texture , const uint32_t level ) { checkAttachment( texture , level ); colorAttachments_.add( T_Attachment_{ texture , level } ); return *this; } T_RendertargetSetup& T_RendertargetSetup::depth( T_Texture& texture ) { assert( !depthAttachment_ ); checkAttachment( texture , 0 ); depthAttachment_.setNew( texture , 0 ); return *this; } void T_RendertargetSetup::checkAttachment( T_Texture const& texture , const uint32_t level ) { const uint32_t tw( texture.width( ) >> level ) , th( texture.height( ) >> level ); if ( hasAttachments_ ) { assert( tw == width_ ); assert( th == height_ ); } else { width_ = tw; height_ = th; hasAttachments_ = true; } } T_Rendertarget T_RendertargetSetup::create( ) { const auto nca( colorAttachments_.size( ) ); assert( hasAttachments_ ); assert( nca != 0 ); // Generate / setup the GL framebuffer GLuint id( 0 ); glGenFramebuffers( 1 , &id ); glBindFramebuffer( GL_FRAMEBUFFER , id ); for ( auto i = 0u ; i < nca ; i ++ ) { #ifdef INTRUSIVE_TRACES printf( "init %p fb %d att %d tx %p level %d\n" , this , id , i , colorAttachments_[ i ].texture , colorAttachments_[ i ].level ); #endif glFramebufferTexture( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 + i , colorAttachments_[ i ].texture->id( ) , colorAttachments_[ i ].level ); } if ( depthAttachment_ ) { T_Attachment_ const& de( *depthAttachment_ ); glFramebufferTexture( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , de.texture->id( ) , de.level ); } assert( glCheckFramebufferStatus( GL_FRAMEBUFFER ) == GL_FRAMEBUFFER_COMPLETE ); glBindFramebuffer( GL_FRAMEBUFFER , 0 ); assert( glGetError( ) == GL_NO_ERROR ); // Reset config hasAttachments_ = false; colorAttachments_.clear( ); depthAttachment_.clear( ); return T_Rendertarget( id , nca , width_ , height_ ); } /*============================================================================*/ T_Rendertarget::T_Rendertarget( ) { glGenFramebuffers( 1 , &id_ ); nCats_ = width_ = height_ = 0; } void T_Rendertarget::attach( T_Texture const& texture , const uint32_t lod , const uint32_t id ) { const uint32_t attId( id ? ( GL_COLOR_ATTACHMENT0 + id - 1 ) : GL_DEPTH_ATTACHMENT ); glFramebufferTexture( GL_FRAMEBUFFER , attId , texture.id( ) , lod ); if ( width_ == 0 ) { width_ = texture.width( ) >> lod; height_ = texture.width( ) >> lod; } } T_Rendertarget::T_Rendertarget( const uint32_t id , const uint32_t nCats , const uint32_t width , const uint32_t height ) : id_( id ) , nCats_( nCats ) , width_( width ) , height_( height ) { } T_Rendertarget::T_Rendertarget( T_Rendertarget&& other ) noexcept : id_( 0 ) , nCats_( other.nCats_ ) , width_( other.width_ ) , height_( other.height_ ) { swap( id_ , other.id_ ); } T_Rendertarget& T_Rendertarget::operator =( T_Rendertarget&& other ) noexcept { swap( id_ , other.id_ ); swap( nCats_ , other.nCats_ ); swap( width_ , other.width_ ); swap( height_ , other.height_ ); return *this; } T_Rendertarget::~T_Rendertarget( ) { if ( id_ != 0 ) { glDeleteFramebuffers( 1 , &id_ ); } } bool T_Rendertarget::activate( ) { if ( id_ != 0 ) { #ifdef INTRUSIVE_TRACES printf( "ACTIVATING FB %d (%dx%d, %d c.a.)\n" , id_ , width_ , height_ , nCats_ ); #endif if ( nCats_ != buffers_.size( ) ) { buffers_.clear( ); for ( auto i = 0u ; i < nCats_ ; i ++ ) { buffers_.add( GL_COLOR_ATTACHMENT0 + i ); } #ifdef INTRUSIVE_TRACES printf( "fb %d: created buffers (%d items)\n" , id_ , int( buffers_.size( ) ) ); #endif } glBindFramebuffer( GL_FRAMEBUFFER , id_ ); glViewport( 0 , 0 , width_ , height_ ); glDrawBuffers( nCats_ , &buffers_[ 0 ] ); assert( glCheckFramebufferStatus( GL_FRAMEBUFFER ) == GL_FRAMEBUFFER_COMPLETE ); assert( glGetError( ) == GL_NO_ERROR ); } return id_ != 0; } void T_Rendertarget::toggle( const uint32_t id , const bool active ) { const auto realId( GL_COLOR_ATTACHMENT0 + id ); const int32_t idx( buffers_.indexOf( realId ) ); if ( active && idx < 0 ) { buffers_.add( realId ); } else if ( !active && idx >= 0 ) { buffers_.removeSwap( idx ); } else { return; } glDrawBuffers( buffers_.size( ) , &buffers_[ 0 ] ); } void T_Rendertarget::MainOutput( ) { auto const& dspSize( ImGui::GetIO( ).DisplaySize ); glBindFramebuffer( GL_FRAMEBUFFER , 0 ); glViewport( 0 , 0 , (int) dspSize.x, (int) dspSize.y ); }