osgEarth 2.1.1
|
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 }