void FogEffect::attach( osg::StateSet* stateSet ) { VirtualProgram* vp = VirtualProgram::getOrCreate( stateSet ); Shaders pkg; pkg.load( vp, pkg.Fog_Vertex ); pkg.load( vp, pkg.Fog_Fragment ); _statesets.push_back(stateSet); }
void PointDrawable::setupState() { // Create the singleton state set for the shader. This stateset will be // shared by all PointDrawable instances so OSG will sort them together. if (!_sharedStateSet.valid()) { static Threading::Mutex s_mutex; s_mutex.lock(); if (!_sharedStateSet.valid()) { _sharedStateSet = new osg::StateSet(); _sharedStateSet->setTextureAttributeAndModes(0, new osg::PointSprite(), osg::StateAttribute::ON); if (_gpu) { VirtualProgram* vp = VirtualProgram::getOrCreate(_sharedStateSet.get()); Shaders shaders; shaders.load(vp, shaders.PointDrawable); _sharedStateSet->setMode(GL_PROGRAM_POINT_SIZE, 1); } else { //todo } s_isCoreProfile = Registry::capabilities().isCoreProfile(); } s_mutex.unlock(); } }
RexTerrainEngineNode::RexTerrainEngineNode() : TerrainEngineNode ( ), _terrain ( 0L ), _update_mapf ( 0L ), _tileCount ( 0 ), _tileCreationTime ( 0.0 ), _batchUpdateInProgress( false ), _refreshRequired ( false ), _stateUpdateRequired ( false ) { // unique ID for this engine: _uid = Registry::instance()->createUID(); // always require elevation. _requireElevationTextures = true; // install an elevation callback so we can update elevation data _elevationCallback = new ElevationChangedCallback( this ); // static shaders. if ( Registry::capabilities().supportsGLSL() ) { osg::StateSet* stateset = getOrCreateStateSet(); VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); Shaders package; package.load(vp, package.SDK); } // TODO: replace with a "renderer" object that can return statesets // for different layer types, or something. _imageLayerStateSet = new osg::StateSet(); }
void GeodeticGraticule::installEffect() { if (_mapNode.valid() == false) return; // shader components osg::StateSet* stateset = _mapNode->getTerrainEngine()->getSurfaceStateSet(); VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); // configure shaders Shaders package; package.load(vp, package.Graticule_Vertex); package.load(vp, package.Graticule_Fragment); stateset->addUniform(new osg::Uniform(COLOR_UNIFORM, options().color().get())); stateset->addUniform(new osg::Uniform(WIDTH_UNIFORM, options().lineWidth().get())); }
void BumpMapTerrainEffect::onInstall(TerrainEngineNode* engine) { if ( engine && _bumpMapTex.valid() ) { osg::StateSet* stateset = engine->getSurfaceStateSet(); // install the NormalMap texture array: if ( engine->getResources()->reserveTextureImageUnit(_bumpMapUnit, "BumpMap") ) { // NormalMap sampler _bumpMapTexUniform = stateset->getOrCreateUniform(BUMP_SAMPLER, osg::Uniform::SAMPLER_2D); _bumpMapTexUniform->set( _bumpMapUnit ); stateset->setTextureAttribute( _bumpMapUnit, _bumpMapTex.get() ); // configure shaders VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); Shaders package; package.define( "OE_USE_NORMAL_MAP", false ); //engine->normalTexturesRequired() ); //package.load( vp, package.VertexModel ); package.load( vp, package.VertexView ); package.load( vp, _octaves <= 1? package.FragmentSimple : package.FragmentProgressive ); if ( _octaves > 1 ) stateset->addUniform(new osg::Uniform("oe_bumpmap_octaves", _octaves)); stateset->addUniform(new osg::Uniform("oe_bumpmap_maxRange", _maxRange)); stateset->addUniform(new osg::Uniform("oe_bumpmap_slopeFactor", 1.0f)); stateset->addUniform(new osg::Uniform("oe_bumpmap_baseLOD", (float)_baseLOD)); stateset->addUniform( _scaleUniform.get() ); stateset->addUniform( _intensityUniform.get() ); } else { OE_WARN << LC << "Failed to allocation a texture image unit!\n"; } } }
void AlphaEffect::install(osg::StateSet* stateset) { if (stateset) { VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); if (vp) { vp->setName( "osgEarth.AlphaEffect" ); Shaders pkg; pkg.load(vp, pkg.AlphaEffectFragment); stateset->addUniform(_alphaUniform.get()); } } }
RexTerrainEngineNode::RexTerrainEngineNode() : TerrainEngineNode ( ), _terrain ( 0L ), _update_mapf ( 0L ), _tileCount ( 0 ), _tileCreationTime ( 0.0 ), _batchUpdateInProgress( false ), _refreshRequired ( false ), _stateUpdateRequired ( false ), _selectionInfo ( 0L ) { // unique ID for this engine: _uid = Registry::instance()->createUID(); // always require elevation. _requireElevationTextures = true; // Register our render bins protos. { // Mutex because addRenderBinPrototype isn't thread-safe. Threading::ScopedMutexLock lock(_renderBinMutex); // generate uniquely named render bin prototypes for this engine: //_surfaceRenderBinPrototype = new SurfaceBin(); //osgUtil::RenderBin::addRenderBinPrototype( _surfaceRenderBinPrototype->getName(), _surfaceRenderBinPrototype.get() ); } // install an elevation callback so we can update elevation data _elevationCallback = new ElevationChangedCallback( this ); // static shaders. if ( Registry::capabilities().supportsGLSL() ) { osg::StateSet* stateset = getOrCreateStateSet(); VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); Shaders package; package.load(vp, package.SDK); } _surfaceSS = new osg::StateSet(); }
void ContourMap::onInstall(TerrainEngineNode* engine) { if ( engine ) { if ( !engine->getResources()->reserveTextureImageUnit(_unit, "ContourMap") ) { OE_WARN << LC << "Failed to reserve a texture image unit; disabled." << std::endl; return; } osg::StateSet* stateset = engine->getOrCreateStateSet(); // Install the texture and its sampler uniform: stateset->setTextureAttributeAndModes( _unit, _xferTexture.get(), osg::StateAttribute::ON ); stateset->addUniform( _xferSampler.get() ); _xferSampler->set( _unit ); // (By the way: if you want to draw image layers on top of the contoured terrain, // set the "priority" parameter to setFunction() to a negative number so that it draws // before the terrain's layers.) VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); Shaders pkg; //pkg.load(vp, pkg.ContourMap_Vertex); pkg.load(vp, pkg.ContourMap_Fragment); // Install some uniforms that tell the shader the height range of the color map. stateset->addUniform( _xferMin.get() ); _xferMin->set( _xfer->getMinimum() ); stateset->addUniform( _xferRange.get() ); _xferRange->set( _xfer->getMaximum() - _xfer->getMinimum() ); stateset->addUniform( _opacityUniform.get() ); } }
// Generates the main shader code for rendering the terrain. void RexTerrainEngineNode::updateState() { if ( _batchUpdateInProgress ) { _stateUpdateRequired = true; } else { osg::StateSet* terrainStateSet = _terrain->getOrCreateStateSet(); // everything osg::StateSet* surfaceStateSet = getSurfaceStateSet(); // just the surface // required for multipass tile rendering to work surfaceStateSet->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0, 1, true) ); // activate standard mix blending. terrainStateSet->setAttributeAndModes( new osg::BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON ); // install patch param if we are tessellation on the GPU. if ( _terrainOptions.gpuTessellation() == true ) { #ifdef HAVE_PATCH_PARAMETER terrainStateSet->setAttributeAndModes( new osg::PatchParameter(3) ); #endif } // install shaders, if we're using them. if ( Registry::capabilities().supportsGLSL() ) { Shaders package; VirtualProgram* terrainVP = VirtualProgram::getOrCreate(terrainStateSet); terrainVP->setName( "Rex Terrain" ); package.load(terrainVP, package.ENGINE_VERT_MODEL); //moved to CTOR so it's always available //package.load(terrainVP, package.SDK); bool useTerrainColor = _terrainOptions.color().isSet(); package.define("OE_REX_USE_TERRAIN_COLOR", useTerrainColor); if ( useTerrainColor ) { surfaceStateSet->addUniform(new osg::Uniform("oe_terrain_color", _terrainOptions.color().get())); } bool useBlending = _terrainOptions.enableBlending().get(); package.define("OE_REX_GL_BLENDING", useBlending); bool morphImagery = _terrainOptions.morphImagery().get(); package.define("OE_REX_MORPH_IMAGERY", morphImagery); // Funtions that affect only the terrain surface: VirtualProgram* surfaceVP = VirtualProgram::getOrCreate(surfaceStateSet); surfaceVP->setName("Rex Surface"); // Functions that affect the terrain surface only: package.load(surfaceVP, package.ENGINE_VERT_VIEW); package.load(surfaceVP, package.ENGINE_FRAG); // Normal mapping shaders: if ( this->normalTexturesRequired() ) { package.load(surfaceVP, package.NORMAL_MAP_VERT); package.load(surfaceVP, package.NORMAL_MAP_FRAG); } // Morphing? if (_terrainOptions.morphTerrain() == true || _terrainOptions.morphImagery() == true) { package.define("OE_REX_VERTEX_MORPHING", (_terrainOptions.morphTerrain() == true)); package.load(surfaceVP, package.MORPHING_VERT); } for(LandCoverZones::iterator zone = _landCoverData._zones.begin(); zone != _landCoverData._zones.end(); ++zone) { for(LandCoverBins::iterator bin = zone->_bins.begin(); bin != zone->_bins.end(); ++bin) { osg::StateSet* landCoverStateSet = bin->_binProto->getStateSet(); // enable alpha-to-coverage multisampling for vegetation. landCoverStateSet->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, 1); // uniform that communicates the availability of multisampling. landCoverStateSet->addUniform( new osg::Uniform( "oe_terrain_hasMultiSamples", osg::DisplaySettings::instance()->getMultiSamples()) ); landCoverStateSet->setAttributeAndModes( new osg::BlendFunc(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO), osg::StateAttribute::OVERRIDE ); #ifdef HAVE_OSG_PATCH_PARAMETER landCoverStateSet->setAttributeAndModes( new osg::PatchParameter(3) ); #endif } } // assemble color filter code snippets. bool haveColorFilters = false; { // Color filter frag function: std::string fs_colorfilters = "#version " GLSL_VERSION_STR "\n" GLSL_DEFAULT_PRECISION_FLOAT "\n" "uniform int oe_layer_uid; \n" "$COLOR_FILTER_HEAD" "void oe_rexEngine_applyFilters(inout vec4 color) \n" "{ \n" "$COLOR_FILTER_BODY" "} \n"; std::stringstream cf_head; std::stringstream cf_body; const char* I = " "; // second, install the per-layer color filter functions AND shared layer bindings. bool ifStarted = false; int numImageLayers = _update_mapf->imageLayers().size(); for( int i=0; i<numImageLayers; ++i ) { ImageLayer* layer = _update_mapf->getImageLayerAt(i); if ( layer->getEnabled() ) { // install Color Filter function calls: const ColorFilterChain& chain = layer->getColorFilters(); if ( chain.size() > 0 ) { haveColorFilters = true; if ( ifStarted ) cf_body << I << "else if "; else cf_body << I << "if "; cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n"; for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j ) { const ColorFilter* filter = j->get(); cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n"; cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n"; filter->install( surfaceStateSet ); } cf_body << I << "}\n"; ifStarted = true; } } } if ( haveColorFilters ) { std::string cf_head_str, cf_body_str; cf_head_str = cf_head.str(); cf_body_str = cf_body.str(); replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str ); replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str ); surfaceVP->setFunction( "oe_rexEngine_applyFilters", fs_colorfilters, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.0 ); } } // Apply uniforms for sampler bindings: OE_DEBUG << LC << "Render Bindings:\n"; for(RenderBindings::const_iterator b = _renderBindings.begin(); b != _renderBindings.end(); ++b) { if ( b->isActive() ) { terrainStateSet->addUniform( new osg::Uniform(b->samplerName().c_str(), b->unit()) ); OE_DEBUG << LC << " > Bound \"" << b->samplerName() << "\" to unit " << b->unit() << "\n"; } } // uniform that controls per-layer opacity terrainStateSet->addUniform( new osg::Uniform("oe_layer_opacity", 1.0f) ); // uniform that conveys the layer UID to the shaders; necessary // for per-layer branching (like color filters) // UID -1 => no image layer (no texture) terrainStateSet->addUniform( new osg::Uniform("oe_layer_uid", (int)-1 ) ); // uniform that conveys the render order, since the shaders // need to know which is the first layer in order to blend properly terrainStateSet->addUniform( new osg::Uniform("oe_layer_order", (int)0) ); // default min/max range uniforms. (max < min means ranges are disabled) terrainStateSet->addUniform( new osg::Uniform("oe_layer_minRange", 0.0f) ); terrainStateSet->addUniform( new osg::Uniform("oe_layer_maxRange", -1.0f) ); terrainStateSet->getOrCreateUniform( "oe_min_tile_range_factor", osg::Uniform::FLOAT)->set( *_terrainOptions.minTileRangeFactor() ); terrainStateSet->addUniform(new osg::Uniform("oe_tile_size", (float)_terrainOptions.tileSize().get())); // special object ID that denotes the terrain surface. surfaceStateSet->addUniform( new osg::Uniform( Registry::objectIndex()->getObjectIDUniformName().c_str(), OSGEARTH_OBJECTID_TERRAIN) ); } _stateUpdateRequired = false; } }
// Generates the main shader code for rendering the terrain. void MPTerrainEngineNode::updateState() { if ( _batchUpdateInProgress ) { _stateUpdateRequired = true; } else { if ( _elevationTextureUnit < 0 && elevationTexturesRequired() ) { getResources()->reserveTextureImageUnit( _elevationTextureUnit, "MP Engine Elevation" ); } osg::StateSet* terrainStateSet = getTerrainStateSet(); if ( !terrainStateSet ) return; // required for multipass tile rendering to work terrainStateSet->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0, 1, true) ); // activate standard mix blending. terrainStateSet->setAttributeAndModes( new osg::BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON ); // install shaders, if we're using them. if ( Registry::capabilities().supportsGLSL() ) { VirtualProgram* vp = new VirtualProgram(); vp->setName( "osgEarth.engine_mp.TerrainNode" ); terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON ); Shaders package; package.replace( "$MP_PRIMARY_UNIT", Stringify() << _primaryUnit ); package.replace( "$MP_SECONDARY_UNIT", Stringify() << (_secondaryUnit>=0?_secondaryUnit:0) ); package.define( "MP_USE_BLENDING", (_terrainOptions.enableBlending() == true) ); package.load( vp, package.EngineVertexModel ); package.load( vp, package.EngineVertexView ); package.load( vp, package.EngineFragment ); if ( this->normalTexturesRequired() ) { package.load( vp, package.NormalMapVertex ); package.load( vp, package.NormalMapFragment ); terrainStateSet->addUniform( new osg::Uniform("oe_tile_normalTex", _normalMapUnit) ); } // terrain background color; negative means use the vertex color. Color terrainColor = _terrainOptions.color().getOrUse( Color(1,1,1,-1) ); terrainStateSet->addUniform(new osg::Uniform("oe_terrain_color", terrainColor)); if ( _update_mapf ) { // assemble color filter code snippets. bool haveColorFilters = false; { // Color filter frag function: std::string fs_colorfilters = "#version " GLSL_VERSION_STR "\n" GLSL_DEFAULT_PRECISION_FLOAT "\n" "uniform int oe_layer_uid; \n" "$COLOR_FILTER_HEAD" "void oe_mp_apply_filters(inout vec4 color) \n" "{ \n" "$COLOR_FILTER_BODY" "} \n"; std::stringstream cf_head; std::stringstream cf_body; const char* I = " "; // second, install the per-layer color filter functions AND shared layer bindings. ImageLayerVector imageLayers; _update_mapf->getLayers(imageLayers); bool ifStarted = false; int numImageLayers = imageLayers.size(); for( int i=0; i<numImageLayers; ++i ) { ImageLayer* layer = imageLayers[i].get(); if ( layer->getEnabled() ) { // install Color Filter function calls: const ColorFilterChain& chain = layer->getColorFilters(); if ( chain.size() > 0 ) { haveColorFilters = true; if ( ifStarted ) cf_body << I << "else if "; else cf_body << I << "if "; cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n"; for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j ) { const ColorFilter* filter = j->get(); cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n"; cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n"; filter->install( terrainStateSet ); } cf_body << I << "}\n"; ifStarted = true; } } } if ( haveColorFilters ) { std::string cf_head_str, cf_body_str; cf_head_str = cf_head.str(); cf_body_str = cf_body.str(); replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str ); replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str ); vp->setFunction( "oe_mp_apply_filters", fs_colorfilters, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.5f ); } } } // binding for the terrain texture terrainStateSet->getOrCreateUniform( "oe_layer_tex", osg::Uniform::SAMPLER_2D )->set( _primaryUnit ); // binding for the secondary texture (for LOD blending) if ( parentTexturesRequired() ) { terrainStateSet->getOrCreateUniform( "oe_layer_tex_parent", osg::Uniform::SAMPLER_2D )->set( _secondaryUnit ); // binding for the default secondary texture matrix osg::Matrixf parent_mat; parent_mat(0,0) = 0.0f; terrainStateSet->getOrCreateUniform( "oe_layer_parent_matrix", osg::Uniform::FLOAT_MAT4 )->set( parent_mat ); } // uniform for accessing the elevation texture sampler. if ( elevationTexturesRequired() ) { terrainStateSet->getOrCreateUniform( "oe_terrain_tex", osg::Uniform::SAMPLER_2D)->set( _elevationTextureUnit ); } // uniform that controls per-layer opacity terrainStateSet->getOrCreateUniform( "oe_layer_opacity", osg::Uniform::FLOAT )->set( 1.0f ); // uniform that conveys the layer UID to the shaders; necessary // for per-layer branching (like color filters) // UID -1 => no image layer (no texture) terrainStateSet->getOrCreateUniform( "oe_layer_uid", osg::Uniform::INT )->set( -1 ); // uniform that conveys the render order, since the shaders // need to know which is the first layer in order to blend properly terrainStateSet->getOrCreateUniform( "oe_layer_order", osg::Uniform::INT )->set( 0 ); // default min/max range uniforms. (max < min means ranges are disabled) terrainStateSet->addUniform( new osg::Uniform("oe_layer_minRange", 0.0f) ); terrainStateSet->addUniform( new osg::Uniform("oe_layer_maxRange", FLT_MAX) ); terrainStateSet->addUniform( new osg::Uniform("oe_layer_attenuationRange", _terrainOptions.attentuationDistance().get()) ); terrainStateSet->getOrCreateUniform( "oe_min_tile_range_factor", osg::Uniform::FLOAT)->set( *_terrainOptions.minTileRangeFactor() ); // special object ID that denotes the terrain surface. terrainStateSet->addUniform( new osg::Uniform( Registry::objectIndex()->getObjectIDUniformName().c_str(), OSGEARTH_OBJECTID_TERRAIN) ); // assign the uniforms for each shared layer. if ( _update_mapf ) { ImageLayerVector imageLayers; _update_mapf->getLayers(imageLayers); int numImageLayers = imageLayers.size(); for( int i=0; i<numImageLayers; ++i ) { ImageLayer* layer = imageLayers[i].get(); if ( layer->getEnabled() && layer->isShared() ) { terrainStateSet->addUniform( new osg::Uniform( layer->shareTexUniformName()->c_str(), layer->shareImageUnit().get() ) ); } } } } _stateUpdateRequired = false; } }
// Generates the main shader code for rendering the terrain. void RexTerrainEngineNode::updateState() { if ( _batchUpdateInProgress ) { _stateUpdateRequired = true; } else { osg::StateSet* terrainStateSet = _terrain->getOrCreateStateSet(); // everything osg::StateSet* surfaceStateSet = getSurfaceStateSet(); // just the surface //terrainStateSet->setRenderBinDetails(0, "SORT_FRONT_TO_BACK"); // required for multipass tile rendering to work surfaceStateSet->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0, 1, true) ); surfaceStateSet->setAttributeAndModes( new osg::CullFace(), osg::StateAttribute::ON); // activate standard mix blending. terrainStateSet->setAttributeAndModes( new osg::BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON ); // install patch param if we are tessellation on the GPU. if ( _terrainOptions.gpuTessellation() == true ) { #ifdef HAVE_PATCH_PARAMETER terrainStateSet->setAttributeAndModes( new osg::PatchParameter(3) ); #endif } // install shaders, if we're using them. if ( Registry::capabilities().supportsGLSL() ) { Shaders package; VirtualProgram* terrainVP = VirtualProgram::getOrCreate(terrainStateSet); terrainVP->setName( "Rex Terrain" ); package.load(terrainVP, package.ENGINE_VERT_MODEL); surfaceStateSet->addUniform(new osg::Uniform("oe_terrain_color", _terrainOptions.color().get())); if (_terrainOptions.enableBlending() == true) { surfaceStateSet->setDefine("OE_TERRAIN_BLEND_IMAGERY"); } // Funtions that affect only the terrain surface: VirtualProgram* surfaceVP = VirtualProgram::getOrCreate(surfaceStateSet); surfaceVP->setName("Rex Surface"); // Functions that affect the terrain surface only: package.load(surfaceVP, package.ENGINE_VERT_VIEW); package.load(surfaceVP, package.ENGINE_FRAG); // Elevation? if (this->elevationTexturesRequired()) { surfaceStateSet->setDefine("OE_TERRAIN_RENDER_ELEVATION"); } // Normal mapping shaders: if ( this->normalTexturesRequired() ) { package.load(surfaceVP, package.NORMAL_MAP_VERT); package.load(surfaceVP, package.NORMAL_MAP_FRAG); surfaceStateSet->setDefine("OE_TERRAIN_RENDER_NORMAL_MAP"); } // Morphing? if (_terrainOptions.morphTerrain() == true || _terrainOptions.morphImagery() == true) { package.load(surfaceVP, package.MORPHING_VERT); if (_terrainOptions.morphImagery() == true) { surfaceStateSet->setDefine("OE_TERRAIN_MORPH_IMAGERY"); } if (_terrainOptions.morphTerrain() == true) { surfaceStateSet->setDefine("OE_TERRAIN_MORPH_GEOMETRY"); } } // assemble color filter code snippets. bool haveColorFilters = false; { // Color filter frag function: std::string fs_colorfilters = "#version " GLSL_VERSION_STR "\n" GLSL_DEFAULT_PRECISION_FLOAT "\n" "uniform int oe_layer_uid; \n" "$COLOR_FILTER_HEAD" "void oe_rexEngine_applyFilters(inout vec4 color) \n" "{ \n" "$COLOR_FILTER_BODY" "} \n"; std::stringstream cf_head; std::stringstream cf_body; const char* I = " "; // second, install the per-layer color filter functions AND shared layer bindings. bool ifStarted = false; ImageLayerVector imageLayers; _update_mapf->getLayers(imageLayers); for( int i=0; i<imageLayers.size(); ++i ) { ImageLayer* layer = imageLayers.at(i); if ( layer->getEnabled() ) { // install Color Filter function calls: const ColorFilterChain& chain = layer->getColorFilters(); if ( chain.size() > 0 ) { haveColorFilters = true; if ( ifStarted ) cf_body << I << "else if "; else cf_body << I << "if "; cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n"; for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j ) { const ColorFilter* filter = j->get(); cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n"; cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n"; filter->install( surfaceStateSet ); } cf_body << I << "}\n"; ifStarted = true; } } } if ( haveColorFilters ) { std::string cf_head_str, cf_body_str; cf_head_str = cf_head.str(); cf_body_str = cf_body.str(); replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str ); replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str ); surfaceVP->setFunction( "oe_rexEngine_applyFilters", fs_colorfilters, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.6 ); } } // Apply uniforms for sampler bindings: OE_DEBUG << LC << "Render Bindings:\n"; osg::ref_ptr<osg::Texture> tex = new osg::Texture2D(ImageUtils::createEmptyImage(1,1)); for (unsigned i = 0; i < _renderBindings.size(); ++i) { SamplerBinding& b = _renderBindings[i]; if (b.isActive()) { osg::Uniform* u = new osg::Uniform(b.samplerName().c_str(), b.unit()); terrainStateSet->addUniform( u ); OE_DEBUG << LC << " > Bound \"" << b.samplerName() << "\" to unit " << b.unit() << "\n"; terrainStateSet->setTextureAttribute(b.unit(), tex.get()); } } // uniform that controls per-layer opacity terrainStateSet->addUniform( new osg::Uniform("oe_layer_opacity", 1.0f) ); // uniform that conveys the layer UID to the shaders; necessary // for per-layer branching (like color filters) // UID -1 => no image layer (no texture) terrainStateSet->addUniform( new osg::Uniform("oe_layer_uid", (int)-1 ) ); // uniform that conveys the render order, since the shaders // need to know which is the first layer in order to blend properly terrainStateSet->addUniform( new osg::Uniform("oe_layer_order", (int)0) ); // default min/max range uniforms. (max < min means ranges are disabled) terrainStateSet->addUniform( new osg::Uniform("oe_layer_minRange", 0.0f) ); terrainStateSet->addUniform( new osg::Uniform("oe_layer_maxRange", -1.0f) ); terrainStateSet->addUniform( new osg::Uniform("oe_layer_attenuationRange", _terrainOptions.attentuationDistance().get()) ); terrainStateSet->getOrCreateUniform( "oe_min_tile_range_factor", osg::Uniform::FLOAT)->set( *_terrainOptions.minTileRangeFactor() ); terrainStateSet->addUniform(new osg::Uniform("oe_tile_size", (float)_terrainOptions.tileSize().get())); // special object ID that denotes the terrain surface. surfaceStateSet->addUniform( new osg::Uniform( Registry::objectIndex()->getObjectIDUniformName().c_str(), OSGEARTH_OBJECTID_TERRAIN) ); } _stateUpdateRequired = false; } }
void DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params) { // create the projected texture: osg::Texture2D* projTexture = new DrapingTexture(); // new osg::Texture2D(); projTexture->setTextureSize( *_textureSize, *_textureSize ); projTexture->setInternalFormat( GL_RGBA ); projTexture->setSourceFormat( GL_RGBA ); projTexture->setSourceType( GL_UNSIGNED_BYTE ); projTexture->setFilter( osg::Texture::MIN_FILTER, _mipmapping? osg::Texture::LINEAR_MIPMAP_LINEAR: osg::Texture::LINEAR ); projTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR ); projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER ); projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER ); //projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE ); projTexture->setBorderColor( osg::Vec4(0,0,0,0) ); // set up the RTT camera: params._rttCamera = new DrapingCamera(); //new osg::Camera(); params._rttCamera->setClearColor( osg::Vec4f(0,0,0,0) ); // this ref frame causes the RTT to inherit its viewpoint from above (in order to properly // process PagedLOD's etc. -- it doesn't affect the perspective of the RTT camera though) params._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT ); params._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize ); params._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); params._rttCamera->setRenderOrder( osg::Camera::PRE_RENDER ); params._rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); params._rttCamera->setImplicitBufferAttachmentMask(0, 0); params._rttCamera->attach( osg::Camera::COLOR_BUFFER0, projTexture, 0, 0, _mipmapping ); if ( _attachStencil ) { OE_INFO << LC << "Attaching a stencil buffer to the RTT camera" << std::endl; // try a depth-packed buffer. failing that, try a normal one.. if the FBO doesn't support // that (which is doesn't on some GPUs like Intel), it will automatically fall back on // a PBUFFER_RTT impl if ( Registry::capabilities().supportsDepthPackedStencilBuffer() ) { #ifdef OSG_GLES2_AVAILABLE params._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8_EXT ); #else params._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT ); #endif } else { params._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX ); } params._rttCamera->setClearStencil( 0 ); params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); } else { params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT ); } // set up a StateSet for the RTT camera. osg::StateSet* rttStateSet = params._rttCamera->getOrCreateStateSet(); osg::StateAttribute::OverrideValue forceOff = osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE; rttStateSet->addUniform( Registry::shaderFactory()->createUniformForGLMode(GL_LIGHTING, forceOff) ); rttStateSet->setMode( GL_LIGHTING, forceOff ); // activate blending within the RTT camera's FBO if ( _rttBlending ) { //Setup a separate blend function for the alpha components and the RGB components. //Because the destination alpha is initialized to 0 instead of 1 osg::BlendFunc* blendFunc = 0; if (Registry::capabilities().supportsGLSL(140u)) { //Blend Func Separate is only available on OpenGL 1.4 and above blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } rttStateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); } else { rttStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); } // attach the overlay group to the camera. // TODO: we should probably lock this since other cull traversals might be accessing the group // while we are changing its children. params._rttCamera->addChild( params._group ); // overlay geometry is rendered with no depth testing, and in the order it's found in the // scene graph... until further notice. rttStateSet->setMode(GL_DEPTH_TEST, 0); rttStateSet->setBinName( "TraversalOrderBin" ); // add to the terrain stateset, i.e. the stateset that the OverlayDecorator will // apply to the terrain before cull-traversing it. This will activate the projective // texturing on the terrain. params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, projTexture, osg::StateAttribute::ON ); // fire up the local per-view data: LocalPerViewData* local = new LocalPerViewData(); params._techniqueData = local; if ( _maxFarNearRatio > 1.0 ) { // Custom clipper that accounts for the projection matrix warping. // Without this, you will get geometry beyond the original ortho far plane. // (i.e. geometry from beyond the horizon will show through the earth) // When the projection matrix has been warped, verts with Z=1.0 are no longer // always on the far plane (only when y=-1) because of the perspective divide (w). // So we need to test the Z directly (without w) and clip. NOTE: this seems to work // fine, although I think it would be proper to clip at the fragment level with // alpha. We shall see. const char* warpClip = "#version " GLSL_VERSION_STR "\n" "void oe_overlay_warpClip(inout vec4 vclip) { \n" " if (vclip.z > 1.0) vclip.z = vclip.w+1.0; \n" "} \n"; VirtualProgram* rtt_vp = VirtualProgram::getOrCreate(rttStateSet); rtt_vp->setFunction( "oe_overlay_warpClip", warpClip, ShaderComp::LOCATION_VERTEX_CLIP ); } // Assemble the terrain shaders that will apply projective texturing. VirtualProgram* terrain_vp = VirtualProgram::getOrCreate(params._terrainStateSet); terrain_vp->setName( "Draping terrain shaders"); // sampler for projected texture: params._terrainStateSet->getOrCreateUniform( "oe_overlay_tex", osg::Uniform::SAMPLER_2D )->set( *_textureUnit ); // the texture projection matrix uniform. local->_texGenUniform = params._terrainStateSet->getOrCreateUniform( "oe_overlay_texmatrix", osg::Uniform::FLOAT_MAT4 ); // shaders Shaders pkg; pkg.load( terrain_vp, pkg.DrapingVertex ); pkg.load( terrain_vp, pkg.DrapingFragment ); }