From f6166d1119965e9f71f33ca38a0d792a83df8b8b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 9 Oct 2009 13:39:11 +0000 Subject: [PATCH] Introduced new uniforms for tracking the modelview and project matrices in shaders using non built-ins. --- .../osgvertexattributes.cpp | 41 ++++--- include/osg/State | 26 ++++- src/osg/Geometry.cpp | 101 ++++++++++++------ src/osg/State.cpp | 68 +++--------- src/osgUtil/RenderLeaf.cpp | 9 +- 5 files changed, 142 insertions(+), 103 deletions(-) diff --git a/examples/osgvertexattributes/osgvertexattributes.cpp b/examples/osgvertexattributes/osgvertexattributes.cpp index 2616f32b1..c8b5407ad 100644 --- a/examples/osgvertexattributes/osgvertexattributes.cpp +++ b/examples/osgvertexattributes/osgvertexattributes.cpp @@ -51,7 +51,7 @@ class ConvertToVertexAttibArrays : public osg::NodeVisitor program.addBindAttribLocation(alias.second, alias.first); } - void replaceAndBind(osg::Program& program, std::string& source, const std::string& originalStr, const AttributeAlias& alias, const std::string& declarationPrefix) + void replaceAndBindAttrib(osg::Program& program, std::string& source, const std::string& originalStr, const AttributeAlias& alias, const std::string& declarationPrefix) { if (replace(source, originalStr, alias.second)) { @@ -60,6 +60,14 @@ class ConvertToVertexAttibArrays : public osg::NodeVisitor } } + void replaceBuiltInUniform(std::string& source, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix) + { + if (replace(source, originalStr, newStr)) + { + source.insert(0, declarationPrefix + newStr + std::string(";\n")); + } + } + void convertVertexShader(osg::Program& program, osg::Shader& shader) { std::string source = shader.getShaderSource(); @@ -67,20 +75,20 @@ class ConvertToVertexAttibArrays : public osg::NodeVisitor // replace ftransform as it only works with built-ins replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex"); - replaceAndBind(program, source, "gl_Normal", _normalAlias, "attribute vec3 "); - replaceAndBind(program, source, "gl_Vertex", _vertexAlias, "attribute vec4 "); - replaceAndBind(program, source, "gl_Color", _colorAlias, "attribute vec4 "); - replaceAndBind(program, source, "gl_SecondaryColor", _secondaryColorAlias, "attribute vec4 "); - replaceAndBind(program, source, "gl_FogCoord", _fogCoordAlias, "attribute float "); + replaceAndBindAttrib(program, source, "gl_Normal", _normalAlias, "attribute vec3 "); + replaceAndBindAttrib(program, source, "gl_Vertex", _vertexAlias, "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_Color", _colorAlias, "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_SecondaryColor", _secondaryColorAlias, "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_FogCoord", _fogCoordAlias, "attribute float "); - replaceAndBind(program, source, "gl_MultiTexCoord0", _texCoordAlias[0], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord1", _texCoordAlias[1], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord2", _texCoordAlias[2], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord3", _texCoordAlias[3], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord4", _texCoordAlias[4], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord5", _texCoordAlias[5], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord6", _texCoordAlias[6], "attribute vec4 "); - replaceAndBind(program, source, "gl_MultiTexCoord7", _texCoordAlias[7], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord0", _texCoordAlias[0], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord1", _texCoordAlias[1], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord2", _texCoordAlias[2], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord3", _texCoordAlias[3], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord4", _texCoordAlias[4], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord5", _texCoordAlias[5], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord6", _texCoordAlias[6], "attribute vec4 "); + replaceAndBindAttrib(program, source, "gl_MultiTexCoord7", _texCoordAlias[7], "attribute vec4 "); #if 0 @@ -88,6 +96,11 @@ class ConvertToVertexAttibArrays : public osg::NodeVisitor replace(source, "gl_ModelViewMatrix", "osg_ModeViewMatrix"); replace(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix"); replace(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix"); +#else + // replace built in uniform + replaceBuiltInUniform(source, "gl_ModelViewMatrix", "osg_ModeViewMatrix", "uniform mat4 "); + replaceBuiltInUniform(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix", "uniform mat4 "); + replaceBuiltInUniform(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix", "uniform mat4 "); #endif shader.setShaderSource(source); } diff --git a/include/osg/State b/include/osg/State index 8f8d34619..3baaa917a 100644 --- a/include/osg/State +++ b/include/osg/State @@ -166,17 +166,20 @@ class OSG_EXPORT State : public Referenced, public Observer { if (_projection!=matrix) { - glMatrixMode( GL_PROJECTION ); if (matrix) { _projection=matrix; - glLoadMatrix(matrix->ptr()); } else { _projection=_identity; - glLoadIdentity(); } + + if (_projectionMatrixUniform.valid()) _projectionMatrixUniform->set(*_projection); + if (_modelViewProjectionMatrixUniform.valid()) _modelViewProjectionMatrixUniform->set((*_modelView) * (*_projection)); + + glMatrixMode( GL_PROJECTION ); + glLoadMatrix(_projection->ptr()); glMatrixMode( GL_MODELVIEW ); } } @@ -193,13 +196,16 @@ class OSG_EXPORT State : public Referenced, public Observer if (matrix) { _modelView=matrix; - glLoadMatrix(matrix->ptr()); } else { _modelView=_identity; - glLoadIdentity(); } + + if (_modelViewMatrixUniform.valid()) _modelViewMatrixUniform->set(*_modelView); + if (_modelViewProjectionMatrixUniform.valid()) _modelViewProjectionMatrixUniform->set((*_modelView) * (*_projection)); + + glLoadMatrix(_modelView->ptr()); } } @@ -208,6 +214,12 @@ class OSG_EXPORT State : public Referenced, public Observer return *_modelView; } + void applyModelViewAndProjectionUniformsIfRequired(); + + osg::Uniform* getModelViewMatrixUniform() { return _modelViewMatrixUniform.get(); } + osg::Uniform* getProjectionMatrixUniform() { return _projectionMatrixUniform.get(); } + osg::Uniform* getModelViewProjectionMatrixUniform() { return _modelViewProjectionMatrixUniform.get(); } + Polytope getViewFrustum() const; @@ -1088,6 +1100,10 @@ class OSG_EXPORT State : public Referenced, public Observer ref_ptr _projection; ref_ptr _modelView; + ref_ptr _modelViewMatrixUniform; + ref_ptr _projectionMatrixUniform; + ref_ptr _modelViewProjectionMatrixUniform; + Matrix _initialInverseViewMatrix; ref_ptr _displaySettings; diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 8aeac07f4..d9707b983 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -2114,7 +2114,16 @@ void Geometry::accept(AttributeFunctor& af) { AttributeFunctorArrayVisitor afav(af); - afav.applyArray(VERTICES,_vertexData.array.get()); + if (_vertexData.array.valid()) + { + afav.applyArray(VERTICES,_vertexData.array.get()); + } + else if (_vertexAttribList.size()>0) + { + osg::notify(osg::INFO)<<"Geometry::accept(AttributeFunctor& af): Using vertex attribute instead"<0) + { + osg::notify(osg::INFO)<<"Geometry::accept(ConstAttributeFunctor& af): Using vertex attribute instead"<getNumElements()==0) return; + const osg::Array* vertices = _vertexData.array.get(); + const osg::IndexArray* indices = _vertexData.indices.get(); - if (!_vertexData.indices.valid()) + if (!vertices && _vertexAttribList.size()>0) { - switch(_vertexData.array->getType()) + osg::notify(osg::INFO)<<"Using vertex attribute instead"<getNumElements()==0) return; + + if (!indices) + { + switch(vertices->getType()) { case(Array::Vec2ArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec3ArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec4ArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec2dArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec3dArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec4dArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; default: - notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<getType()<getType(); + Array::Type type = vertices->getType(); switch(type) { case(Array::Vec2ArrayType): - vec2Array = static_cast(_vertexData.array->getDataPointer()); + vec2Array = static_cast(vertices->getDataPointer()); break; case(Array::Vec3ArrayType): - vec3Array = static_cast(_vertexData.array->getDataPointer()); + vec3Array = static_cast(vertices->getDataPointer()); break; case(Array::Vec4ArrayType): - vec4Array = static_cast(_vertexData.array->getDataPointer()); + vec4Array = static_cast(vertices->getDataPointer()); break; case(Array::Vec2dArrayType): - vec2dArray = static_cast(_vertexData.array->getDataPointer()); + vec2dArray = static_cast(vertices->getDataPointer()); break; case(Array::Vec3dArrayType): - vec3dArray = static_cast(_vertexData.array->getDataPointer()); + vec3dArray = static_cast(vertices->getDataPointer()); break; case(Array::Vec4dArrayType): - vec4dArray = static_cast(_vertexData.array->getDataPointer()); + vec4dArray = static_cast(vertices->getDataPointer()); break; default: - notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<getType()<getNumElements()==0) return; + const osg::Array* vertices = _vertexData.array.get(); + const osg::IndexArray* indices = _vertexData.indices.get(); - switch(_vertexData.array->getType()) + if (!vertices && _vertexAttribList.size()>0) + { + osg::notify(osg::INFO)<<"Geometry::accept(PrimitiveIndexFunctor& functor): Using vertex attribute instead"<getNumElements()==0) return; + + switch(vertices->getType()) { case(Array::Vec2ArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec3ArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec4ArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec2dArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec3dArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; case(Array::Vec4dArrayType): - functor.setVertexArray(_vertexData.array->getNumElements(),static_cast(_vertexData.array->getDataPointer())); + functor.setVertexArray(vertices->getNumElements(),static_cast(vertices->getDataPointer())); break; default: - notify(WARN)<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<getType()<getUniformList()); -#else - if (_lastAppliedProgramObject) - { - for(StateSetStack::iterator sitr=_stateStateStack.begin(); - sitr!=_stateStateStack.end(); - ++sitr) - { - const StateSet* stateset = *sitr; - const StateSet::UniformList& uniformList = stateset->getUniformList(); - for(StateSet::UniformList::const_iterator itr=uniformList.begin(); - itr!=uniformList.end(); - ++itr) - { - _lastAppliedProgramObject->apply(*(itr->second.first)); - } - } - - const StateSet::UniformList& uniformList = dstate->getUniformList(); - for(StateSet::UniformList::const_iterator itr=uniformList.begin(); - itr!=uniformList.end(); - ++itr) - { - _lastAppliedProgramObject->apply(*(itr->second.first)); - } - } -#endif - } else { @@ -508,27 +486,7 @@ void State::apply() } } -#if 1 applyUniformMap(_uniformMap); -#else - if (_lastAppliedProgramObject && !_stateStateStack.empty()) - { - for(StateSetStack::iterator sitr=_stateStateStack.begin(); - sitr!=_stateStateStack.end(); - ++sitr) - { - const StateSet* stateset = *sitr; - const StateSet::UniformList& uniformList = stateset->getUniformList(); - for(StateSet::UniformList::const_iterator itr=uniformList.begin(); - itr!=uniformList.end(); - ++itr) - { - _lastAppliedProgramObject->apply(*(itr->second.first)); - } - } - } -#endif - if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()"); } @@ -1033,3 +991,11 @@ bool State::checkGLErrors(const StateAttribute* attribute) const } +void State::applyModelViewAndProjectionUniformsIfRequired() +{ + if (!_lastAppliedProgramObject) return; + + if (_modelViewMatrixUniform.valid()) _lastAppliedProgramObject->apply(*_modelViewMatrixUniform); + if (_projectionMatrixUniform) _lastAppliedProgramObject->apply(*_projectionMatrixUniform); + if (_modelViewProjectionMatrixUniform) _lastAppliedProgramObject->apply(*_modelViewProjectionMatrixUniform); +} diff --git a/src/osgUtil/RenderLeaf.cpp b/src/osgUtil/RenderLeaf.cpp index ebebd2891..65d63b485 100644 --- a/src/osgUtil/RenderLeaf.cpp +++ b/src/osgUtil/RenderLeaf.cpp @@ -54,7 +54,10 @@ void RenderLeaf::render(osg::RenderInfo& renderInfo,RenderLeaf* previous) state.apply(rg->getStateSet()); } - + + // if we are using osg::Program which requires OSG's generated uniforms to track + // modelview and projection matrices then apply them now. + state.applyModelViewAndProjectionUniformsIfRequired(); // draw the drawable _drawable->draw(renderInfo); @@ -70,6 +73,10 @@ void RenderLeaf::render(osg::RenderInfo& renderInfo,RenderLeaf* previous) state.apply(_parent->getStateSet()); + // if we are using osg::Program which requires OSG's generated uniforms to track + // modelview and projection matrices then apply them now. + state.applyModelViewAndProjectionUniformsIfRequired(); + // draw the drawable _drawable->draw(renderInfo); }