To the GLSL shader plugin added support forL
#pragma include shaderfile.glsl To enable easier reuse of shaders
This commit is contained in:
@@ -32,48 +32,115 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter
|
||||
|
||||
virtual const char* className() const { return "GLSL Shader Reader"; }
|
||||
|
||||
osg::Shader* processIncludes( const osg::Shader* shader, const Options* options ) const
|
||||
void processIncludes( osg::Shader& shader, const Options* options ) const
|
||||
{
|
||||
std::string code = shader->getShaderSource();
|
||||
std::string code = shader.getShaderSource();
|
||||
std::string startOfIncludeMarker("// Start of include code : ");
|
||||
std::string endOfIncludeMarker("// End of include code : ");
|
||||
std::string failedLoadMarker("// Failed to load include code : ");
|
||||
|
||||
#if defined(__APPLE__)
|
||||
std::string endOfLine("\r");
|
||||
#elif defined(_WIN32)
|
||||
std::string endOfLine("\r\n");
|
||||
#else
|
||||
std::string endOfLine("\n");
|
||||
#endif
|
||||
|
||||
|
||||
std::string::size_type pos = 0;
|
||||
|
||||
static std::string::size_type includeLen = 8;
|
||||
|
||||
while( ( pos = code.find( "#include", pos ) ) != std::string::npos )
|
||||
std::string::size_type pragma_pos = 0;
|
||||
std::string::size_type include_pos = 0;
|
||||
while( (pos !=std::string::npos) && (((pragma_pos=code.find( "#pragma", pos )) != std::string::npos) || (include_pos=code.find( "#include", pos )) != std::string::npos))
|
||||
{
|
||||
// we found an include
|
||||
std::string::size_type pos2 = code.find_first_not_of( " ", pos + includeLen );
|
||||
pos = (pragma_pos!= std::string::npos) ? pragma_pos : include_pos;
|
||||
|
||||
if ( ( pos2 == std::string::npos ) || ( code[ pos2 ] != '\"' ) )
|
||||
std::string::size_type start_of_pragma_line = pos;
|
||||
std::string::size_type end_of_line = code.find_first_of("\n\r", pos );
|
||||
|
||||
if (pragma_pos!= std::string::npos)
|
||||
{
|
||||
// error, bail out
|
||||
return NULL;
|
||||
// we have #pragma usage so skip to the start of the first non white space
|
||||
pos = code.find_first_not_of(" \t", pos+7 );
|
||||
if (pos==std::string::npos) break;
|
||||
|
||||
|
||||
// check for include part of #pragma imclude usage
|
||||
if (code.compare(pos, 7, "include")!=0)
|
||||
{
|
||||
pos = end_of_line;
|
||||
continue;
|
||||
}
|
||||
|
||||
// found include entry so skip to next non white space
|
||||
pos = code.find_first_not_of(" \t", pos+7 );
|
||||
if (pos==std::string::npos) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have #include usage so skip to next non white space
|
||||
pos = code.find_first_not_of(" \t", pos+8 );
|
||||
if (pos==std::string::npos) break;
|
||||
}
|
||||
|
||||
// we found an "
|
||||
std::string::size_type pos3 = code.find( "\"", pos2 + 1 );
|
||||
|
||||
if ( pos3 == std::string::npos )
|
||||
std::string::size_type num_characters = (end_of_line==std::string::npos) ? code.size()-pos : end_of_line-pos;
|
||||
if (num_characters==0) continue;
|
||||
|
||||
// prune trailing white space
|
||||
while(num_characters>0 && (code[pos+num_characters-1]==' ' || code[pos+num_characters-1]=='\t')) --num_characters;
|
||||
|
||||
if (code[pos]=='\"')
|
||||
{
|
||||
return NULL;
|
||||
if (code[pos+num_characters-1]!='\"')
|
||||
{
|
||||
num_characters -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_characters -= 2;
|
||||
}
|
||||
|
||||
++pos;
|
||||
}
|
||||
|
||||
const std::string filename = code.substr( pos2 + 1, pos3 - pos2 - 1 );
|
||||
std::string filename(code, pos, num_characters);
|
||||
|
||||
osg::ref_ptr<osg::Shader> innerShader = osgDB::readRefShaderFile( shader->getType(), filename, options );
|
||||
code.erase(start_of_pragma_line, (end_of_line==std::string::npos) ? code.size()-start_of_pragma_line : end_of_line-start_of_pragma_line);
|
||||
pos = start_of_pragma_line;
|
||||
|
||||
if ( !innerShader.valid() )
|
||||
osg::ref_ptr<osg::Shader> innerShader = osgDB::readRefShaderFile( filename, options );
|
||||
|
||||
if (innerShader.valid())
|
||||
{
|
||||
return NULL;
|
||||
if (!startOfIncludeMarker.empty())
|
||||
{
|
||||
code.insert(pos, startOfIncludeMarker); pos += startOfIncludeMarker.size();
|
||||
code.insert(pos, filename); pos += filename.size();
|
||||
code.insert(pos, endOfLine); pos += endOfLine.size();
|
||||
}
|
||||
|
||||
code.insert(pos, innerShader->getShaderSource() ); pos += innerShader->getShaderSource().size();
|
||||
|
||||
if (!endOfIncludeMarker.empty())
|
||||
{
|
||||
code.insert(pos, endOfIncludeMarker); pos += endOfIncludeMarker.size();
|
||||
code.insert(pos, filename); pos += filename.size();
|
||||
code.insert(pos, endOfLine); pos += endOfLine.size();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!failedLoadMarker.empty())
|
||||
{
|
||||
code.insert(pos, failedLoadMarker); pos += failedLoadMarker.size();
|
||||
code.insert(pos, filename); pos += filename.size();
|
||||
code.insert(pos, endOfLine); pos += endOfLine.size();
|
||||
}
|
||||
}
|
||||
|
||||
code.replace( pos, pos3 - pos + 1, innerShader->getShaderSource() );
|
||||
|
||||
pos += innerShader->getShaderSource().size();
|
||||
}
|
||||
|
||||
return new osg::Shader( shader->getType(), code );
|
||||
shader.setShaderSource(code);
|
||||
}
|
||||
|
||||
virtual ReadResult readObject(std::istream& fin,const Options* options) const
|
||||
@@ -108,8 +175,10 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter
|
||||
if (options->getOptionString().find("compute")!=std::string::npos) shader->setType(osg::Shader::COMPUTE);
|
||||
}
|
||||
|
||||
processIncludes( *shader, options );
|
||||
|
||||
// return valid shader
|
||||
return processIncludes( shader.get(), options );
|
||||
return shader.get();
|
||||
}
|
||||
|
||||
virtual ReadResult readShader(const std::string& file, const osgDB::ReaderWriter::Options* options) const
|
||||
@@ -120,9 +189,12 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter
|
||||
std::string fileName = osgDB::findDataFile( file, options );
|
||||
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
|
||||
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
|
||||
|
||||
osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
|
||||
if(!istream) return ReadResult::FILE_NOT_HANDLED;
|
||||
ReadResult rr = readShader(istream, options);
|
||||
ReadResult rr = readShader(istream, local_opt);
|
||||
if(rr.validShader())
|
||||
{
|
||||
osg::Shader* shader = rr.getShader();
|
||||
|
||||
Reference in New Issue
Block a user