From 7e223ff2f4b3ccefea9da4183bb4f05e232f9241 Mon Sep 17 00:00:00 2001 From: Emmanuel Benoit Date: Sat, 30 Sep 2017 14:59:15 +0200 Subject: [PATCH] Render-fucking-targets, motherfuckers! --- Makefile | 3 +- copy.glsl | 13 +++++ main.cc | 48 +++++++++++----- rendertarget.cc | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ rendertarget.hh | 69 +++++++++++++++++++++++ 5 files changed, 264 insertions(+), 15 deletions(-) create mode 100644 copy.glsl create mode 100644 rendertarget.cc create mode 100644 rendertarget.hh diff --git a/Makefile b/Makefile index ab8dc4c..a654009 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,8 @@ DEMO = \ main.o \ imgui_impl_sdl.o \ utilities.o \ - texture.o + texture.o \ + rendertarget.o DEMO_DEPS = $(DEMO:%.o=.%.d) diff --git a/copy.glsl b/copy.glsl new file mode 100644 index 0000000..dcd0402 --- /dev/null +++ b/copy.glsl @@ -0,0 +1,13 @@ +#version 450 core + +layout( location = 0 ) uniform sampler2D u_InputTexture; + +layout( location = 0 ) out vec4 color; + +void main( void ) +{ + vec2 tmp = gl_FragCoord.xy / vec2( 1280. , 720. ); + color = textureLod( u_InputTexture , tmp , 0 ); + //color.xy *= .75 + tmp * .25; +} + diff --git a/main.cc b/main.cc index acfc06c..961c2a2 100644 --- a/main.cc +++ b/main.cc @@ -3,6 +3,7 @@ #include "imgui_impl_sdl.h" #include "utilities.hh" #include "texture.hh" +#include "rendertarget.hh" /*= T_Main ===================================================================*/ @@ -27,7 +28,11 @@ struct T_Main T_Camera camera; T_FilesWatcher watcher; - std::unique_ptr< T_ShaderProgram > program; + std::unique_ptr< T_ShaderProgram > spRaymarch; + std::unique_ptr< T_ShaderProgram > spCopy; + + std::unique_ptr< T_Texture > txRaymarchOutput; + std::unique_ptr< T_Rendertarget > rtRaymarchOutput; void startIteration( ); void handleCapture( ); @@ -60,8 +65,10 @@ T_Main::T_Main( ) ImGui_ImplSdl_Init( window ); initProgram( ); - - //T_Texture textureTest( 512 , 512 , E_TexType::R8 ); + txRaymarchOutput = std::make_unique< T_Texture >( + 1280 , 720 , E_TexType::RGBA8 ); + rtRaymarchOutput = std::make_unique < T_Rendertarget >( + T_RendertargetSetup( ).add( *txRaymarchOutput ).create( ) ); } void T_Main::mainLoop( ) @@ -158,12 +165,9 @@ void T_Main::makeUI( ) void T_Main::render( ) { - auto const& dspSize( ImGui::GetIO( ).DisplaySize ); - glViewport( 0 , 0 , (int) dspSize.x, (int) dspSize.y ); - glClearColor( 1 , 0 , 1 , 1 ); - glClear( GL_COLOR_BUFFER_BIT ); - - if ( program->activate( ) ) { + if ( spRaymarch->activate( ) && rtRaymarchOutput->activate( ) ) { + glClearColor( 0 , 1 , 1 , 1 ); + glClear( GL_COLOR_BUFFER_BIT ); enum { U_TIME = 0 , U_RESOLUTION = 1 , @@ -190,6 +194,17 @@ void T_Main::render( ) glRectf( -1, -1 , 1 , 1 ); } + T_Rendertarget::MainOutput( ); + glClearColor( 1 , 0 , 1 , 1 ); + glClear( GL_COLOR_BUFFER_BIT ); + if ( spCopy->activate( ) ) { + T_TextureBinding tb( 0 ); + tb.set( 0 , *txRaymarchOutput ); + tb.bind( ); + glRectf( -1, -1 , 1 , 1 ); + glBindTexture( GL_TEXTURE_2D , 0 ); + } + glUseProgram( 0 ); ImGui::Render( ); SDL_GL_SwapWindow( window ); @@ -198,12 +213,17 @@ void T_Main::render( ) void T_Main::initProgram( ) { - program = std::make_unique< T_ShaderProgram >( + spRaymarch = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER , watcher ); - program->addFile( "raymarch-header.glsl" ); - program->addFile( "map.glsl" ); - program->addFile( "raymarcher.glsl" ); - program->load( ); + spRaymarch->addFile( "raymarch-header.glsl" ); + spRaymarch->addFile( "map.glsl" ); + spRaymarch->addFile( "raymarcher.glsl" ); + spRaymarch->load( ); + + spCopy = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER , + watcher ); + spCopy->addFile( "copy.glsl" ); + spCopy->load( ); } diff --git a/rendertarget.cc b/rendertarget.cc new file mode 100644 index 0000000..5d944cb --- /dev/null +++ b/rendertarget.cc @@ -0,0 +1,146 @@ +#include "externals.hh" +#include "texture.hh" +#include "rendertarget.hh" + + +T_RendertargetSetup::T_RendertargetSetup( ) + : hasAttachments_( false ) +{ } + +T_RendertargetSetup& T_RendertargetSetup::add( + __rw__ T_Texture& texture , + __rd__ const uint32_t level ) +{ + checkAttachment( texture , level ); + colorAttachments_.push_back( T_Attachment_{ texture , level } ); + return *this; +} + + +T_RendertargetSetup& T_RendertargetSetup::depth( + __rw__ T_Texture& texture ) +{ + assert( !depthAttachment_ ); + checkAttachment( texture , 0 ); + depthAttachment_ = std::make_unique< T_Attachment_ >( texture , 0 ); + return *this; +} + + +void T_RendertargetSetup::checkAttachment( + __rw__ T_Texture const& texture , + __rd__ 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 ++ ) { + glFramebufferTexture( GL_FRAMEBUFFER , + GL_COLOR_ATTACHMENT0 + i , + colorAttachments_[ i ].texture->id( ) , + colorAttachments_[ i ].level ); + } + if ( depthAttachment_ ) { + glFramebufferTexture( GL_FRAMEBUFFER , + GL_DEPTH_ATTACHMENT , + depthAttachment_->texture->id( ) , + depthAttachment_->level ); + } + assert( glCheckFramebufferStatus( GL_FRAMEBUFFER ) == GL_FRAMEBUFFER_COMPLETE ); + glBindFramebuffer( GL_FRAMEBUFFER , 0 ); + + assert( glGetError( ) == GL_NO_ERROR ); + + // Reset config + hasAttachments_ = false; + colorAttachments_.clear( ); + depthAttachment_.reset( ); + + return T_Rendertarget( id , nca , width_ , height_ ); +} + +/*============================================================================*/ + +T_Rendertarget::T_Rendertarget( + __rd__ const uint32_t id , + __rd__ const uint32_t nCats , + __rd__ const uint32_t width , + __rd__ const uint32_t height ) + : id_( id ) , nCats_( nCats ) , width_( width ) , height_( height ) +{ } + +T_Rendertarget::T_Rendertarget( + __rw__ T_Rendertarget&& other ) noexcept + : id_( 0 ) , nCats_( other.nCats_ ) , width_( other.width_ ) , + height_( other.height_ ) +{ + std::swap( id_ , other.id_ ); +} + +T_Rendertarget& T_Rendertarget::operator =( + __rw__ T_Rendertarget&& other ) noexcept +{ + std::swap( id_ , other.id_ ); + std::swap( nCats_ , other.nCats_ ); + std::swap( width_ , other.width_ ); + std::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_.push_back( GL_COLOR_ATTACHMENT0 + i ); + } + } + 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::MainOutput( ) +{ + auto const& dspSize( ImGui::GetIO( ).DisplaySize ); + glBindFramebuffer( GL_FRAMEBUFFER , 0 ); + glViewport( 0 , 0 , (int) dspSize.x, (int) dspSize.y ); +} diff --git a/rendertarget.hh b/rendertarget.hh new file mode 100644 index 0000000..e83ca2f --- /dev/null +++ b/rendertarget.hh @@ -0,0 +1,69 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +# include "texture.hh" +#endif + +struct T_Rendertarget; + +struct T_RendertargetSetup +{ + T_RendertargetSetup( ); + + T_RendertargetSetup& add( + __rw__ T_Texture& texture , + __rd__ const uint32_t level = 0 ); + T_RendertargetSetup& depth( + __rw__ T_Texture& texture ); + + T_Rendertarget create( ); + + private: + struct T_Attachment_ { + T_Texture* texture; + uint32_t level; + + T_Attachment_( + __rw__ T_Texture& texture , + __rd__ const uint32_t level ) + : texture( &texture ) , level( level ) + {} + }; + + void checkAttachment( + __rw__ T_Texture const& texture , + __rd__ const uint32_t level ); + + bool hasAttachments_; + uint32_t width_ , height_; + std::vector< T_Attachment_ > colorAttachments_; + std::unique_ptr< T_Attachment_ > depthAttachment_; +}; + + +struct T_Rendertarget +{ + T_Rendertarget( ) = delete; + T_Rendertarget( T_Rendertarget const& ) = delete; + + T_Rendertarget( + __rd__ const GLuint id , + __rd__ const uint32_t nCats , + __rd__ const uint32_t width , + __rd__ const uint32_t height ); + + T_Rendertarget( __rw__ T_Rendertarget&& other ) noexcept; + T_Rendertarget& operator =( + __rw__ T_Rendertarget&& ) noexcept; + + ~T_Rendertarget( ); + + bool activate( ); + + static void MainOutput( ); + + private: + GLuint id_; + uint32_t nCats_ , width_ , height_; + std::vector< GLenum > buffers_; +};