From 7d16b704b527e3e0b2b1e9f998cca03e6a473cff Mon Sep 17 00:00:00 2001 From: Emmanuel Benoit Date: Sat, 30 Sep 2017 12:08:18 +0200 Subject: [PATCH] Better abstraction for shader programs --- .vim.local/scripts/vimmake.test | 2 +- main.cc | 46 +++++---------------- map.glsl | 4 +- utilities.cc | 71 +++++++++++++++++++++++++++++++++ utilities.hh | 29 ++++++++++++++ 5 files changed, 115 insertions(+), 37 deletions(-) diff --git a/.vim.local/scripts/vimmake.test b/.vim.local/scripts/vimmake.test index 749a225..e41a604 100755 --- a/.vim.local/scripts/vimmake.test +++ b/.vim.local/scripts/vimmake.test @@ -1,4 +1,4 @@ #!/bin/bash if make -j 8; then - ./editor tests/test.json + optirun ./demo fi diff --git a/main.cc b/main.cc index 99ca730..aa148fe 100644 --- a/main.cc +++ b/main.cc @@ -26,23 +26,19 @@ struct T_Main T_Camera camera; T_FilesWatcher watcher; - T_WatchedFiles shaderFiles; - GLuint prog; + std::unique_ptr< T_ShaderProgram > program; void startIteration( ); void handleCapture( ); void makeUI( ); void render( ); - void loadProgram( ); + void initProgram( ); }; /*----------------------------------------------------------------------------*/ T_Main::T_Main( ) - : shaderFiles( watcher , [this] { - this->loadProgram( ); - } ) { SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ); @@ -62,7 +58,7 @@ T_Main::T_Main( ) glewInit(); ImGui_ImplSdl_Init( window ); - loadProgram( ); + initProgram( ); } void T_Main::mainLoop( ) @@ -157,9 +153,7 @@ void T_Main::render( ) // FIXME draw the fuck //project->render( ); - if ( prog != 0 ) { - glUseProgram( prog ); - + if ( program->activate( ) ) { enum { U_TIME = 0 , U_RESOLUTION = 1 , @@ -192,32 +186,14 @@ void T_Main::render( ) } -void T_Main::loadProgram( ) +void T_Main::initProgram( ) { - std::vector< std::string > errors; - - if ( prog != 0 ) { - glDeleteProgram( prog ); - prog = 0; - } - - shaderFiles.clear( ); - shaderFiles.watch( "raymarch-header.glsl" ); - shaderFiles.watch( "map.glsl" ); - shaderFiles.watch( "raymarcher.glsl" ); - - T_ShaderCode shader( 3 ); - shader.loadPart( 0 , "raymarch-header.glsl" , errors ); - shader.loadPart( 1 , "map.glsl" , errors ); - shader.loadPart( 2 , "raymarcher.glsl" , errors ); - - prog = shader.createProgram( GL_FRAGMENT_SHADER , errors ); - - if ( errors.size( ) != 0 ) { - for ( auto const& str : errors ) { - printf( "ERR: %s\n" , str.c_str( ) ); - } - } + program = std::make_unique< T_ShaderProgram >( + GL_FRAGMENT_SHADER , watcher ); + program->addFile( "raymarch-header.glsl" ); + program->addFile( "map.glsl" ); + program->addFile( "raymarcher.glsl" ); + program->load( ); } diff --git a/map.glsl b/map.glsl index a62fc36..3aec80b 100644 --- a/map.glsl +++ b/map.glsl @@ -1,4 +1,6 @@ vec2 map( vec3 pos ) { - return vec2( length( pos ) - 1. , 0. ); + vec3 q = pos; + q.xy = mod( q.xy + 2. , 4. ) - 2.; + return vec2( length( q ) - 2.1 , 0. ); } diff --git a/utilities.cc b/utilities.cc index 429ebd6..ffd3c23 100644 --- a/utilities.cc +++ b/utilities.cc @@ -297,6 +297,77 @@ GLuint T_ShaderCode::createProgram( } +/*= T_ShaderProgram ==========================================================*/ + +T_ShaderProgram::T_ShaderProgram( + __rd__ const GLenum programType , + __rw__ T_FilesWatcher& watcher ) + : files_( watcher , [this] { load( ); } ) , + programType_( programType ) , program_( 0 ) +{ +} + +T_ShaderProgram::~T_ShaderProgram( ) +{ + if ( program_ != 0 ) { + glDeleteProgram( program_ ); + } +} + +void T_ShaderProgram::addChunk( + __rd__ std::string const& string ) +{ + chunksOrFiles_.push_back( true ); + parts_.push_back( string ); +} + +void T_ShaderProgram::addFile( + __rd__ std::string const& source ) +{ + chunksOrFiles_.push_back( false ); + parts_.push_back( source ); +} + +void T_ShaderProgram::load( ) +{ + const auto n( parts_.size( ) ); + errors_.clear( ); + files_.clear( ); + if ( program_ != 0 ) { + glDeleteProgram( program_ ); + program_ = 0; + } + + T_ShaderCode sc( n ); + for ( auto i = 0u ; i < n ; i ++ ) { + if ( chunksOrFiles_[ i ] ) { + sc.setPart( i , parts_[ i ].c_str( ) ); + } else if ( sc.loadPart( i , parts_[ i ].c_str( ) , errors_ ) ) { + files_.watch( parts_[ i ] ); + } + } + + if ( errors_.size( ) == 0 ) { + program_ = sc.createProgram( programType_ , errors_ ); + } + + if ( errors_.size( ) ) { + printf( "\n--------------------------------------------------------------------------------\n\n" ); + for ( auto const& str : errors_ ) { + printf( "ERR: %s\n" , str.c_str( ) ); + } + } +} + +bool T_ShaderProgram::activate( ) const +{ + if ( program_ != 0 ) { + glUseProgram( program_ ); + } + return program_ != 0; +} + + /*= T_Camera =================================================================*/ void T_Camera::handleDND( diff --git a/utilities.hh b/utilities.hh index b1d8f7e..89523a6 100644 --- a/utilities.hh +++ b/utilities.hh @@ -126,6 +126,35 @@ struct T_ShaderCode std::vector< char* > code; }; +struct T_ShaderProgram +{ + T_ShaderProgram( ) = delete; + T_ShaderProgram( T_ShaderProgram const& ) = delete; + T_ShaderProgram( T_ShaderProgram&& ) = delete; + + T_ShaderProgram( + __rd__ GLenum programType , + __rw__ T_FilesWatcher& watcher ); + ~T_ShaderProgram( ); + + void addChunk( __rd__ std::string const& string ); + void addFile( __rd__ std::string const& source ); + + void load( ); + bool activate( ) const; + + private: + T_WatchedFiles files_; + + std::vector< bool > chunksOrFiles_; + std::vector< std::string > parts_; + + std::vector< std::string > errors_; + + GLenum programType_; + GLuint program_; +}; + /*= T_Camera =================================================================*/