diff --git a/main.cc b/main.cc index 4fcd696..2f7788e 100644 --- a/main.cc +++ b/main.cc @@ -60,6 +60,9 @@ void T_Main::mainLoop( ) initDemo( ); } + Globals::Watcher( ).check( ); + Globals::Shaders( ).update( ); + glFinish( ); p.startFrame( ); p.start( "Full frame" ); @@ -70,7 +73,6 @@ void T_Main::mainLoop( ) render( ); p.end( "Full frame" ); Globals::Window( ).swap( ); - Globals::Watcher( ).check( ); p.endFrame( ); } } diff --git a/raymarcher.cc b/raymarcher.cc index ef86630..7740e4a 100644 --- a/raymarcher.cc +++ b/raymarcher.cc @@ -1,6 +1,7 @@ #include "externals.hh" #include "raymarcher.hh" #include "profiling.hh" +#include "globals.hh" namespace { @@ -14,7 +15,7 @@ namespace { T_Raymarcher::T_Raymarcher( __rd__ const uint32_t width , __rd__ const uint32_t height ) - : camera_( ) , program_( GL_FRAGMENT_SHADER ) , + : camera_( ) , txOutput_( width , height , E_TexType::RGB16F ) , txDepth_( width , height , E_TexType::R16F ) , rtOutput_( T_RendertargetSetup( ) @@ -22,39 +23,22 @@ T_Raymarcher::T_Raymarcher( .add( txDepth_ ) .create( ) ) { -#if 0 - glGenProgramPipelines( 1 , &pipeline_ ); -#endif - - program_.addFile( "raymarch-header.glsl" ); - program_.addFile( "pbr.glsl" ); - program_.addFile( "blinn-phong.glsl" ); - program_.addFile( "map.glsl" ); - program_.addFile( "raymarcher.glsl" ); - program_.load( ); - -#if 0 - auto& fsq( T_ShaderProgram::FullscreenQuad( watcher ) ); - glUseProgramStages( pipeline_ , GL_VERTEX_SHADER_BIT , fsq.id( ) ); - glUseProgramStages( pipeline_ , GL_FRAGMENT_SHADER_BIT , program_.id( ) ); - assert( glGetError( ) == GL_NO_ERROR ); -#endif + program_ = Globals::Shaders( ).pipeline({ + "fullscreen.v.glsl" , "scene.f.glsl" }); } void T_Raymarcher::render( ) { PSTART( ); - if ( ! rtOutput_.activate( ) ) { + if ( !rtOutput_.activate( ) || !program_.valid( ) ) { + glClearColor( 0 , 0 , 0 , 1 ); + glClear( GL_COLOR_BUFFER_BIT ); PEND( ); return; } + program_.enable( ); -#if 0 - glBindProgramPipeline( pipeline_ ); -#else - program_.activate( ); -#endif glClearColor( 0 , 0 , 0 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); enum { @@ -68,18 +52,19 @@ void T_Raymarcher::render( ) U_RAYMARCHER = 7 , }; -#if 0 - glProgramUniform1f( program_.id( ) , U_TIME , 0 ); - glProgramUniform2f( program_.id( ) , U_RESOLUTION , rtOutput_.width( ) , rtOutput_.height( ) ); +#if 1 + const auto id( program_.program( E_ShaderType::FRAGMENT ) ); + glProgramUniform1f( id , U_TIME , 0 ); + glProgramUniform2f( id , U_RESOLUTION , rtOutput_.width( ) , rtOutput_.height( ) ); - glProgramUniform3fv( program_.id( ) , U_CAM_POS , 1 , &camera_.pos.x ); - glProgramUniform3fv( program_.id( ) , U_LOOK_AT , 1 , &camera_.lookAt.x ); - glProgramUniform3fv( program_.id( ) , U_CAM_UP , 1 , &camera_.up.x ); - glProgramUniform1f( program_.id( ) , U_NEAR_PLANE , camera_.np ); + glProgramUniform3fv( id , U_CAM_POS , 1 , &camera_.pos.x ); + glProgramUniform3fv( id , U_LOOK_AT , 1 , &camera_.lookAt.x ); + glProgramUniform3fv( id , U_CAM_UP , 1 , &camera_.up.x ); + glProgramUniform1f( id , U_NEAR_PLANE , camera_.np ); - glProgramUniform3f( program_.id( ) , U_LIGHT_DIR , 0 , 1 , -1 ); + glProgramUniform3f( id , U_LIGHT_DIR , 0 , 1 , -1 ); - glProgramUniform4f( program_.id( ) , U_RAYMARCHER , rmIterations , rmStep , + glProgramUniform4f( id , U_RAYMARCHER , rmIterations , rmStep , rmEpsilon , rmMaxDist ); glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 ); diff --git a/raymarcher.hh b/raymarcher.hh index 57b7d3a..3d7958a 100644 --- a/raymarcher.hh +++ b/raymarcher.hh @@ -1,7 +1,7 @@ #pragma once #include "rendertarget.hh" -#include "programs.hh" +#include "shaders.hh" #include "camera.hh" @@ -27,10 +27,8 @@ struct T_Raymarcher private: T_Camera camera_; -#if 0 - GLuint pipeline_; -#endif - T_ShaderProgram program_; + //T_ShaderProgram program_; + T_ShaderPipeline program_; T_Texture txOutput_ , txDepth_; T_Rendertarget rtOutput_; diff --git a/shaders.cc b/shaders.cc index a2ca3c7..a8b13e6 100644 --- a/shaders.cc +++ b/shaders.cc @@ -7,7 +7,7 @@ namespace { const std::regex PreprocDirective_( "^\\s*//!\\s*([a-z]+(\\s+([^\\s]+))*)\\s*$" ); -const std::regex GLSLErrorNv_( "^\\d+\\((\\d+)\\) : " ); +const std::regex GLSLErrorNv_( "^[0-9]*\\(([0-9]+).*$" ); const std::map< std::string , E_ShaderInput > InputTypes_( ([] { std::map< std::string , E_ShaderInput > t; @@ -260,6 +260,28 @@ void T_ShaderPipeline::enable( ) const } } +GLuint T_ShaderPipeline::program( + __rd__ const E_ShaderType program ) const +{ + if ( !valid( ) ) { + return 0; + } + + auto const& sm( Globals::Shaders( ) ); + auto const& pl( sm.pipelines_[ smIndex_ ] ); + for ( auto const& pn : pl.programs ) { + auto pos( sm.programIndex_.find( pn ) ); + if ( pos == sm.programIndex_.end( ) ) { + continue; + } + auto& p( sm.programs_[ pos->second ] ); + if ( p.code.type == program ) { + return p.id; + } + } + return 0; +} + /*= T_CodeBuilder_ ===========================================================*/ @@ -312,6 +334,13 @@ bool T_CodeBuilder_::buildCode( ) if ( !main ) { return false; } + if ( main->type == E_ShaderInput::CHUNK + || main->type == E_ShaderInput::LIBRARY ) { + code.errors.push_back( T_ShaderError{ + name , 0 , "invalid type" } ); + } else { + code.type = E_ShaderType( int( main->type ) - 2 ); + } cname = name; current = main; @@ -392,7 +421,7 @@ void T_CodeBuilder_::include( cname = nname; current = isi; cpos = UINT32_MAX; - pos[ cname ] = 1; + pos[ cname ] = 0; } void T_CodeBuilder_::next( ) @@ -450,6 +479,8 @@ T_ShaderPipeline T_ShaderManager::pipeline( void T_ShaderManager::update( ) { + inputs_.clear( ); + // Check for missing files for ( auto it = missing_.begin( ) ; it != missing_.end( ) ; ++ it ) { const bool exists( ([] ( std::string const& name ) -> bool { @@ -475,6 +506,9 @@ void T_ShaderManager::update( ) resetProgram( pr ); } } + if ( updates_.empty( ) ) { + return; + } // Reset pipelines affected by the programs above for ( auto plid : pipelines ) { @@ -489,12 +523,18 @@ void T_ShaderManager::update( ) for ( auto const& name : updates_ ) { auto& pr( programs_[ programIndex_[ name ] ] ); initProgram( pr ); + for ( auto const& e : pr.code.errors ) { + printf( "%s:%d: %s\n" , e.source.c_str( ) , e.line , + e.error.c_str( ) ); + } } // Try to initialise all affected pipelines for ( auto plid : pipelines ) { initPipeline( pipelines_[ plid ] ); } + + updates_.clear( ); } @@ -540,6 +580,9 @@ void T_ShaderManager::loadProgram( program.references.insert( pipeline ); program.id = 0; initProgram( program ); + for ( auto const& e : program.code.errors ) { + printf( "%s:%d: %s\n" , e.source.c_str( ) , e.line , e.error.c_str( ) ); + } } bool T_ShaderManager::useExistingProgram( @@ -618,6 +661,7 @@ void T_ShaderManager::initPipeline( { assert( pipeline.id == 0 ); + printf( "init pipeline %s\n" , pipeline.idString.c_str( ) ); constexpr auto nst{ size_t( E_ShaderType::__COUNT__ ) }; int32_t programs[ nst ]; for ( auto i = 0u ; i < nst ; i ++ ) { @@ -629,6 +673,7 @@ void T_ShaderManager::initPipeline( auto const& program( programs_[ pid ] ); if ( programs[ int( program.code.type ) ] != -1 || program.id == 0 ) { + printf( "... failed\n" ); return; } programs[ int( program.code.type ) ] = pid; @@ -648,10 +693,12 @@ void T_ShaderManager::initPipeline( } GL_CHECK({ glDeleteProgramPipelines( 1 , &id ); + printf( "... failed\n" ); return; }); pipeline.id = id; + printf( "... success\n" ); } @@ -662,6 +709,7 @@ void T_ShaderManager::initProgram( // Build the code auto name( program.name ); + printf( "init program %s\n" , program.name.c_str( ) ); auto& code( program.code ); T_CodeBuilder_ cb( [this]( std::string const& n ) { return getInput( n ); } , name , code ); @@ -678,7 +726,7 @@ void T_ShaderManager::initProgram( } ); for ( auto entry : code.files ) { if ( entry.second ) { - program.watch->watch( entry.first ); + program.watch->watch( "shaders/" + entry.first ); } else { missing_[ entry.first ].insert( name ); } @@ -725,6 +773,7 @@ void T_ShaderManager::initProgram( glGetProgramiv( sid , GL_LINK_STATUS , &lnk ); if ( lnk ) { program.id = sid; + printf( "... success\n" ); } else { glDeleteProgram( sid ); } @@ -739,7 +788,7 @@ void T_ShaderManager::parseGLSLError( std::cmatch m; uint32_t rawLine; if ( std::regex_match( errorLine , m , GLSLErrorNv_ ) ) { - rawLine = atoi( m[ 0 ].str( ).c_str( ) ); + rawLine = atoi( m[ 1 ].str( ).c_str( ) ); } else { rawLine = 0; } @@ -752,7 +801,7 @@ void T_ShaderManager::parseGLSLError( code.errors.push_back( T_ShaderError{ pos == 0 ? "*unknown*" : code.sources[ pos - 1 ] , - pos == 0 ? 0 : ( rawLine - ( check + code.counts[ pos - 1 ] ) + code.starts[ pos - 1 ] ) , + pos == 0 ? 0 : ( rawLine + code.counts[ pos - 1 ] - check + code.starts[ pos - 1 ] ) , errorLine } ); } diff --git a/shaders.hh b/shaders.hh index f2f64bb..589a8ce 100644 --- a/shaders.hh +++ b/shaders.hh @@ -88,6 +88,8 @@ struct T_ShaderPipeline bool valid( ) const noexcept; void enable( ) const; + GLuint program( __rd__ const E_ShaderType program ) const; + private: explicit T_ShaderPipeline( __rd__ const int32_t index ); diff --git a/shaders/fsquad.glsl b/shaders/fullscreen.v.glsl similarity index 90% rename from shaders/fsquad.glsl rename to shaders/fullscreen.v.glsl index b64e5b0..b3da9d2 100644 --- a/shaders/fsquad.glsl +++ b/shaders/fullscreen.v.glsl @@ -1,5 +1,7 @@ #version 450 core +//! type vertex + out gl_PerVertex { vec4 gl_Position; }; diff --git a/shaders/pbr.glsl b/shaders/pbr.glsl index 4937b2d..8e28a35 100644 --- a/shaders/pbr.glsl +++ b/shaders/pbr.glsl @@ -1,3 +1,5 @@ +//! type library + struct T_PBRMaterialOld { vec3 cAlbedo, cSpecular; diff --git a/shaders/raymarch-header.glsl b/shaders/raymarch-header.glsl index 0ccd569..70900fe 100644 --- a/shaders/raymarch-header.glsl +++ b/shaders/raymarch-header.glsl @@ -1,5 +1,3 @@ -#version 450 - layout( location = 0 ) uniform float u_Time; layout( location = 1 ) uniform vec2 u_Resolution; layout( location = 2 ) uniform vec3 u_CamPos; diff --git a/shaders/scene.f.glsl b/shaders/scene.f.glsl new file mode 100644 index 0000000..b8fa5d4 --- /dev/null +++ b/shaders/scene.f.glsl @@ -0,0 +1,7 @@ +#version 450 core +//! type fragment +//! include raymarch-header.glsl +//! include pbr.glsl +//! include blinn-phong.glsl +//! include map.glsl +//! include raymarcher.glsl