Example #1
0
// Build the stateset necessary for drawing contours.
osg::StateSet* createStateSet( osg::TransferFunction1D* xfer, int unit )
{
    osg::StateSet* stateSet = new osg::StateSet();

    // Create a 1D texture from the transfer function's image.
    osg::Texture* tex = new osg::Texture1D( xfer->getImage() );
    tex->setResizeNonPowerOfTwoHint( false );
    tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
    tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
    tex->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
    stateSet->setTextureAttributeAndModes( unit, tex, osg::StateAttribute::ON );

    // Tell the shader program where to find it.
    stateSet->getOrCreateUniform( "contour_colorMap", osg::Uniform::SAMPLER_1D )->set( unit );

    // Install the shaders. We also bind osgEarth's elevation data attribute, which the 
    // terrain engine automatically generates at the specified location.
    VirtualProgram* vp = new VirtualProgram();
    vp->installDefaultColoringAndLightingShaders();
    vp->setFunction( "setupContour", vertexShader,   ShaderComp::LOCATION_VERTEX_PRE_LIGHTING );
    vp->setFunction( "colorContour", fragmentShader, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
    vp->addBindAttribLocation( "osgearth_elevData", osg::Drawable::ATTRIBUTE_6 );
    stateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );

    // Install some uniforms that tell the shader the height range of the color map.
    stateSet->getOrCreateUniform( "contour_xferMin",   osg::Uniform::FLOAT )->set( xfer->getMinimum() );
    stateSet->getOrCreateUniform( "contour_xferRange", osg::Uniform::FLOAT )->set( xfer->getMaximum() - xfer->getMinimum() );

    return stateSet;
};
Example #2
0
void
OSGTerrainEngineNode::installShaders()
{
    // This method installs a default shader setup on the engine node itself. The texture compositor
    // can then override parts of the program by using a VirtualProgram on the _terrain node. We do
    // it this way so that the developer has the option of removing this top-level shader program,
    // replacing it, or migrating it higher up the scene graph if necessary.

    if ( _texCompositor.valid() && _texCompositor->usesShaderComposition() )
    {
        const ShaderFactory* sf = Registry::instance()->getShaderFactory();

        int numLayers = osg::maximum( 1, (int)_update_mapf->imageLayers().size() );
        //int numLayers = osg::maximum( 0, (int)_update_mapf->imageLayers().size() );

        VirtualProgram* vp = new VirtualProgram();
        vp->setName( "engine_osgterrain:EngineNode" );
        vp->installDefaultColoringAndLightingShaders(numLayers);

        getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON );
    }
}
Example #3
0
void
MapNode::init()
{
    // Take a reference to this object so that it doesn't get inadvertently
    // deleting during startup. It is possible that during startup, a driver
    // will load that will take a reference to the MapNode (like in a
    // ModelSource node operation) and we don't want that deleting the MapNode
    // out from under us. 
    // This is paired by an unref_nodelete() at the end of this method.
    this->ref();

    // Protect the MapNode from the Optimizer
    setDataVariance(osg::Object::DYNAMIC);

    // initialize 0Ls
    _terrainEngine          = 0L;
    _terrainEngineContainer = 0L;
    _overlayDecorator       = 0L;

    setName( "osgEarth::MapNode" );

    // Since we have global uniforms in the stateset, mark it dynamic so it is immune to
    // multi-threaded overlap
    // TODO: do we need this anymore? there are no more global uniforms in here.. gw
    getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC);

    _modelLayerCallback = new MapModelLayerCallback(this);

    _maskLayerNode = 0L;
    _lastNumBlacklistedFilenames = 0;

    // Set the global proxy settings
    // TODO: this should probably happen elsewhere, like in the registry?
    if ( _mapNodeOptions.proxySettings().isSet() )
    {
        HTTPClient::setProxySettings( _mapNodeOptions.proxySettings().get() );
    }

    // establish global driver options. These are OSG reader-writer options that
    // will make their way to any read* calls down the pipe
    const osgDB::Options* global_options = _map->getGlobalOptions();

    osg::ref_ptr<osgDB::Options> local_options = global_options ? 
        Registry::instance()->cloneOrCreateOptions( global_options ) :
        NULL;

    if ( local_options.valid() )
    {
        OE_INFO << LC
            << "Options string = " 
            << (local_options.valid()? local_options->getOptionString() : "<empty>")
            << std::endl;
    }

    // TODO: not sure why we call this here
    _map->setGlobalOptions( local_options.get() );

    // load and attach the terrain engine, but don't initialize it until we need it
    const TerrainOptions& terrainOptions = _mapNodeOptions.getTerrainOptions();

    _terrainEngine = TerrainEngineNodeFactory::create( _map.get(), terrainOptions );
    _terrainEngineInitialized = false;

    // the engine needs a container so we can set lighting state on the container and
    // not on the terrain engine itself. Setting the dynamic variance will prevent
    // an optimizer from collapsing the empty group node.
    _terrainEngineContainer = new osg::Group();
    _terrainEngineContainer->setDataVariance( osg::Object::DYNAMIC );
    this->addChild( _terrainEngineContainer );

    // initialize terrain-level lighting:
    if ( terrainOptions.enableLighting().isSet() )
    {
        _terrainEngineContainer->getOrCreateStateSet()->setMode( 
            GL_LIGHTING, 
            terrainOptions.enableLighting().value() ? 1 : 0 );
    }

    if ( _terrainEngine )
    {
        // inform the terrain engine of the map information now so that it can properly
        // initialize it's CoordinateSystemNode. This is necessary in order to support
        // manipulators and to set up the texture compositor prior to frame-loop 
        // initialization.
        _terrainEngine->preInitialize( _map.get(), terrainOptions );
        _terrainEngineContainer->addChild( _terrainEngine );
    }
    else
    {
        OE_WARN << "FAILED to create a terrain engine for this map" << std::endl;
    }

    // make a group for the model layers.
    // NOTE: for now, we are going to nullify any shader programs that occur above the model
    // group, since it does not YET support shader composition. Programs defined INSIDE a
    // model layer will still work OK though.
    _models = new osg::Group();
    _models->setName( "osgEarth::MapNode.modelsGroup" );
    addChild( _models.get() );

    // make a group for overlay model layers:
    _overlayModels = new ObserverGroup(); //osg::Group();
    _overlayModels->setName( "osgEarth::MapNode.overlayModelsGroup" );

    // a decorator for overlay models:
    _overlayDecorator = new OverlayDecorator();
    _overlayDecorator->setOverlayGraphTraversalMask( terrainOptions.secondaryTraversalMask().value() );

    if ( _mapNodeOptions.overlayBlending().isSet() )
        _overlayDecorator->setOverlayBlending( *_mapNodeOptions.overlayBlending() );
    if ( _mapNodeOptions.overlayTextureSize().isSet() )
        _overlayDecorator->setTextureSize( *_mapNodeOptions.overlayTextureSize() );
    if ( _mapNodeOptions.overlayMipMapping().isSet() )
        _overlayDecorator->setMipMapping( *_mapNodeOptions.overlayMipMapping() );

    addTerrainDecorator( _overlayDecorator );

    // install any pre-existing model layers:
    ModelLayerVector modelLayers;
    _map->getModelLayers( modelLayers );
    int modelLayerIndex = 0;
    for( ModelLayerVector::const_iterator k = modelLayers.begin(); k != modelLayers.end(); k++, modelLayerIndex++ )
    {
        onModelLayerAdded( k->get(), modelLayerIndex );
    }

    _mapCallback = new MapNodeMapCallbackProxy(this);
    // install a layer callback for processing further map actions:
    _map->addMapCallback( _mapCallback.get()  );

    osg::StateSet* ss = getOrCreateStateSet();

    if ( _mapNodeOptions.enableLighting().isSet() )
    {
        ss->setMode( 
            GL_LIGHTING, 
            _mapNodeOptions.enableLighting().value() ? 1 : 0 );
    }

    dirtyBound();

    // Install top-level shader programs:
    if ( Registry::capabilities().supportsGLSL() )
    {
        VirtualProgram* vp = new VirtualProgram();
        vp->setName( "MapNode" );
        vp->installDefaultColoringAndLightingShaders();
        ss->setAttributeAndModes( vp, osg::StateAttribute::ON );
    }

    // register for event traversals so we can deal with blacklisted filenames
    ADJUST_EVENT_TRAV_COUNT( this, 1 );

    // remove the temporary reference.
    this->unref_nodelete();
}
Example #4
0
void
OverlayDecorator::initializePerViewData( PerViewData& pvd )
{
    if ( !_textureUnit.isSet() || !_overlayGraph.valid() )
        return;

    // create the projected texture:
    osg::Texture2D* projTexture = 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_EDGE); //CLAMP_TO_BORDER );
    projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
    projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE );
    projTexture->setBorderColor( osg::Vec4(0,0,0,0) );

    // set up the RTT camera:
    pvd._rttCamera = new osg::Camera();
    pvd._rttCamera->setClearColor( osg::Vec4f(0,0,0,0) );
    pvd._rttCamera->setClearStencil( 0 );
    pvd._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    // 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)
    pvd._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT );
    pvd._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize );
    pvd._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );
    pvd._rttCamera->setRenderOrder( osg::Camera::PRE_RENDER );
    pvd._rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );

    pvd._rttCamera->attach( osg::Camera::COLOR_BUFFER, projTexture, 0, 0, _mipmapping );

    if (_attachStencil) {
        // 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::instance()->getCapabilities().supportsDepthPackedStencilBuffer() )
        {
#ifdef OSG_GLES2_AVAILABLE 
            pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8_EXT );
#else
            pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT );
#endif
        }
        else
        {
            pvd._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX );
        }
    }

    osg::StateSet* rttStateSet = pvd._rttCamera->getOrCreateStateSet();

    rttStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );

    // install a new default shader program that replaces anything from above.
    if ( _useShaders )
    {
        VirtualProgram* vp = new VirtualProgram();
        vp->setName( "overlay rtt" );
        vp->installDefaultColoringAndLightingShaders();
        vp->setInheritShaders( false );
        rttStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
    }
    
    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::instance()->getCapabilities().supportsGLSL(1.4f))
        {
            //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 graph to the RTT camera.
    if ( _overlayGraph.valid() && ( _overlayGraph->getNumParents() == 0 || _overlayGraph->getParent(0) != pvd._rttCamera.get() ))
    {
        if ( pvd._rttCamera->getNumChildren() > 0 )
            pvd._rttCamera->replaceChild( 0, _overlayGraph.get() );
        else
            pvd._rttCamera->addChild( _overlayGraph.get() );
    }

    // 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" );


    // assemble the subgraph stateset:
    pvd._subgraphStateSet = new osg::StateSet();

    pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, projTexture, osg::StateAttribute::ON );
    
    if ( _useShaders )
    {            
        // GPU path
        initSubgraphShaders( pvd );
    }
    else
    {
        // FFP path
        pvd._texGen = new osg::TexGen();
        pvd._texGen->setMode( osg::TexGen::EYE_LINEAR );
        pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, pvd._texGen.get(), 1 );

        osg::TexEnv* env = new osg::TexEnv();
        env->setMode( osg::TexEnv::DECAL );
        pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, env, 1 );
    }
}