Added support for passing on uniforms from StateAttribute

This commit is contained in:
Robert Osfield 2010-07-06 10:55:54 +00:00
parent 751b0498fe
commit 74ae526bb5
5 changed files with 100 additions and 29 deletions

View File

@ -19,41 +19,61 @@
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/ShaderAttribute>
#include <osg/PositionAttitudeTransform>
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 )

View File

@ -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*>(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> _shaderComposer;
osg::Program* _currentShaderCompositionProgram;
StateSet::UniformList _currentShaderCompositionUniformList;
ref_ptr<FrameStamp> _frameStamp;

View File

@ -13,6 +13,8 @@
#include <osg/ShaderAttribute>
#include <osg/Notify>
#include <osg/StateSet>
#include <osg/State>
using namespace osg;
@ -78,7 +80,12 @@ bool ShaderAttribute::getModeUsage(StateAttribute::ModeUsage& usage) const
void ShaderAttribute::apply(State& state) const
{
OSG_NOTICE<<"ShaderAttribute::apply(..)"<<std::endl;
for(Uniforms::const_iterator itr = _uniforms.begin();
itr != _uniforms.end();
++itr)
{
state.applyShaderCompositionUniform(itr->get());
}
}
void ShaderAttribute::compose(ShaderComposer& composer) const

View File

@ -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"<<std::endl;
// OSG_NOTICE<<"ShaderComposer::getOrCreateProgram(..) using cached Program"<<std::endl;
return itr->second.get();
}

View File

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