osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/ShaderUtils.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 #include <osgEarth/ShaderUtils>
00020 #include <osgEarth/Registry>
00021 #include <list>
00022 
00023 using namespace osgEarth;
00024 
00025 //------------------------------------------------------------------------
00026 
00027 namespace 
00028 {
00029     typedef std::list<const osg::StateSet*> StateSetStack;
00030 
00031     static osg::StateAttribute::GLModeValue 
00032     getModeValue(const StateSetStack& statesetStack, osg::StateAttribute::GLMode mode)
00033     {
00034         osg::StateAttribute::GLModeValue base_val = osg::StateAttribute::ON;
00035         for(StateSetStack::const_iterator itr = statesetStack.begin();
00036             itr != statesetStack.end();
00037             ++itr)
00038         {
00039             osg::StateAttribute::GLModeValue val = (*itr)->getMode(mode);
00040             if ((val & ~osg::StateAttribute::INHERIT)!=0)
00041             {
00042                 if ((val & osg::StateAttribute::PROTECTED)!=0 ||
00043                     (base_val & osg::StateAttribute::OVERRIDE)==0)
00044                 {
00045                     base_val = val;
00046                 }
00047             }
00048         }
00049         return base_val;
00050     }
00051 }
00052 
00053 //------------------------------------------------------------------------
00054 
00055 #undef LC
00056 #define LC "[UpdateLightingUniformHelper] "
00057 
00058 UpdateLightingUniformsHelper::UpdateLightingUniformsHelper( bool useUpdateTrav ) :
00059 _lightingEnabled( true ),
00060 _dirty( true ),
00061 _applied( false ),
00062 _useUpdateTrav( useUpdateTrav )
00063 {
00064     _maxLights = Registry::instance()->getCapabilities().getMaxLights();
00065 
00066     _lightEnabled = new bool[ _maxLights ];
00067     if ( _maxLights > 0 )
00068         _lightEnabled[0] = 1;
00069     for(int i=1; i<_maxLights; ++i )
00070         _lightEnabled[i] = 0;
00071 
00072     _lightingEnabledUniform = new osg::Uniform( osg::Uniform::BOOL, "osgearth_LightingEnabled" );
00073     _lightEnabledUniform    = new osg::Uniform( osg::Uniform::INT,  "osgearth_LightEnabled", _maxLights );
00074 
00075     if ( !_useUpdateTrav )
00076     {
00077         // setting the data variance the DYNAMIC makes it safe to change the uniform values
00078         // during the CULL traversal.
00079         _lightingEnabledUniform->setDataVariance( osg::Object::DYNAMIC );
00080         _lightEnabledUniform->setDataVariance( osg::Object::DYNAMIC );
00081     }
00082 }
00083 
00084 UpdateLightingUniformsHelper::~UpdateLightingUniformsHelper()
00085 {
00086     delete [] _lightEnabled;
00087 }
00088 
00089 void
00090 UpdateLightingUniformsHelper::cullTraverse( osg::Node* node, osg::NodeVisitor* nv )
00091 {
00092     osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( nv );
00093     if ( cv )
00094     {
00095         StateSetStack stateSetStack;
00096 
00097         osgUtil::StateGraph* sg = cv->getCurrentStateGraph();
00098         while( sg )
00099         {
00100             const osg::StateSet* stateset = sg->getStateSet();
00101             if (stateset)
00102             {
00103                 stateSetStack.push_front(stateset);
00104             }                
00105             sg = sg->_parent;
00106         }
00107 
00108         // Update the overall lighting-enabled value:
00109         bool lightingEnabled = 
00110             ( getModeValue(stateSetStack, GL_LIGHTING) & osg::StateAttribute::ON ) != 0;
00111 
00112         if ( lightingEnabled != _lightingEnabled || !_applied )
00113         {
00114             _lightingEnabled = lightingEnabled;
00115             if ( _useUpdateTrav )
00116                 _dirty = true;
00117             else
00118                 _lightingEnabledUniform->set( _lightingEnabled );
00119         }
00120 
00121         // Update the list of enabled lights:
00122         for( int i=0; i < _maxLights; ++i )
00123         {
00124             bool enabled =
00125                 ( getModeValue( stateSetStack, GL_LIGHT0 + i ) & osg::StateAttribute::ON ) != 0;
00126 
00127             if ( _lightEnabled[i] != enabled || !_applied )
00128             {
00129                 _lightEnabled[i] = enabled;
00130                 if ( _useUpdateTrav )
00131                     _dirty = true;
00132                 else
00133                     _lightEnabledUniform->setElement( i, _lightEnabled[i] );
00134             }
00135         }       
00136 
00137         // apply if necessary:
00138         if ( !_applied && !_useUpdateTrav )
00139         {
00140             OpenThreads::ScopedLock<OpenThreads::Mutex> lock( _stateSetMutex );
00141             if (!_applied)
00142             {
00143                 node->getOrCreateStateSet()->addUniform( _lightingEnabledUniform.get() );
00144                 node->getStateSet()->addUniform( _lightEnabledUniform.get() );
00145                 _applied = true;
00146             }
00147         }               
00148     }        
00149 }
00150 
00151 void
00152 UpdateLightingUniformsHelper::updateTraverse( osg::Node* node )
00153 {
00154     if ( _dirty )
00155     {
00156         _lightingEnabledUniform->set( _lightingEnabled );
00157 
00158         for( int i=0; i < _maxLights; ++i )
00159             _lightEnabledUniform->setElement( i, _lightEnabled[i] );
00160 
00161         _dirty = false;
00162 
00163         if ( !_applied )
00164         {
00165             osg::StateSet* stateSet = node->getOrCreateStateSet();
00166             stateSet->addUniform( _lightingEnabledUniform.get() );
00167             stateSet->addUniform( _lightEnabledUniform.get() );
00168         }
00169     }
00170 }
00171 
00172 //------------------------------------------------------------------------
00173 
00174 ArrayUniform::ArrayUniform( const std::string& name, osg::Uniform::Type type, osg::StateSet* stateSet, unsigned size )
00175 {
00176     attach( name, type, stateSet, size );
00177 }
00178 
00179 void
00180 ArrayUniform::attach( const std::string& name, osg::Uniform::Type type, osg::StateSet* stateSet, unsigned size )
00181 {
00182     _uniform    = stateSet->getUniform( name );
00183     _uniformAlt = stateSet->getUniform( name + "[0]" );
00184 
00185     if ( !isValid() )
00186     {
00187         _uniform    = new osg::Uniform( type, name, size );
00188         _uniformAlt = new osg::Uniform( type, name + "[0]", size );
00189         stateSet->addUniform( _uniform.get() );
00190         stateSet->addUniform( _uniformAlt.get() );
00191     }
00192 
00193     _stateSet = stateSet;
00194 }
00195 
00196 void 
00197 ArrayUniform::setElement( unsigned index, int value )
00198 {
00199     if ( isValid() )
00200     {
00201         ensureCapacity( index+1 );
00202         _uniform->setElement( index, value );
00203         _uniformAlt->setElement( index, value );
00204     }
00205 }
00206 
00207 void 
00208 ArrayUniform::setElement( unsigned index, unsigned value )
00209 {
00210     if ( isValid() )
00211     {
00212         ensureCapacity( index+1 );
00213         _uniform->setElement( index, value );
00214         _uniformAlt->setElement( index, value );
00215     }
00216 }
00217 
00218 void 
00219 ArrayUniform::setElement( unsigned index, bool value )
00220 {
00221     if ( isValid() )
00222     {
00223         ensureCapacity( index+1 );
00224         _uniform->setElement( index, value );
00225         _uniformAlt->setElement( index, value );
00226     }
00227 }
00228 
00229 void 
00230 ArrayUniform::setElement( unsigned index, float value )
00231 {
00232     if ( isValid() )
00233     {
00234         ensureCapacity( index+1 );
00235         _uniform->setElement( index, value );
00236         _uniformAlt->setElement( index, value );
00237     }
00238 }
00239 
00240 void
00241 ArrayUniform::setElement( unsigned index, const osg::Matrix& value )
00242 {
00243     if ( isValid() )
00244     {
00245         ensureCapacity( index+1 );
00246         _uniform->setElement( index, value );
00247         _uniformAlt->setElement( index, value );
00248     }
00249 }
00250 
00251 void
00252 ArrayUniform::setElement( unsigned index, const osg::Vec3& value )
00253 {
00254     if ( isValid() )
00255     {
00256         ensureCapacity( index+1 );
00257         _uniform->setElement( index, value );
00258         _uniformAlt->setElement( index, value );
00259     }
00260 }
00261 
00262 bool 
00263 ArrayUniform::getElement( unsigned index, int& out_value ) const
00264 {
00265     return isValid() ? _uniform->getElement( index, out_value ) : false;
00266 }
00267 
00268 bool 
00269 ArrayUniform::getElement( unsigned index, unsigned& out_value ) const
00270 {
00271     return isValid() ? _uniform->getElement( index, out_value ) : false;
00272 }
00273 
00274 bool 
00275 ArrayUniform::getElement( unsigned index, bool& out_value ) const
00276 {
00277     return isValid() ? _uniform->getElement( index, out_value ) : false;
00278 }
00279 
00280 bool 
00281 ArrayUniform::getElement( unsigned index, float& out_value ) const
00282 {
00283     return isValid() ? _uniform->getElement( index, out_value ) : false;
00284 }
00285 
00286 bool 
00287 ArrayUniform::getElement( unsigned index, osg::Matrix& out_value ) const
00288 {
00289     return isValid() ? _uniform->getElement( index, out_value ) : false;
00290 }
00291 
00292 bool 
00293 ArrayUniform::getElement( unsigned index, osg::Vec3& out_value ) const
00294 {
00295     return isValid() ? _uniform->getElement( index, out_value ) : false;
00296 }
00297 
00298 
00299 void
00300 ArrayUniform::ensureCapacity( unsigned newSize )
00301 {
00302     if ( isValid() && _uniform->getNumElements() < newSize )
00303     {
00304         osg::ref_ptr<osg::StateSet> stateSet_safe = _stateSet.get();
00305         if ( stateSet_safe.valid() )
00306         {
00307             osg::ref_ptr<osg::Uniform> _oldUniform    = _uniform.get();
00308             osg::ref_ptr<osg::Uniform> _oldUniformAlt = _oldUniform.get();
00309 
00310             stateSet_safe->removeUniform( _uniform->getName() );
00311             stateSet_safe->removeUniform( _uniformAlt->getName() );
00312 
00313             _uniform    = new osg::Uniform( _uniform->getType(), _uniform->getName(), newSize );
00314             _uniformAlt = new osg::Uniform( _uniform->getType(), _uniform->getName() + "[0]", newSize );
00315 
00316             switch( _oldUniform->getInternalArrayType(_oldUniform->getType()) )
00317             {
00318             case GL_FLOAT:
00319               {
00320                 for( unsigned i = 0; i < _oldUniform->getNumElements(); ++i )
00321                 {
00322                   float value;
00323                   _oldUniform->getElement(i, value);
00324                   setElement( i, value );
00325                 }
00326               }
00327               break;
00328 
00329             case GL_INT:
00330               {
00331                 for( unsigned i = 0; i < _oldUniform->getNumElements(); ++i )
00332                 {
00333                   int value;
00334                   _oldUniform->getElement(i, value);
00335                   setElement( i, value );
00336                 }
00337               }
00338               break;
00339 
00340             case GL_UNSIGNED_INT:
00341               {
00342                 for( unsigned i = 0; i < _oldUniform->getNumElements(); ++i )
00343                 {
00344                   unsigned value;
00345                   _oldUniform->getElement(i, value);
00346                   setElement( i, value );
00347                 }
00348               }
00349               break;
00350             }
00351 
00352             stateSet_safe->addUniform( _uniform.get() );
00353             stateSet_safe->addUniform( _uniformAlt.get() );
00354 
00355             stateSet_safe.release(); // don't want to unref delete
00356         }
00357     }
00358 }
00359 
00360 void
00361 ArrayUniform::detach()
00362 {
00363     if ( isValid() )
00364     {
00365         osg::ref_ptr<osg::StateSet> stateSet_safe = _stateSet.get();
00366         if ( stateSet_safe.valid() )
00367         {
00368             stateSet_safe->removeUniform( _uniform->getName() );
00369             stateSet_safe->removeUniform( _uniformAlt->getName() );
00370 
00371             _uniform = 0L;
00372             _uniformAlt = 0L;
00373             _stateSet = 0L;
00374 
00375             stateSet_safe.release(); // don't want to unref delete
00376         }
00377     }
00378 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines