Added fallback textures to handle cases where no texture is provided

This commit is contained in:
Robert Osfield 2016-11-01 10:15:11 +00:00
parent 0bcfa8d980
commit d1222fc2ef
3 changed files with 124 additions and 8 deletions

View File

@ -10,6 +10,7 @@
*/ */
#include <osg/TexGen> #include <osg/TexGen>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/WriteFile> #include <osgDB/WriteFile>
@ -55,6 +56,15 @@ bool readShaderArguments(osg::ArgumentParser& arguments, const std::string& opti
} }
} }
osg::Image* createFallbackImage()
{
osg::Image* image = new osg::Image;
image->allocateImage(1,1,1,GL_RGBA, GL_UNSIGNED_BYTE);
//image->setColor(osg::Vec4(1.0,1.0,0.0,1.0), 0, 0, 0);
*(reinterpret_cast<unsigned int*>(image->data())) = 0xffffffff;
return image;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
// use an ArgumentParser object to manage the program arguments. // use an ArgumentParser object to manage the program arguments.
@ -82,6 +92,9 @@ int main(int argc, char** argv)
return 1; return 1;
} }
unsigned int maxTextureUnits = 1;
while(arguments.read("--units", maxTextureUnits)) {}
// assign program to topmost StateSet // assign program to topmost StateSet
viewer.getCamera()->getOrCreateStateSet()->setAttribute(program); viewer.getCamera()->getOrCreateStateSet()->setAttribute(program);
@ -97,7 +110,6 @@ int main(int argc, char** argv)
osg::ref_ptr<osg::StateSet> stateset = viewer.getCamera()->getOrCreateStateSet(); osg::ref_ptr<osg::StateSet> stateset = viewer.getCamera()->getOrCreateStateSet();
unsigned int maxTextureUnits = 1;
std::stringstream sstream; std::stringstream sstream;
sstream<<maxTextureUnits; sstream<<maxTextureUnits;
stateset->setDefine("GL_MAX_TEXTURE_UNITS", sstream.str()); stateset->setDefine("GL_MAX_TEXTURE_UNITS", sstream.str());
@ -109,6 +121,18 @@ int main(int argc, char** argv)
if (maxTextureUnits>0) if (maxTextureUnits>0)
{ {
osg::ref_ptr<osg::Texture2D> fallbackTexture = new osg::Texture2D(createFallbackImage());
fallbackTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
fallbackTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
fallbackTexture->setWrap(osg::Texture2D::WRAP_R, osg::Texture2D::CLAMP_TO_EDGE);
fallbackTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
fallbackTexture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
for(unsigned int i=0; i<maxTextureUnits;++i)
{
stateset->setTextureAttribute(i, fallbackTexture.get());
}
ADD_DEFINE(GL_EYE_LINEAR); ADD_DEFINE(GL_EYE_LINEAR);
ADD_DEFINE(GL_OBJECT_LINEAR); ADD_DEFINE(GL_OBJECT_LINEAR);
ADD_DEFINE(GL_SPHERE_MAP); ADD_DEFINE(GL_SPHERE_MAP);
@ -155,7 +179,7 @@ int main(int argc, char** argv)
sstream.str(""); sstream.str("");
sstream<<"sampler"<<i; sstream<<"sampler"<<i;
OSG_NOTICE<<"****** texture unit : "<<sstream.str()<<std::endl; OSG_NOTICE<<"****** texture unit : "<<sstream.str()<<std::endl;
stateset->addUniform(new osg::Uniform(sstream.str().c_str(), i)); stateset->addUniform(new osg::Uniform(sstream.str().c_str(), static_cast<int>(i)));
// fragment shader texture defines // fragment shader texture defines

View File

@ -882,6 +882,7 @@ class OSG_EXPORT State : public Referenced
CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; } CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
bool checkGLErrors(const char* str1=0, const char* str2=0) const; bool checkGLErrors(const char* str1=0, const char* str2=0) const;
bool checkGLErrors(const std::string& str) const;
bool checkGLErrors(StateAttribute::GLMode mode) const; bool checkGLErrors(StateAttribute::GLMode mode) const;
bool checkGLErrors(const StateAttribute* attribute) const; bool checkGLErrors(const StateAttribute* attribute) const;
@ -2043,6 +2044,7 @@ inline void State::applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& a
} }
#if 0
inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList) inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
{ {
if (!_lastAppliedProgramObject) return; if (!_lastAppliedProgramObject) return;
@ -2116,6 +2118,7 @@ inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::Unifo
} }
} }
#endif
inline void State::applyDefineList(DefineMap& defineMap, const StateSet::DefineList& defineList) inline void State::applyDefineList(DefineMap& defineMap, const StateSet::DefineList& defineList)
{ {

View File

@ -738,6 +738,8 @@ void State::apply(const StateSet* dstate)
} }
} }
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("after attributes State::apply()");
if (dstate->getUniformList().empty()) if (dstate->getUniformList().empty())
{ {
if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap); if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap);
@ -810,12 +812,95 @@ void State::apply()
applyShaderComposition(); applyShaderComposition();
} }
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("after attributes State::apply()");
if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap); if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap);
else applyUniformList(_uniformMap, _currentShaderCompositionUniformList); else applyUniformList(_uniformMap, _currentShaderCompositionUniformList);
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()"); if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()");
} }
#if 1
void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
{
if (!_lastAppliedProgramObject) return;
StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
UniformMap::iterator this_aitr=uniformMap.begin();
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)");
while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
{
if (this_aitr->first<ds_aitr->first)
{
// note attribute type = this_aitr->first
UniformStack& as = this_aitr->second;
if (!as.uniformVec.empty())
{
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
}
++this_aitr;
}
else if (ds_aitr->first<this_aitr->first)
{
_lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
++ds_aitr;
}
else
{
// this_mitr & ds_mitr refer to the same attribute, check the override
// if any otherwise just apply the incoming attribute
UniformStack& as = this_aitr->second;
if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
{
// override is on, just treat as a normal apply on uniform.
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
}
else
{
// no override on or no previous entry, therefore consider incoming attribute.
_lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
}
++this_aitr;
++ds_aitr;
}
}
// iterator over the remaining state attributes to apply any previous changes.
for(;
this_aitr!=uniformMap.end();
++this_aitr)
{
// note attribute type = this_aitr->first
UniformStack& as = this_aitr->second;
if (!as.uniformVec.empty())
{
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.uniformVec.back().first->getName());
}
}
// iterator over the remaining incoming attribute to apply any new attribute.
for(;
ds_aitr!=uniformList.end();
++ds_aitr)
{
_lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(ds_aitr->second.first->getName());
}
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("after of State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)");
}
#endif
void State::applyShaderComposition() void State::applyShaderComposition()
{ {
if (_shaderCompositionEnabled) if (_shaderCompositionEnabled)
@ -1154,6 +1239,10 @@ unsigned int State::getClientActiveTextureUnit() const
return _currentClientActiveTextureUnit; return _currentClientActiveTextureUnit;
} }
bool State::checkGLErrors(const std::string& str) const
{
return checkGLErrors(str.c_str());
}
bool State::checkGLErrors(const char* str1, const char* str2) const bool State::checkGLErrors(const char* str1, const char* str2) const
{ {
@ -1739,12 +1828,12 @@ void State::getDefineString(std::string& shaderDefineStr, const osg::ShaderPragm
StringModeMap::iterator m_itr = _stringModeMap.find(modeStr); StringModeMap::iterator m_itr = _stringModeMap.find(modeStr);
if (m_itr!=_stringModeMap.end()) if (m_itr!=_stringModeMap.end())
{ {
OSG_NOTICE<<"Look up mode ["<<modeStr<<"]"<<std::endl; // OSG_NOTICE<<"Look up mode ["<<modeStr<<"]"<<std::endl;
StateAttribute::GLMode mode = m_itr->second; StateAttribute::GLMode mode = m_itr->second;
if (mode>=GL_TEXTURE0 && mode<=(GL_TEXTURE0+15)) if (mode>=GL_TEXTURE0 && mode<=(GL_TEXTURE0+15))
{ {
OSG_NOTICE<<" Need to map GL_TEXTUREi"<<std::endl; // OSG_NOTICE<<" Need to map GL_TEXTUREi"<<std::endl;
} }
else else
{ {
@ -1754,7 +1843,7 @@ void State::getDefineString(std::string& shaderDefineStr, const osg::ShaderPragm
bool mode_enabled = mm_itr->second.last_applied_value; bool mode_enabled = mm_itr->second.last_applied_value;
if (mode_enabled) if (mode_enabled)
{ {
OSG_NOTICE<<" mapping mode to #define "<<modeStr<<std::endl; // OSG_NOTICE<<" mapping mode to #define "<<modeStr<<std::endl;
shaderDefineStr += "#define "; shaderDefineStr += "#define ";
shaderDefineStr += modeStr; shaderDefineStr += modeStr;
shaderDefineStr += s_LineEnding; shaderDefineStr += s_LineEnding;
@ -1779,7 +1868,7 @@ void State::getDefineString(std::string& shaderDefineStr, const osg::ShaderPragm
StringModeMap::iterator m_itr = _stringModeMap.find(modeStr); StringModeMap::iterator m_itr = _stringModeMap.find(modeStr);
if (m_itr!=_stringModeMap.end()) if (m_itr!=_stringModeMap.end())
{ {
OSG_NOTICE<<"Need to look up mode ["<<modeStr<<"]"<<std::endl; // OSG_NOTICE<<"Need to look up mode ["<<modeStr<<"]"<<std::endl;
StateAttribute::GLMode mode = m_itr->second; StateAttribute::GLMode mode = m_itr->second;
ModeMap::const_iterator mm_itr = modeMap.find(mode); ModeMap::const_iterator mm_itr = modeMap.find(mode);
if (mm_itr!=modeMap.end()) if (mm_itr!=modeMap.end())
@ -1787,7 +1876,7 @@ void State::getDefineString(std::string& shaderDefineStr, const osg::ShaderPragm
bool mode_enabled = mm_itr->second.last_applied_value; bool mode_enabled = mm_itr->second.last_applied_value;
if (mode_enabled) if (mode_enabled)
{ {
OSG_NOTICE<<" mapping mode to #define "<<modeStr<<std::endl; // OSG_NOTICE<<" mapping mode to #define "<<modeStr<<std::endl;
shaderDefineStr += "#define "; shaderDefineStr += "#define ";
shaderDefineStr += modeStr; shaderDefineStr += modeStr;
shaderDefineStr += s_LineEnding; shaderDefineStr += s_LineEnding;
@ -1802,7 +1891,7 @@ void State::getDefineString(std::string& shaderDefineStr, const osg::ShaderPragm
} }
OSG_NOTICE<<"State::getDefineString(..) "<<shaderDefineStr<<std::endl; // OSG_NOTICE<<"State::getDefineString(..) "<<shaderDefineStr<<std::endl;
} }
bool State::supportsShaderRequirements(const osg::ShaderPragmas& shaderPragmas) bool State::supportsShaderRequirements(const osg::ShaderPragmas& shaderPragmas)