From d1222fc2ef21c166058899ebeb7037d41535a8ad Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 1 Nov 2016 10:15:11 +0000 Subject: [PATCH] Added fallback textures to handle cases where no texture is provided --- .../osgshaderpipeline/osgshaderpipeline.cpp | 28 ++++- include/osg/State | 3 + src/osg/State.cpp | 101 ++++++++++++++++-- 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/examples/osgshaderpipeline/osgshaderpipeline.cpp b/examples/osgshaderpipeline/osgshaderpipeline.cpp index e52a005a5..c427b7687 100644 --- a/examples/osgshaderpipeline/osgshaderpipeline.cpp +++ b/examples/osgshaderpipeline/osgshaderpipeline.cpp @@ -10,6 +10,7 @@ */ #include + #include #include @@ -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(image->data())) = 0xffffffff; + return image; +} + int main(int argc, char** argv) { // use an ArgumentParser object to manage the program arguments. @@ -82,6 +92,9 @@ int main(int argc, char** argv) return 1; } + unsigned int maxTextureUnits = 1; + while(arguments.read("--units", maxTextureUnits)) {} + // assign program to topmost StateSet viewer.getCamera()->getOrCreateStateSet()->setAttribute(program); @@ -97,7 +110,6 @@ int main(int argc, char** argv) osg::ref_ptr stateset = viewer.getCamera()->getOrCreateStateSet(); - unsigned int maxTextureUnits = 1; std::stringstream sstream; sstream<setDefine("GL_MAX_TEXTURE_UNITS", sstream.str()); @@ -109,6 +121,18 @@ int main(int argc, char** argv) if (maxTextureUnits>0) { + osg::ref_ptr 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; isetTextureAttribute(i, fallbackTexture.get()); + } + + ADD_DEFINE(GL_EYE_LINEAR); ADD_DEFINE(GL_OBJECT_LINEAR); ADD_DEFINE(GL_SPHERE_MAP); @@ -155,7 +179,7 @@ int main(int argc, char** argv) sstream.str(""); sstream<<"sampler"<addUniform(new osg::Uniform(sstream.str().c_str(), i)); + stateset->addUniform(new osg::Uniform(sstream.str().c_str(), static_cast(i))); // fragment shader texture defines diff --git a/include/osg/State b/include/osg/State index 7a9c33021..9c64ab862 100644 --- a/include/osg/State +++ b/include/osg/State @@ -882,6 +882,7 @@ class OSG_EXPORT State : public Referenced CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; } 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(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) { 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) { diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 19575d280..ab6ed677f 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -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 (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap); @@ -810,12 +812,95 @@ void State::apply() applyShaderComposition(); } + if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("after attributes State::apply()"); + if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap); else applyUniformList(_uniformMap, _currentShaderCompositionUniformList); 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->firstfirst) + { + // 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->firstfirst) + { + _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() { if (_shaderCompositionEnabled) @@ -1154,6 +1239,10 @@ unsigned int State::getClientActiveTextureUnit() const 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 { @@ -1739,12 +1828,12 @@ void State::getDefineString(std::string& shaderDefineStr, const osg::ShaderPragm StringModeMap::iterator m_itr = _stringModeMap.find(modeStr); if (m_itr!=_stringModeMap.end()) { - OSG_NOTICE<<"Look up mode ["<second; if (mode>=GL_TEXTURE0 && mode<=(GL_TEXTURE0+15)) { - OSG_NOTICE<<" Need to map GL_TEXTUREi"<second.last_applied_value; if (mode_enabled) { - OSG_NOTICE<<" mapping mode to #define "<second; ModeMap::const_iterator mm_itr = modeMap.find(mode); 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; if (mode_enabled) { - OSG_NOTICE<<" mapping mode to #define "<