diff --git a/include/osg/StateSet b/include/osg/StateSet index ff31ac029..b8aa6445c 100644 --- a/include/osg/StateSet +++ b/include/osg/StateSet @@ -307,6 +307,9 @@ class OSG_EXPORT StateSet : public Object * Returns NULL if no matching Uniform is contained within StateSet.*/ Uniform* getUniform(const std::string& name); + /** Get Uniform for specified name, if one is not available create it, add it to this StateSet and return a pointer to it.*/ + Uniform* getOrCreateUniform(const std::string& name, Uniform::Type type); + /** Get const Uniform for specified name. * Returns NULL if no matching Uniform is contained within StateSet.*/ const Uniform* getUniform(const std::string& name) const; diff --git a/include/osg/Uniform b/include/osg/Uniform index c44d1cff7..811e72768 100644 --- a/include/osg/Uniform +++ b/include/osg/Uniform @@ -153,7 +153,7 @@ class OSG_EXPORT Uniform : public Object public: Uniform(); - Uniform( const char* name, Type type ); + Uniform( const std::string& name, Type type ); /** Copy constructor using CopyOp to manage deep vs shallow copy. */ Uniform(const Uniform& rhs, const CopyOp& copyop=CopyOp::SHALLOW_COPY); diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index b55866e5f..f08dee03c 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -123,7 +123,6 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSetting const osg::Vec4& getClearColor() const { return _clearColor; } - void setGlobalStateSet(osg::StateSet* state) { _globalStateSet = state; } osg::StateSet* getGlobalStateSet() { return _globalStateSet.get(); } const osg::StateSet* getGlobalStateSet() const { return _globalStateSet.get(); } @@ -131,6 +130,28 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSetting void setLocalStateSet(osg::StateSet* state) { _localStateSet = state; } osg::StateSet* getLocalStateSet() { return _localStateSet.get(); } const osg::StateSet* getLocalStateSet() const { return _localStateSet.get(); } + + enum ActiveUniforms + { + FRAME_NUMBER_UNIFORM = 0x1, + FRAME_TIME_UNIFORM = 0x2, + VIEW_MATRIX_UNIFORM = 0x4, + INVERSE_VIEW_MATRIX_UNIFORM = 0x8, + DEFAULT_UNIFORMS = FRAME_NUMBER_UNIFORM | + FRAME_TIME_UNIFORM | + VIEW_MATRIX_UNIFORM | + INVERSE_VIEW_MATRIX_UNIFORM, + ALL_UNIFORMS = 0xFFFFFFFF + }; + + /** Set the uniforms that SceneView should set set up on each frame.*/ + void setActiveUniforms(int activeUniforms) { _activeUniforms = activeUniforms; } + + /** Set the uniforms that SceneView should set set up on each frame.*/ + int getActiveUniforms(int activeUniforms) const { return _activeUniforms; } + + void updateUniforms(); + typedef Options LightingMode; @@ -486,6 +507,8 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSetting bool _requiresFlush; + int _activeUniforms; + }; } diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp index 79ea1f47f..eb178ce75 100644 --- a/src/osg/StateSet.cpp +++ b/src/osg/StateSet.cpp @@ -923,6 +923,25 @@ Uniform* StateSet::getUniform(const std::string& name) else return 0; } +Uniform* StateSet::getOrCreateUniform(const std::string& name, Uniform::Type type) +{ + // for look for an appropriate uniform. + UniformList::iterator itr = _uniformList.find(name); + if (itr!=_uniformList.end() && + itr->second.first->getType()==type) + { + return itr->second.first.get(); + } + + // no uniform found matching name so create it.. + + Uniform* uniform = new Uniform(name,type); + addUniform(uniform); + + return uniform; +} + + const Uniform* StateSet::getUniform(const std::string& name) const { UniformList::const_iterator itr = _uniformList.find(name); diff --git a/src/osg/Uniform.cpp b/src/osg/Uniform.cpp index 70ff01e60..925d9173f 100644 --- a/src/osg/Uniform.cpp +++ b/src/osg/Uniform.cpp @@ -34,7 +34,7 @@ Uniform::Uniform() : } -Uniform::Uniform( const char* name, Type type ) : +Uniform::Uniform( const std::string& name, Type type ) : _name(name), _type(type),_modifiedCount(0) { setDataVariance(STATIC); @@ -89,6 +89,8 @@ void Uniform::removeParent(osg::StateSet* object) bool Uniform::setType( Type t ) { + if (_type==t) return true; + if( _type != UNDEFINED ) { osg::notify(osg::WARN) << "cannot change Uniform type" << std::endl; @@ -721,6 +723,7 @@ bool Uniform::get( bool& b0, bool& b1, bool& b2, bool& b3 ) const void Uniform::apply(const GL2Extensions* ext, GLint location) const { + // osg::notify(osg::NOTICE) << "uniform at "<reset(); @@ -188,8 +185,41 @@ void SceneView::update() // multi-threaded. _sceneData->getBound(); } +} + +void SceneView::updateUniforms() +{ + if (!_localStateSet) + { + _localStateSet = new osg::StateSet; + } + + if (!_localStateSet) return; + if ((_activeUniforms & FRAME_NUMBER_UNIFORM) && _frameStamp.valid()) + { + osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_FrameNumber",osg::Uniform::INT); + uniform->set(_frameStamp->getFrameNumber()); + } + if ((_activeUniforms & FRAME_TIME_UNIFORM) && _frameStamp.valid()) + { + osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_FrameTime",osg::Uniform::FLOAT); + uniform->set(static_cast(_frameStamp->getReferenceTime())); + } + + if (_activeUniforms & VIEW_MATRIX_UNIFORM) + { + osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_ViewMatrix",osg::Uniform::FLOAT_MAT4); + uniform->set(_viewMatrix); + } + + if (_activeUniforms & INVERSE_VIEW_MATRIX_UNIFORM) + { + osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_InverseViewMatrix",osg::Uniform::FLOAT_MAT4); + uniform->set(osg::Matrix::inverse(_viewMatrix)); + } + } osg::Matrixd SceneView::computeLeftEyeProjectionImplementation(const osg::Matrixd& projection) const @@ -324,6 +354,8 @@ osg::Matrixd SceneView::computeRightEyeViewImplementation(const osg::Matrixd& vi void SceneView::cull() { + // update the active uniforms + updateUniforms(); if (!_state) {