Shaders - directives for uniforms
This commit is contained in:
parent
d53269e09e
commit
7ab196df56
2 changed files with 112 additions and 22 deletions
115
shaders.cc
115
shaders.cc
|
@ -6,7 +6,7 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const std::regex PreprocDirective_( "^\\s*//!\\s*([a-z]+(\\s+([^\\s]+))*)\\s*$" );
|
const std::regex PreprocDirective_( "^\\s*//!\\s*([a-z]+(\\s+([^\\s]+))*)\\s*$" );
|
||||||
|
const std::regex UniformName_( "^[A-Za-z][A-Za-z0-9_]*$" );
|
||||||
const std::regex GLSLErrorNv_( "^[0-9]*\\(([0-9]+).*$" );
|
const std::regex GLSLErrorNv_( "^[0-9]*\\(([0-9]+).*$" );
|
||||||
|
|
||||||
const std::map< std::string , E_ShaderInput > InputTypes_( ([] {
|
const std::map< std::string , E_ShaderInput > InputTypes_( ([] {
|
||||||
|
@ -22,6 +22,20 @@ const std::map< std::string , E_ShaderInput > InputTypes_( ([] {
|
||||||
return t;
|
return t;
|
||||||
})());
|
})());
|
||||||
|
|
||||||
|
const std::unordered_map< std::string , E_UniformType > UniformTypes_( ([] {
|
||||||
|
std::unordered_map< std::string , E_UniformType > t;
|
||||||
|
t.emplace( "float" , E_UniformType::F1 );
|
||||||
|
t.emplace( "vec2" , E_UniformType::F2 );
|
||||||
|
t.emplace( "vec3" , E_UniformType::F3 );
|
||||||
|
t.emplace( "vec4" , E_UniformType::F4 );
|
||||||
|
t.emplace( "int" , E_UniformType::I1 );
|
||||||
|
t.emplace( "ivec2" , E_UniformType::I2 );
|
||||||
|
t.emplace( "ivec3" , E_UniformType::I3 );
|
||||||
|
t.emplace( "ivec4" , E_UniformType::I4 );
|
||||||
|
t.emplace( "sampler2D" , E_UniformType::SAMPLER2D );
|
||||||
|
return t;
|
||||||
|
})());
|
||||||
|
|
||||||
const GLenum ProgramTypes_[] = {
|
const GLenum ProgramTypes_[] = {
|
||||||
GL_VERTEX_SHADER ,
|
GL_VERTEX_SHADER ,
|
||||||
GL_FRAGMENT_SHADER ,
|
GL_FRAGMENT_SHADER ,
|
||||||
|
@ -64,11 +78,16 @@ struct T_InputReader_
|
||||||
~T_InputReader_( );
|
~T_InputReader_( );
|
||||||
|
|
||||||
void read( );
|
void read( );
|
||||||
void nl( );
|
|
||||||
void addAccumulated( );
|
|
||||||
void handleDirective(
|
void handleDirective(
|
||||||
__rd__ T_Tokens_ const& tokens );
|
__rd__ T_Tokens_ const& tokens );
|
||||||
void error( __rd__ std::string const& err );
|
void parseInputDirective(
|
||||||
|
__rd__ T_Tokens_ const& tokens );
|
||||||
|
|
||||||
|
void error(
|
||||||
|
__rd__ std::string const& err );
|
||||||
|
void nl( );
|
||||||
|
void addAccumulated( );
|
||||||
};
|
};
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
@ -103,22 +122,7 @@ void T_InputReader_::read( )
|
||||||
addAccumulated( );
|
addAccumulated( );
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_InputReader_::nl( )
|
/*----------------------------------------------------------------------------*/
|
||||||
{
|
|
||||||
accumLines ++;
|
|
||||||
accumulator += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
void T_InputReader_::addAccumulated( )
|
|
||||||
{
|
|
||||||
if ( accumLines ) {
|
|
||||||
auto& ck( input.chunks );
|
|
||||||
ck.emplace_back( E_ShaderInputChunk::CODE ,
|
|
||||||
std::move( accumulator ) , accumLines );
|
|
||||||
accumulator = {};
|
|
||||||
accumLines = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void T_InputReader_::handleDirective(
|
void T_InputReader_::handleDirective(
|
||||||
__rd__ T_Tokens_ const& tokens )
|
__rd__ T_Tokens_ const& tokens )
|
||||||
|
@ -148,20 +152,89 @@ void T_InputReader_::handleDirective(
|
||||||
input.type = pos->second;
|
input.type = pos->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if ( directive == "input" ) {
|
||||||
|
nl( );
|
||||||
|
parseInputDirective( tokens );
|
||||||
|
|
||||||
|
} else if ( directive == "uniforms" ) {
|
||||||
|
nl( );
|
||||||
|
for ( auto const& c : input.chunks ) {
|
||||||
|
if ( c.type == E_ShaderInputChunk::UNIFORMS ) {
|
||||||
|
error( "duplicate uniform generation" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input.chunks.emplace_back( E_ShaderInputChunk::UNIFORMS , "" , 1 );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
nl( );
|
nl( );
|
||||||
error( "unknown directive" );
|
error( "unknown directive" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void T_InputReader_::parseInputDirective(
|
||||||
|
__rd__ T_Tokens_ const& tokens )
|
||||||
|
{
|
||||||
|
if ( tokens.size( ) != 4 ) {
|
||||||
|
error( "invalid arguments" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local/global
|
||||||
|
const bool global{ tokens[ 1 ] == "global" };
|
||||||
|
if ( !global && tokens[ 1 ] != "local" ) {
|
||||||
|
error( "second argument should be 'local' or 'global'" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name
|
||||||
|
std::string const& name{ tokens[ 2 ] };
|
||||||
|
if ( input.uniforms.find( name ) != input.uniforms.end( ) ) {
|
||||||
|
error( "duplicate uniform" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( !std::regex_match( name , UniformName_ ) ) {
|
||||||
|
error( "invalid uniform name" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type
|
||||||
|
auto tPos( UniformTypes_.find( tokens[ 3 ] ) );
|
||||||
|
if ( tPos == UniformTypes_.end( ) ) {
|
||||||
|
error( "unsupported uniform type" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.uniforms.emplace( tokens[ 2 ] , T_ShaderUniform{
|
||||||
|
tokens[ 2 ] , global , tPos->second } );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void T_InputReader_::error(
|
void T_InputReader_::error(
|
||||||
__rd__ std::string const& err )
|
__rd__ std::string const& err )
|
||||||
{
|
{
|
||||||
printf( "input error (%d - %s)\n" , line , err.c_str( ) );
|
|
||||||
input.errors.push_back( T_ShaderInputError{
|
input.errors.push_back( T_ShaderInputError{
|
||||||
line , err } );
|
line , err } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void T_InputReader_::nl( )
|
||||||
|
{
|
||||||
|
accumLines ++;
|
||||||
|
accumulator += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_InputReader_::addAccumulated( )
|
||||||
|
{
|
||||||
|
if ( accumLines ) {
|
||||||
|
auto& ck( input.chunks );
|
||||||
|
ck.emplace_back( E_ShaderInputChunk::CODE ,
|
||||||
|
std::move( accumulator ) , accumLines );
|
||||||
|
accumulator = {};
|
||||||
|
accumLines = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
19
shaders.hh
19
shaders.hh
|
@ -8,7 +8,8 @@
|
||||||
// Type of input chunk
|
// Type of input chunk
|
||||||
enum class E_ShaderInputChunk {
|
enum class E_ShaderInputChunk {
|
||||||
CODE ,
|
CODE ,
|
||||||
INCLUDE
|
INCLUDE ,
|
||||||
|
UNIFORMS
|
||||||
};
|
};
|
||||||
|
|
||||||
// Input chunk data
|
// Input chunk data
|
||||||
|
@ -44,12 +45,28 @@ struct T_ShaderInputError
|
||||||
std::string error;
|
std::string error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Uniform types
|
||||||
|
enum class E_UniformType {
|
||||||
|
F1 , F2 , F3 , F4 ,
|
||||||
|
I1 , I2 , I3 , I4 ,
|
||||||
|
SAMPLER2D
|
||||||
|
};
|
||||||
|
|
||||||
|
// Uniform declarations
|
||||||
|
struct T_ShaderUniform
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
bool global;
|
||||||
|
E_UniformType type;
|
||||||
|
};
|
||||||
|
|
||||||
// Source file
|
// Source file
|
||||||
struct T_ShaderInput
|
struct T_ShaderInput
|
||||||
{
|
{
|
||||||
E_ShaderInput type = E_ShaderInput::CHUNK;
|
E_ShaderInput type = E_ShaderInput::CHUNK;
|
||||||
std::vector< T_ShaderInputChunk > chunks;
|
std::vector< T_ShaderInputChunk > chunks;
|
||||||
std::vector< T_ShaderInputError > errors;
|
std::vector< T_ShaderInputError > errors;
|
||||||
|
std::unordered_map< std::string , T_ShaderUniform > uniforms;
|
||||||
|
|
||||||
bool load( __rd__ std::string const& path );
|
bool load( __rd__ std::string const& path );
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue