From 74ae526bb52368f11fda3612a722293ce904db64 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 6 Jul 2010 10:55:54 +0000 Subject: [PATCH] Added support for passing on uniforms from StateAttribute --- .../osgshadercomposition.cpp | 64 ++++++++++++------- include/osg/State | 12 ++++ src/osg/ShaderAttribute.cpp | 9 ++- src/osg/ShaderComposer.cpp | 2 +- src/osg/State.cpp | 42 ++++++++++-- 5 files changed, 100 insertions(+), 29 deletions(-) diff --git a/examples/osgshadercomposition/osgshadercomposition.cpp b/examples/osgshadercomposition/osgshadercomposition.cpp index 832329f4d..47026662a 100644 --- a/examples/osgshadercomposition/osgshadercomposition.cpp +++ b/examples/osgshadercomposition/osgshadercomposition.cpp @@ -19,41 +19,61 @@ #include #include #include +#include osg::Node* createSceneGraph(osg::ArgumentParser& arguments) { osg::Node* node = osgDB::readNodeFiles(arguments); if (!node) return 0; - osg::StateSet* stateset = node->getOrCreateStateSet(); - osg::ShaderAttribute* sa = new osg::ShaderAttribute; - stateset->setAttribute(sa); + osg::Group* group = new osg::Group; + double spacing = node->getBound().radius() * 2.0; + + osg::Vec3d position(0.0,0.0,0.0); { - const char shader_str[] = - "vec4 colour()\n" - "{\n" - " return vec4(1.0,0.5,1.0,1.0);\n" - "}\n"; + osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; + pat->setPosition(position); + pat->addChild(node); - osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, shader_str); - vertex_shader->addCodeInjection(-1,"varying vec4 c;\n"); - vertex_shader->addCodeInjection(-1,"vec4 colour();\n"); - vertex_shader->addCodeInjection(0,"gl_Position = ftransform();\n"); - vertex_shader->addCodeInjection(0,"c = colour();\n"); + position.x() += spacing; - sa->addShader(vertex_shader); - } + osg::StateSet* stateset = pat->getOrCreateStateSet(); + osg::ShaderAttribute* sa = new osg::ShaderAttribute; + stateset->setAttribute(sa); - { - osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); - fragment_shader->addCodeInjection(-1,"varying vec4 c;\n"); - fragment_shader->addCodeInjection(0,"gl_FragColor = c;\n"); + { + const char shader_str[] = + "uniform vec4 myColour;\n" + "vec4 colour()\n" + "{\n" + " return myColour;\n" + "}\n"; - sa->addShader(fragment_shader); - } + osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, shader_str); + vertex_shader->addCodeInjection(-1,"varying vec4 c;\n"); + vertex_shader->addCodeInjection(-1,"vec4 colour();\n"); + vertex_shader->addCodeInjection(0,"gl_Position = ftransform();\n"); + vertex_shader->addCodeInjection(0,"c = colour();\n"); - return node; + sa->addUniform(new osg::Uniform("myColour",osg::Vec4(1.0f,0.5f,0.0f,1.0f))); + + sa->addShader(vertex_shader); + } + + { + osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); + fragment_shader->addCodeInjection(-1,"varying vec4 c;\n"); + fragment_shader->addCodeInjection(0,"gl_FragColor = c;\n"); + + sa->addShader(fragment_shader); + } + + group->addChild(pat); + + } + + return group; } int main( int argc, char **argv ) diff --git a/include/osg/State b/include/osg/State index d081deb43..cf22d5f2a 100644 --- a/include/osg/State +++ b/include/osg/State @@ -157,6 +157,17 @@ class OSG_EXPORT State : public Referenced, public Observer /** Get the const ShaderComposor object.*/ const ShaderComposer* getShaderComposer() const { return _shaderComposer.get(); } + /** Get the unform list in which to inject any uniforms that StateAttribute::apply(State&) methods provide.*/ + StateSet::UniformList& getCurrentShaderCompositionUniformList() { return _currentShaderCompositionUniformList; } + + /** Convinience method for StateAttribute:::apply(State&) methods to pass on their uniforms to osg::State so it can apply them at the appropriate point.*/ + void applyShaderCompositionUniform(const osg::Uniform* uniform, StateAttribute::OverrideValue value=StateAttribute::ON) + { + StateSet::RefUniformPair& up = _currentShaderCompositionUniformList[uniform->getName()]; + up.first = const_cast(uniform); + up.second = value; + } + /** Push stateset onto state stack.*/ void pushStateSet(const StateSet* dstate); @@ -1364,6 +1375,7 @@ class OSG_EXPORT State : public Referenced, public Observer bool _shaderCompositionDirty; osg::ref_ptr _shaderComposer; osg::Program* _currentShaderCompositionProgram; + StateSet::UniformList _currentShaderCompositionUniformList; ref_ptr _frameStamp; diff --git a/src/osg/ShaderAttribute.cpp b/src/osg/ShaderAttribute.cpp index b082dc122..da7847da8 100644 --- a/src/osg/ShaderAttribute.cpp +++ b/src/osg/ShaderAttribute.cpp @@ -13,6 +13,8 @@ #include #include +#include +#include using namespace osg; @@ -78,7 +80,12 @@ bool ShaderAttribute::getModeUsage(StateAttribute::ModeUsage& usage) const void ShaderAttribute::apply(State& state) const { - OSG_NOTICE<<"ShaderAttribute::apply(..)"<get()); + } } void ShaderAttribute::compose(ShaderComposer& composer) const diff --git a/src/osg/ShaderComposer.cpp b/src/osg/ShaderComposer.cpp index aef3238e2..6583142c5 100644 --- a/src/osg/ShaderComposer.cpp +++ b/src/osg/ShaderComposer.cpp @@ -37,7 +37,7 @@ osg::Program* ShaderComposer::getOrCreateProgram(const ShaderComponents& shaderC ProgramMap::iterator itr = _programMap.find(shaderComponents); if (itr != _programMap.end()) { - OSG_NOTICE<<"ShaderComposer::getOrCreateProgram(..) using cached Program"<second.get(); } diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 887b90e12..5157cf016 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -495,6 +495,7 @@ void State::apply(const StateSet* dstate) if (dstate) { + _currentShaderCompositionUniformList.clear(); applyModeList(_modeMap,dstate->getModeList()); applyAttributeList(_attributeMap,dstate->getAttributeList()); @@ -515,9 +516,32 @@ void State::apply(const StateSet* dstate) else if (unit<_textureAttributeMapList.size()) applyAttributeMapOnTexUnit(unit,_textureAttributeMapList[unit]); } - applyShaderComposition(); + if (_shaderCompositionEnabled) + { + applyShaderComposition(); + + if (dstate->getUniformList().empty()) + { + if (_currentShaderCompositionUniformList.empty()) applyUniformMap(_uniformMap); + else applyUniformList(_uniformMap, _currentShaderCompositionUniformList); + } + else + { + if (_currentShaderCompositionUniformList.empty()) applyUniformList(_uniformMap, dstate->getUniformList()); + else + { + // need top merge uniforms lists, but cheat for now by just applying both. + _currentShaderCompositionUniformList.insert(dstate->getUniformList().begin(), dstate->getUniformList().end()); + applyUniformList(_uniformMap, _currentShaderCompositionUniformList); + } + } + + } + else + { + applyUniformList(_uniformMap,dstate->getUniformList()); + } - applyUniformList(_uniformMap,dstate->getUniformList()); } else { @@ -533,6 +557,8 @@ void State::apply() if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply()"); + if (_shaderCompositionEnabled) _currentShaderCompositionUniformList.clear(); + // go through all active OpenGL modes, enabling/disable where // appropriate. applyModeMap(_modeMap); @@ -548,9 +574,15 @@ void State::apply() if (unit<_textureAttributeMapList.size()) applyAttributeMapOnTexUnit(unit,_textureAttributeMapList[unit]); } - applyShaderComposition(); - - applyUniformMap(_uniformMap); + if (_shaderCompositionEnabled) + { + applyShaderComposition(); + applyUniformList(_uniformMap, _currentShaderCompositionUniformList); + } + else + { + applyUniformMap(_uniformMap); + } if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()"); }