Introduced new shader composition approach that utilizes #pragma requires(), #pragma import_defines() and #ifdef in GLSL to enable multiple different versions of shaders based

on defines passed in from osg::StateSet::setDefine(..).



git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14681 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield
2015-02-10 17:04:02 +00:00
parent bb637e73f3
commit b90503fdf5
14 changed files with 910 additions and 175 deletions

View File

@@ -850,49 +850,6 @@ void Geometry::drawPrimitivesImplementation(RenderInfo& renderInfo) const
}
}
class AttributeFunctorArrayVisitor : public ArrayVisitor
{
public:
AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
_af(af),
_type(0) {}
virtual ~AttributeFunctorArrayVisitor() {}
virtual void apply(ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
inline void applyArray(Drawable::AttributeType type,Array* array)
{
if (array)
{
_type = type;
array->accept(*this);
}
}
protected:
AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
Drawable::AttributeFunctor& _af;
Drawable::AttributeType _type;
};
void Geometry::accept(AttributeFunctor& af)
{
AttributeFunctorArrayVisitor afav(af);
@@ -923,49 +880,6 @@ void Geometry::accept(AttributeFunctor& af)
}
}
class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
{
public:
ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
_af(af),
_type(0) {}
virtual ~ConstAttributeFunctorArrayVisitor() {}
virtual void apply(const ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
virtual void apply(const Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
inline void applyArray(Drawable::AttributeType type,const Array* array)
{
if (array)
{
_type = type;
array->accept(*this);
}
}
protected:
ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
Drawable::ConstAttributeFunctor& _af;
Drawable::AttributeType _type;
};
void Geometry::accept(ConstAttributeFunctor& af) const
{

View File

@@ -247,8 +247,6 @@ void Program::compileGLObjects( osg::State& state ) const
{
if( isFixedFunction() ) return;
const unsigned int contextID = state.getContextID();
for( unsigned int i=0; i < _shaderList.size(); ++i )
{
_shaderList[i]->compileShader( state );
@@ -256,7 +254,7 @@ void Program::compileGLObjects( osg::State& state ) const
if(!_feedbackout.empty())
{
const PerContextProgram* pcp = getPCP(contextID);
const PerContextProgram* pcp = getPCP(state);
const GLExtensions* extensions = state.get<GLExtensions>();
unsigned int numfeedback = _feedbackout.size();
@@ -272,7 +270,7 @@ void Program::compileGLObjects( osg::State& state ) const
extensions->glTransformFeedbackVaryings( pcp->getHandle(), numfeedback, varyings, _feedbackmode);
delete [] varyings;
}
getPCP( contextID )->linkProgram(state);
getPCP( state )->linkProgram(state);
}
void Program::setThreadSafeRefUnref(bool threadSafe)
@@ -292,6 +290,20 @@ void Program::dirtyProgram()
{
if( _pcpList[cxt].valid() ) _pcpList[cxt]->requestLink();
}
// update list of defines required.
_shaderDefines.clear();
for(ShaderList::iterator itr = _shaderList.begin();
itr != _shaderList.end();
++itr)
{
Shader* shader = itr->get();
ShaderDefines& sd = shader->getShaderDefines();
_shaderDefines.insert(sd.begin(), sd.end());
ShaderDefines& sr = shader->getShaderRequirements();
_shaderDefines.insert(sr.begin(), sr.end());
}
}
@@ -376,14 +388,17 @@ void Program::setParameter( GLenum pname, GLint value )
{
switch( pname )
{
case GL_GEOMETRY_VERTICES_OUT:
case GL_GEOMETRY_VERTICES_OUT_EXT:
_geometryVerticesOut = value;
dirtyProgram();
break;
case GL_GEOMETRY_INPUT_TYPE:
case GL_GEOMETRY_INPUT_TYPE_EXT:
_geometryInputType = value;
dirtyProgram(); // needed?
break;
case GL_GEOMETRY_OUTPUT_TYPE:
case GL_GEOMETRY_OUTPUT_TYPE_EXT:
_geometryOutputType = value;
//dirtyProgram(); // needed?
@@ -401,9 +416,15 @@ GLint Program::getParameter( GLenum pname ) const
{
switch( pname )
{
case GL_GEOMETRY_VERTICES_OUT_EXT: return _geometryVerticesOut;
case GL_GEOMETRY_INPUT_TYPE_EXT: return _geometryInputType;
case GL_GEOMETRY_OUTPUT_TYPE_EXT: return _geometryOutputType;
case GL_GEOMETRY_VERTICES_OUT:
case GL_GEOMETRY_VERTICES_OUT_EXT:
return _geometryVerticesOut;
case GL_GEOMETRY_INPUT_TYPE:
case GL_GEOMETRY_INPUT_TYPE_EXT:
return _geometryInputType;
case GL_GEOMETRY_OUTPUT_TYPE:
case GL_GEOMETRY_OUTPUT_TYPE_EXT:
return _geometryOutputType;
}
OSG_WARN << "getParameter invalid param " << pname << std::endl;
return 0;
@@ -464,7 +485,6 @@ void Program::removeBindUniformBlock(const std::string& name)
#include <iostream>
void Program::apply( osg::State& state ) const
{
const unsigned int contextID = state.getContextID();
const GLExtensions* extensions = state.get<GLExtensions>();
if( ! extensions->isGlslSupported ) return;
@@ -475,7 +495,66 @@ void Program::apply( osg::State& state ) const
return;
}
PerContextProgram* pcp = getPCP( contextID );
#if 0
State::DefineMap& defMap = state.getDefineMap();
OSG_NOTICE<<"Program::apply() defMap.changed="<<defMap.changed<<std::endl;
for(State::DefineMap::DefineStackMap::const_iterator itr = defMap.map.begin();
itr != defMap.map.end();
++itr)
{
const State::DefineStack& ds = itr->second;
OSG_NOTICE<<" define ["<<itr->first<<"] ds.changed="<<ds.changed<<" ";
if (ds.defineVec.empty())
{
OSG_NOTICE<<" DefineStack empty "<<std::endl;
}
else
{
const StateSet::DefinePair& dp = ds.defineVec.back();
OSG_NOTICE<<" value = ["<<dp.first<<"], overridevalue = ["<<dp.second<<"]"<< std::endl;
}
}
if (defMap.changed) defMap.updateCurrentDefines();
std::string shaderDefineStr = state.getDefineString(getShaderDefines());
OSG_NOTICE<<"TailoredShaderDefineStr={"<<std::endl;
OSG_NOTICE<<shaderDefineStr;
OSG_NOTICE<<"}"<<std::endl;
shaderDefineStr.clear();
const StateSet::DefineList& currentDefines = defMap.currentDefines;
for(StateSet::DefineList::const_iterator itr = currentDefines.begin();
itr != currentDefines.end();
++itr)
{
const StateSet::DefinePair& dp = itr->second;
shaderDefineStr += "#define ";
shaderDefineStr += itr->first;
if (itr->second.first.empty())
{
shaderDefineStr += "\n";
}
else
{
shaderDefineStr += " ";
shaderDefineStr += itr->second.first;
shaderDefineStr += "\n";
}
OSG_NOTICE<<" active-define = ["<<itr->first<<"], value="<<itr->second.first<<", overridevalue = ["<<itr->second.second<<"]"<< std::endl;
}
OSG_NOTICE<<"FullShaderDefineStr={"<<std::endl;
OSG_NOTICE<<shaderDefineStr;
OSG_NOTICE<<"}"<<std::endl;
#endif
PerContextProgram* pcp = getPCP( state );
if( pcp->needsLink() ) compileGLObjects( state );
if( pcp->isLinked() )
{
@@ -497,20 +576,102 @@ void Program::apply( osg::State& state ) const
}
Program::PerContextProgram* Program::getPCP(unsigned int contextID) const
Program::ProgramObjects::ProgramObjects(const osg::Program* program, unsigned int contextID):
_contextID(contextID),
_program(program)
{
if( ! _pcpList[contextID].valid() )
{
_pcpList[contextID] = new PerContextProgram( this, contextID );
}
// attach all PCSs to this new PCP
for( unsigned int i=0; i < _shaderList.size(); ++i )
Program::PerContextProgram* Program::ProgramObjects::getPCP(const std::string& defineStr) const
{
for(PerContextPrograms::const_iterator itr = _perContextPrograms.begin();
itr != _perContextPrograms.end();
++itr)
{
if ((*itr)->getDefineString()==defineStr)
{
_pcpList[contextID]->addShaderToAttach( _shaderList[i].get() );
// OSG_NOTICE<<"Returning PCP "<<itr->get()<<" DefineString = "<<(*itr)->getDefineString()<<std::endl;
return itr->get();
}
}
return 0;
}
return _pcpList[contextID].get();
Program::PerContextProgram* Program::ProgramObjects::createPerContextProgram(const std::string& defineStr)
{
Program::PerContextProgram* pcp = new PerContextProgram( _program, _contextID );
_perContextPrograms.push_back( pcp );
pcp->setDefineString(defineStr);
// OSG_NOTICE<<"Creating PCP "<<pcp<<" PCP DefineString = ["<<pcp->getDefineString()<<"]"<<std::endl;
return pcp;
}
void Program::ProgramObjects::requestLink()
{
for(PerContextPrograms::iterator itr = _perContextPrograms.begin();
itr != _perContextPrograms.end();
++itr)
{
(*itr)->requestLink();
}
}
void Program::ProgramObjects::addShaderToAttach(Shader* shader)
{
for(PerContextPrograms::iterator itr = _perContextPrograms.begin();
itr != _perContextPrograms.end();
++itr)
{
(*itr)->addShaderToAttach(shader);
}
}
void Program::ProgramObjects::addShaderToDetach(Shader* shader)
{
for(PerContextPrograms::iterator itr = _perContextPrograms.begin();
itr != _perContextPrograms.end();
++itr)
{
(*itr)->addShaderToDetach(shader);
}
}
bool Program::ProgramObjects::getGlProgramInfoLog(std::string& log) const
{
bool result = false;
for(PerContextPrograms::const_iterator itr = _perContextPrograms.begin();
itr != _perContextPrograms.end();
++itr)
{
result = (*itr)->getInfoLog( log ) | result;
}
return result;
}
Program::PerContextProgram* Program::getPCP(State& state) const
{
unsigned int contextID = state.getContextID();
const std::string defineStr = state.getDefineString(getShaderDefines());
if( ! _pcpList[contextID].valid() )
{
_pcpList[contextID] = new ProgramObjects( this, contextID );
}
Program::PerContextProgram* pcp = _pcpList[contextID]->getPCP(defineStr);
if (pcp) return pcp;
pcp = _pcpList[contextID]->createPerContextProgram(defineStr);
// attach all PCSs to this new PCP
for( unsigned int i=0; i < _shaderList.size(); ++i )
{
pcp->addShaderToAttach( _shaderList[i].get() );
}
return pcp;
}
@@ -525,9 +686,11 @@ bool Program::isFixedFunction() const
bool Program::getGlProgramInfoLog(unsigned int contextID, std::string& log) const
{
return getPCP( contextID )->getInfoLog( log );
if (contextID<_pcpList.size()) return (_pcpList[ contextID ])->getGlProgramInfoLog( log );
else return false;
}
#if 0
const Program::ActiveUniformMap& Program::getActiveUniforms(unsigned int contextID) const
{
return getPCP( contextID )->getActiveUniforms();
@@ -542,6 +705,7 @@ const Program::UniformBlockMap& Program::getUniformBlocks(unsigned contextID) co
{
return getPCP( contextID )->getUniformBlocks();
}
#endif
///////////////////////////////////////////////////////////////////////////
// osg::Program::PerContextProgram
@@ -603,19 +767,20 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
_loadedBinary = _isLinked = (linked == GL_TRUE);
}
if (!_loadedBinary && _extensions->isGeometryShader4Supported)
{
_extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_VERTICES_OUT_EXT, _program->_geometryVerticesOut );
_extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_INPUT_TYPE_EXT, _program->_geometryInputType );
_extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, _program->_geometryOutputType );
}
if (!_loadedBinary)
{
if (_extensions->isGeometryShader4Supported)
{
_extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_VERTICES_OUT_EXT, _program->_geometryVerticesOut );
_extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_INPUT_TYPE_EXT, _program->_geometryInputType );
_extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, _program->_geometryOutputType );
}
// Detach removed shaders
for( unsigned int i=0; i < _shadersToDetach.size(); ++i )
{
_shadersToDetach[i]->detachShader( _contextID, _glProgramHandle );
Shader::PerContextShader* pcs = _shadersToDetach[i]->getPCS(state);
if (pcs) _extensions->glDetachShader( _glProgramHandle, pcs->getHandle() );
}
}
_shadersToDetach.clear();
@@ -625,9 +790,12 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
// Attach new shaders
for( unsigned int i=0; i < _shadersToAttach.size(); ++i )
{
_shadersToAttach[i]->attachShader( _contextID, _glProgramHandle );
Shader::PerContextShader* pcs = _shadersToAttach[i]->getPCS(state);
if (pcs) _extensions->glAttachShader( _glProgramHandle, pcs->getHandle() );
}
}
//state.checkGLErrors("After attaching shaders.");
_shadersToAttach.clear();
_uniformInfoMap.clear();
@@ -909,6 +1077,10 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
delete [] name;
}
OSG_INFO << std::endl;
//state.checkGLErrors("After Program::PerContextProgram::linkProgram.");
}
bool Program::PerContextProgram::validateProgram()

View File

@@ -214,19 +214,22 @@ void Shader::discardDeletedGlShaders(unsigned int contextID)
///////////////////////////////////////////////////////////////////////////
Shader::Shader(Type type) :
_type(type)
_type(type),
_shaderDefinesMode(USE_SHADER_PRAGAMA)
{
}
Shader::Shader(Type type, const std::string& source) :
_type(type)
_type(type),
_shaderDefinesMode(USE_SHADER_PRAGAMA)
{
setShaderSource( source);
}
Shader::Shader(Type type, ShaderBinary* shaderBinary) :
_type(type),
_shaderBinary(shaderBinary)
_shaderBinary(shaderBinary),
_shaderDefinesMode(USE_SHADER_PRAGAMA)
{
}
@@ -237,7 +240,8 @@ Shader::Shader(const Shader& rhs, const osg::CopyOp& copyop):
_shaderFileName(rhs._shaderFileName),
_shaderSource(rhs._shaderSource),
_shaderBinary(rhs._shaderBinary),
_codeInjectionMap(rhs._codeInjectionMap)
_codeInjectionMap(rhs._codeInjectionMap),
_shaderDefinesMode(rhs._shaderDefinesMode)
{
}
@@ -283,6 +287,9 @@ int Shader::compare(const Shader& rhs) const
void Shader::setShaderSource( const std::string& sourceText )
{
_shaderSource = sourceText;
_computeShaderDefines();
dirtyShader();
}
@@ -365,12 +372,55 @@ void Shader::releaseGLObjects(osg::State* state) const
void Shader::compileShader( osg::State& state ) const
{
PerContextShader* pcs = getPCS( state.getContextID() );
PerContextShader* pcs = getPCS( state );
if( pcs ) pcs->compileShader( state );
}
Shader::PerContextShader* Shader::getPCS(unsigned int contextID) const
Shader::ShaderObjects::ShaderObjects(const osg::Shader* shader, unsigned int contextID):
_contextID(contextID),
_shader(shader)
{
}
Shader::PerContextShader* Shader::ShaderObjects::getPCS(const std::string& defineStr) const
{
for(PerContextShaders::const_iterator itr = _perContextShaders.begin();
itr != _perContextShaders.end();
++itr)
{
if ((*itr)->getDefineString()==defineStr)
{
// OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' returning PCS "<<itr->get()<<" DefineString = "<<(*itr)->getDefineString()<<std::endl;
return itr->get();
}
}
// OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' returning NULL"<<std::endl;
return 0;
}
Shader::PerContextShader* Shader::ShaderObjects::createPerContextShader(const std::string& defineStr)
{
Shader::PerContextShader* pcs = new PerContextShader( _shader, _contextID );
_perContextShaders.push_back( pcs );
pcs->setDefineString(defineStr);
// OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' Creating PCS "<<pcs<<" DefineString = ["<<pcs->getDefineString()<<"]"<<std::endl;
return pcs;
}
void Shader::ShaderObjects::requestCompile()
{
for(PerContextShaders::const_iterator itr = _perContextShaders.begin();
itr != _perContextShaders.end();
++itr)
{
(*itr)->requestCompile();
}
}
Shader::PerContextShader* Shader::getPCS(osg::State& state) const
{
if( getType() == UNDEFINED )
{
@@ -378,31 +428,28 @@ Shader::PerContextShader* Shader::getPCS(unsigned int contextID) const
return 0;
}
if (!state.supportsShaderRequirements(_shaderRequirements))
{
// OSG_NOTICE<<"Shader not supported "<<_shaderRequirements.size()<<std::endl;
return 0;
}
unsigned int contextID = state.getContextID();
if( ! _pcsList[contextID].valid() )
{
_pcsList[contextID] = new PerContextShader( this, contextID );
_pcsList[contextID] = new ShaderObjects( this, contextID );
}
return _pcsList[contextID].get();
}
const std::string defineStr = state.getDefineString(getShaderDefines());
PerContextShader* pcs = _pcsList[contextID]->getPCS(defineStr);
if (pcs) return pcs;
void Shader::attachShader(unsigned int contextID, GLuint program) const
{
PerContextShader* pcs = getPCS( contextID );
if( pcs ) pcs->attachShader( program );
}
if (state.supportsShaderRequirements(_shaderRequirements))
{
pcs = _pcsList[contextID]->createPerContextShader(defineStr);
}
void Shader::detachShader(unsigned int contextID, GLuint program) const
{
PerContextShader* pcs = getPCS( contextID );
if( pcs ) pcs->detachShader( program );
}
bool Shader::getGlShaderInfoLog(unsigned int contextID, std::string& log) const
{
PerContextShader* pcs = getPCS( contextID );
return (pcs) ? pcs->getInfoLog( log ) : false;
return pcs;
}
@@ -577,8 +624,21 @@ void Shader::PerContextShader::compileShader(osg::State& state)
}
GLint compiled = GL_FALSE;
const GLchar* sourceText = reinterpret_cast<const GLchar*>(source.c_str());
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
// OSG_NOTICE<<"Compiling PerContextShader "<<this<<" ShaderDefine="<<getDefineString()<<std::endl;
if (_defineStr.empty())
{
const GLchar* sourceText = reinterpret_cast<const GLchar*>(source.c_str());
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
}
else
{
const GLchar* sourceText[2];
sourceText[0] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
sourceText[1] = reinterpret_cast<const GLchar*>(source.c_str());
_extensions->glShaderSource( _glShaderHandle, 2, sourceText, NULL );
}
_extensions->glCompileShader( _glShaderHandle );
_extensions->glGetShaderiv( _glShaderHandle, GL_COMPILE_STATUS, &compiled );
@@ -621,3 +681,96 @@ void Shader::PerContextShader::detachShader(GLuint program) const
{
_extensions->glDetachShader( program, _glShaderHandle );
}
void Shader::_parseShaderDefines(const std::string& str, ShaderDefines& defines)
{
std::string::size_type start_of_parameter = 0;
do
{
// skip spaces, tabs, commans
start_of_parameter = str.find_first_not_of(" \t,", start_of_parameter);
if (start_of_parameter==std::string::npos) break;
// find end of the parameter
std::string::size_type end_of_parameter = str.find_first_of(" \t,)", start_of_parameter);
if (end_of_parameter==std::string::npos) end_of_parameter = str.size();
std::string parameter = str.substr(start_of_parameter, end_of_parameter-start_of_parameter);
defines.insert(parameter);
start_of_parameter = end_of_parameter;
} while (start_of_parameter<str.size());
}
void Shader::_computeShaderDefines()
{
if (_shaderDefinesMode==USE_MANUAL_SETTINGS) return;
std::string::size_type pos = 0;
_shaderDefines.clear();
_shaderRequirements.clear();
while ((pos = _shaderSource.find("#pragma", pos))!=std::string::npos)
{
// skip over #pragma characters
pos += 7;
std::string::size_type first_chararcter = _shaderSource.find_first_not_of(" \t", pos);
std::string::size_type eol = _shaderSource.find_first_of("\n\r", pos);
if (eol==std::string::npos) eol = _shaderSource.size();
// OSG_NOTICE<<"\nFound pragma line ["<<_shaderSource.substr(first_chararcter, eol-first_chararcter)<<"]"<<std::endl;
if (first_chararcter<eol)
{
std::string::size_type end_of_keyword = _shaderSource.find_first_of(" \t(", first_chararcter);
std::string keyword = _shaderSource.substr(first_chararcter, end_of_keyword-first_chararcter);
std::string::size_type open_brackets = _shaderSource.find_first_of("(", end_of_keyword);
std::string::size_type close_brackets = _shaderSource.find_first_of(")", open_brackets);
if ((open_brackets!=std::string::npos) && (close_brackets!=std::string::npos) && (close_brackets<eol))
{
std::string str(_shaderSource, open_brackets+1, close_brackets-open_brackets-1);
// OSG_NOTICE<<" parameter str = ["<<str<<"]"<<std::endl;
if (keyword == "import_defines") _parseShaderDefines(str, _shaderDefines);
else if (keyword == "requires") _parseShaderDefines(str, _shaderRequirements);
else {
//OSG_NOTICE<<" keyword not matched ["<<keyword<<"]"<<std::endl;
_parseShaderDefines(str, _shaderDefines);
}
#if 0
for(ShaderDefines::iterator itr = _shaderDefines.begin();
itr != _shaderDefines.end();
++itr)
{
OSG_NOTICE<<" define ["<<*itr<<"]"<<std::endl;
}
for(ShaderDefines::iterator itr = _shaderRequirements.begin();
itr != _shaderRequirements.end();
++itr)
{
OSG_NOTICE<<" requirements ["<<*itr<<"]"<<std::endl;
}
#endif
}
#if 0
else
{
OSG_NOTICE<<" Found keyword ["<<keyword<<"] but not matched ()\n"<<std::endl;
}
#endif
}
pos = eol;
}
}

View File

@@ -338,6 +338,8 @@ void State::pushStateSet(const StateSet* dstate)
}
pushUniformList(_uniformMap,dstate->getUniformList());
pushDefineList(_defineMap,dstate->getDefineList());
}
// OSG_NOTICE<<"State::pushStateSet()"<<_stateStateStack.size()<<std::endl;
@@ -388,6 +390,8 @@ void State::popStateSet()
popUniformList(_uniformMap,dstate->getUniformList());
popDefineList(_defineMap,dstate->getDefineList());
}
// remove the top draw state from the stack.
@@ -513,6 +517,7 @@ void State::apply(const StateSet* dstate)
const Program::PerContextProgram* previousLastAppliedProgramObject = _lastAppliedProgramObject;
applyModeList(_modeMap,dstate->getModeList());
applyDefineList(_defineMap, dstate->getDefineList());
applyAttributeList(_attributeMap,dstate->getAttributeList());
if (_shaderCompositionEnabled)
@@ -617,7 +622,7 @@ void State::applyShaderComposition()
if (_currentShaderCompositionProgram)
{
Program::PerContextProgram* pcp = _currentShaderCompositionProgram->getPCP(_contextID);
Program::PerContextProgram* pcp = _currentShaderCompositionProgram->getPCP(*this);
if (_lastAppliedProgramObject != pcp) applyAttribute(_currentShaderCompositionProgram);
}
}
@@ -1284,23 +1289,24 @@ bool State::checkGLErrors(const char* str) const
GLenum errorNo = glGetError();
if (errorNo!=GL_NO_ERROR)
{
osg::NotifySeverity notifyLevel = NOTICE; // WARN;
const char* error = (char*)gluErrorString(errorNo);
if (error)
{
OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error '" << error<<"'";
OSG_NOTIFY(notifyLevel)<<"Warning: detected OpenGL error '" << error<<"'";
}
else
{
OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
OSG_NOTIFY(notifyLevel)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
}
if (str)
{
OSG_NOTIFY(WARN)<<" at "<<str<< std::endl;
OSG_NOTIFY(notifyLevel)<<" at "<<str<< std::endl;
}
else
{
OSG_NOTIFY(WARN)<<" in osg::State."<< std::endl;
OSG_NOTIFY(notifyLevel)<<" in osg::State."<< std::endl;
}
return true;
@@ -1769,3 +1775,91 @@ void State::frameCompleted()
//OSG_NOTICE<<"State::frameCompleted() setting time stamp. timestamp="<<timestamp<<std::endl;
}
}
bool State::DefineMap::updateCurrentDefines()
{
if (changed)
{
currentDefines.clear();
for(DefineStackMap::const_iterator itr = map.begin();
itr != map.end();
++itr)
{
const DefineStack::DefineVec& dv = itr->second.defineVec;
if (!dv.empty())
{
const StateSet::DefinePair& dp = dv.back();
if (dp.second & osg::StateAttribute::ON)
{
currentDefines[itr->first] = dp;
}
}
}
return true;
}
else
{
return false;
}
}
std::string State::getDefineString(const osg::ShaderDefines& shaderDefines)
{
if (_defineMap.changed) _defineMap.updateCurrentDefines();
const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
ShaderDefines::const_iterator sd_itr = shaderDefines.begin();
StateSet::DefineList::const_iterator cd_itr = currentDefines.begin();
std::string shaderDefineStr;
while(sd_itr != shaderDefines.end() && cd_itr != currentDefines.end())
{
if ((*sd_itr) < cd_itr->first) ++sd_itr;
else if (cd_itr->first < (*sd_itr)) ++cd_itr;
else
{
const StateSet::DefinePair& dp = cd_itr->second;
shaderDefineStr += "#define ";
shaderDefineStr += cd_itr->first;
if (cd_itr->second.first.empty())
{
shaderDefineStr += "\n";
}
else
{
shaderDefineStr += " ";
shaderDefineStr += cd_itr->second.first;
shaderDefineStr += "\n";
}
++sd_itr;
++cd_itr;
}
}
return shaderDefineStr;
}
bool State::supportsShaderRequirements(const osg::ShaderDefines& shaderRequirements)
{
if (shaderRequirements.empty()) return true;
if (_defineMap.changed) _defineMap.updateCurrentDefines();
const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
for(ShaderDefines::const_iterator sr_itr = shaderRequirements.begin();
sr_itr != shaderRequirements.end();
++sr_itr)
{
if (currentDefines.find(*sr_itr)==currentDefines.end()) return false;
}
return true;
}
bool State::supportsShaderRequirement(const std::string& shaderRequirement)
{
if (_defineMap.changed) _defineMap.updateCurrentDefines();
const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
return (currentDefines.find(shaderRequirement)!=currentDefines.end());
}

View File

@@ -178,6 +178,8 @@ StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop),
}
}
_defineList = rhs._defineList;
_renderingHint = rhs._renderingHint;
_binMode = rhs._binMode;
@@ -1129,6 +1131,27 @@ const StateSet::RefUniformPair* StateSet::getUniformPair(const std::string& name
else return 0;
}
void StateSet::setDefine(const std::string& defineName, StateAttribute::OverrideValue value)
{
DefinePair& dp = _defineList[defineName];
dp.first = "";
dp.second = value;
}
void StateSet::setDefine(const std::string& defineName, const std::string& defineValue, StateAttribute::OverrideValue value)
{
DefinePair& dp = _defineList[defineName];
dp.first = defineValue;
dp.second = value;
}
void StateSet::removeDefine(const std::string& defineName)
{
DefineList::iterator itr = _defineList.find(defineName);
if (itr != _defineList.end()) _defineList.erase(itr);
}
void StateSet::setTextureMode(unsigned int unit,StateAttribute::GLMode mode, StateAttribute::GLModeValue value)
{
if (getTextureGLModeSet().isTextureMode(mode))