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

@@ -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());
}