|
|
The current ACGL implementations allows for custom shader parsing and an especially simple interface for custom pragmas.
|
|
|
|
|
|
One notable application is the [[Includes in shaders]] extension.
|
|
|
|
|
|
## Class overview
|
|
|
|
|
|
Every *ShaderProgramCreator* and *ShaderCreator* has a *ShaderParserFactory* that is used to instantiate appropriate *ShaderParser* for every shader source file.
|
|
|
|
|
|
Without any modification, the default *IncludingShaderParser* will be used that supports the _ACGLimport_ pragma for source file inclusion.
|
|
|
|
|
|
In principle, a *ShaderParserFactory* may return a different parser based on the source file. In practice, the same parser for all files is often sufficient. To make things easier, the *SimpleShaderParserFactory<ShaderParserType>* can be used as a factory that returns a parser of type *ShaderParserType* for every file.
|
|
|
|
|
|
## Example
|
|
|
|
|
|
This example presents a simple shader parser that reacts to "#pragma CustomCode" by replacing it with some custom text. The parser is a subclass of *IncludingShaderParser* and is therefore also able to use the ACGLimport pragma.
|
|
|
|
|
|
ShaderParser code:
|
|
|
Header:
|
|
|
<pre>
|
|
|
class CustomShaderParser : public IncludingShaderParser
|
|
|
{
|
|
|
public:
|
|
|
/// c'tor
|
|
|
CustomShaderParser( std::string const& _filename ) : IncludingShaderParser(_filename) { }
|
|
|
|
|
|
/// Processes "#pragma CustomCode"
|
|
|
virtual bool processPragma(std::vector<std::string> const& _tokens, std::string const& _filename);
|
|
|
};
|
|
|
ACGL_SMARTPOINTER_TYPEDEFS(CustomShaderParser)
|
|
|
</pre>
|
|
|
Implementation:
|
|
|
<pre>
|
|
|
bool CustomShaderParser::processPragma(const std::vector<std::string> &_tokens, const std::string &_filename)
|
|
|
{
|
|
|
// (0) Check if correct pragma
|
|
|
if ( _tokens.size() == 1 && _tokens[0] == "CustomCode" )
|
|
|
{
|
|
|
// (1) - Start with lineNumber 1
|
|
|
int lineNumber = 1;
|
|
|
|
|
|
// (2) - Register appropriate source file (using registerSourceFile(...))
|
|
|
int fileID = registerSourceFile("Generated Pipeline Defines");
|
|
|
|
|
|
// (3) - Initialize source content with lineDirective(lineNumber, fileID)
|
|
|
std::string source = lineDirective(lineNumber, fileID);
|
|
|
|
|
|
// (4) - Add custom source content
|
|
|
source += "vec3 customFunction() { return vec3(0, 1, 0); }\n";
|
|
|
|
|
|
// (5) - Call addSource(...) with your source content
|
|
|
addSource(source);
|
|
|
|
|
|
// (6) - return true to indicate success
|
|
|
return true;
|
|
|
}
|
|
|
// Otherwise, return base class processPragma(...)
|
|
|
else return IncludingShaderParser::processPragma(_tokens, _filename);
|
|
|
}
|
|
|
</pre>
|
|
|
In most cases, it is sufficient to adapt point (0) and (4) in the above function.
|
|
|
|
|
|
Usage:
|
|
|
<pre>
|
|
|
// create shader program creator
|
|
|
ACGL::OpenGL::ShaderProgramCreator shader(...);
|
|
|
... shader setup ...
|
|
|
|
|
|
// register custom shader parser factory
|
|
|
shader.shaderParserFactory(std::make_shared<ACGL::OpenGL::SimpleShaderParserFactory<CustomShaderParser> >());
|
|
|
|
|
|
// create shader program using custom parser
|
|
|
ACGL::OpenGL::SharedShaderProgram shaderProg = shader.create();
|
|
|
</pre> |
|
|
\ No newline at end of file |