demotool/ui-rendertarget.cc

196 lines
4.5 KiB
C++
Raw Permalink Normal View History

2017-09-30 14:59:15 +02:00
#include "externals.hh"
#include "ui-rendertarget.hh"
#include "ui-texture.hh"
2017-09-30 14:59:15 +02:00
T_RendertargetSetup::T_RendertargetSetup( )
: hasAttachments_( false )
{ }
T_RendertargetSetup& T_RendertargetSetup::add(
T_Texture& texture ,
const uint32_t level )
2017-09-30 14:59:15 +02:00
{
checkAttachment( texture , level );
2017-11-01 23:45:09 +01:00
colorAttachments_.add( T_Attachment_{ texture , level } );
2017-09-30 14:59:15 +02:00
return *this;
}
T_RendertargetSetup& T_RendertargetSetup::depth(
T_Texture& texture )
2017-09-30 14:59:15 +02:00
{
2017-11-08 09:09:21 +01:00
assert( !depthAttachment_ );
2017-09-30 14:59:15 +02:00
checkAttachment( texture , 0 );
2017-11-01 23:45:09 +01:00
depthAttachment_.setNew( texture , 0 );
2017-09-30 14:59:15 +02:00
return *this;
}
void T_RendertargetSetup::checkAttachment(
T_Texture const& texture ,
const uint32_t level )
2017-09-30 14:59:15 +02:00
{
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 ++ ) {
2017-10-01 15:00:59 +02:00
#ifdef INTRUSIVE_TRACES
2017-10-01 18:51:02 +02:00
printf( "init %p fb %d att %d tx %p level %d\n" ,
this , id , i ,
colorAttachments_[ i ].texture ,
colorAttachments_[ i ].level );
2017-10-01 15:00:59 +02:00
#endif
2017-09-30 14:59:15 +02:00
glFramebufferTexture( GL_FRAMEBUFFER ,
GL_COLOR_ATTACHMENT0 + i ,
colorAttachments_[ i ].texture->id( ) ,
colorAttachments_[ i ].level );
}
2017-11-08 09:09:21 +01:00
if ( depthAttachment_ ) {
T_Attachment_ const& de( *depthAttachment_ );
2017-09-30 14:59:15 +02:00
glFramebufferTexture( GL_FRAMEBUFFER ,
GL_DEPTH_ATTACHMENT ,
2017-11-01 23:45:09 +01:00
de.texture->id( ) ,
de.level );
2017-09-30 14:59:15 +02:00
}
assert( glCheckFramebufferStatus( GL_FRAMEBUFFER ) == GL_FRAMEBUFFER_COMPLETE );
glBindFramebuffer( GL_FRAMEBUFFER , 0 );
assert( glGetError( ) == GL_NO_ERROR );
// Reset config
hasAttachments_ = false;
colorAttachments_.clear( );
2017-11-01 23:45:09 +01:00
depthAttachment_.clear( );
2017-09-30 14:59:15 +02:00
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;
}
}
2017-09-30 14:59:15 +02:00
T_Rendertarget::T_Rendertarget(
const uint32_t id ,
const uint32_t nCats ,
const uint32_t width ,
const uint32_t height )
2017-09-30 14:59:15 +02:00
: id_( id ) , nCats_( nCats ) , width_( width ) , height_( height )
{ }
T_Rendertarget::T_Rendertarget(
T_Rendertarget&& other ) noexcept
2017-09-30 14:59:15 +02:00
: id_( 0 ) , nCats_( other.nCats_ ) , width_( other.width_ ) ,
height_( other.height_ )
{
2017-11-03 09:08:19 +01:00
swap( id_ , other.id_ );
2017-09-30 14:59:15 +02:00
}
T_Rendertarget& T_Rendertarget::operator =(
T_Rendertarget&& other ) noexcept
2017-09-30 14:59:15 +02:00
{
2017-11-03 09:08:19 +01:00
swap( id_ , other.id_ );
swap( nCats_ , other.nCats_ );
swap( width_ , other.width_ );
swap( height_ , other.height_ );
2017-09-30 14:59:15 +02:00
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 ++ ) {
2017-11-01 23:45:09 +01:00
buffers_.add( GL_COLOR_ATTACHMENT0 + i );
2017-09-30 14:59:15 +02:00
}
2017-10-01 18:51:02 +02:00
#ifdef INTRUSIVE_TRACES
printf( "fb %d: created buffers (%d items)\n" , id_ ,
int( buffers_.size( ) ) );
#endif
2017-09-30 14:59:15 +02:00
}
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 ] );
}
2017-09-30 14:59:15 +02:00
void T_Rendertarget::MainOutput( )
{
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
glBindFramebuffer( GL_FRAMEBUFFER , 0 );
glViewport( 0 , 0 , (int) dspSize.x, (int) dspSize.y );
}