Example #1
0
RexTerrainEngineNode::RexTerrainEngineNode() :
TerrainEngineNode     ( ),
_terrain              ( 0L ),
_tileCount            ( 0 ),
_tileCreationTime     ( 0.0 ),
_batchUpdateInProgress( false ),
_refreshRequired      ( false ),
_stateUpdateRequired  ( false )
{
    // Necessary for pager object data
    this->setName("osgEarth.RexTerrainEngineNode");

    // 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);
        vp->setName("RexTerrainEngineNode");
        vp->setIsAbstract(true);    // cannot run by itself, requires additional children
        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();
}
Example #2
0
void
DrawInstanced::install(osg::StateSet* stateset)
{
    if ( !stateset )
        return;

    // simple vertex program to position a vertex based on its instance
    // matrix, which is stored in a texture.
     std::string src_vert = Stringify() 
        << "#version 120 \n" 
        << "#extension GL_EXT_gpu_shader4 : enable \n" 
        << "#extension GL_ARB_draw_instanced: enable \n" 
        << "uniform sampler2D oe_di_postex; \n" 
        << "uniform vec2 oe_di_postex_size; \n" 
        << "void oe_di_setInstancePosition(inout vec4 VertexMODEL) \n" 
        << "{ \n" 
        << "    float index = float(4 * gl_InstanceID) / oe_di_postex_size.x; \n" 
        << "    float s = fract(index); \n" 
        << "    float t = floor(index)/oe_di_postex_size.y; \n" 
        << "    float step = 1.0 / oe_di_postex_size.x; \n"  // step from one vec4 to the next 
        << "    vec4 m0 = texture2D(oe_di_postex, vec2(s, t)); \n" 
        << "    vec4 m1 = texture2D(oe_di_postex, vec2(s+step, t)); \n" 
        << "    vec4 m2 = texture2D(oe_di_postex, vec2(s+step+step, t)); \n" 
        << "    vec4 m3 = texture2D(oe_di_postex, vec2(s+step+step+step, t)); \n" 
        << "    VertexMODEL = VertexMODEL * mat4(m0, m1, m2, m3); \n" // why??? 
        << "} \n"; 

    VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);

    vp->setFunction(
        "oe_di_setInstancePosition",
        src_vert,
        ShaderComp::LOCATION_VERTEX_MODEL );

    stateset->getOrCreateUniform("oe_di_postex", osg::Uniform::SAMPLER_2D)->set(POSTEX_TEXTURE_UNIT);
}
Example #3
0
osg::Node*
createMRTPass(App& app, osg::Node* sceneGraph)
{
    osg::Camera* rtt = new osg::Camera();
    rtt->setRenderOrder(osg::Camera::PRE_RENDER);
    rtt->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
    rtt->setViewport(0, 0, app.gcolor->getTextureWidth(), app.gcolor->getTextureHeight());
    rtt->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    rtt->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0), app.gcolor);
    rtt->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER1), app.gnormal);
    rtt->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER2), app.gdepth);

    static const char* vertSource =
        "varying float mrt_depth;\n"
        "void oe_mrt_vertex(inout vec4 vertexClip)\n"
        "{\n"
        "    mrt_depth = (vertexClip.z/vertexClip.w)*0.5+1.0;\n"
        "}\n";

    static const char* fragSource =
        "varying float mrt_depth;\n"
        "vec3 oe_global_Normal; \n"
        "void oe_mrt_fragment(inout vec4 color)\n"
        "{\n"
        "    gl_FragData[0] = color; \n"
        "    gl_FragData[1] = vec4((oe_global_Normal+1.0)/2.0,1.0);\n"
        "    gl_FragData[2] = vec4(mrt_depth,mrt_depth,mrt_depth,1.0); \n"
        "}\n";

    VirtualProgram* vp = VirtualProgram::getOrCreate( rtt->getOrCreateStateSet() );
    vp->setFunction( "oe_mrt_vertex",   vertSource, ShaderComp::LOCATION_VERTEX_CLIP );
    vp->setFunction( "oe_mrt_fragment", fragSource, ShaderComp::LOCATION_FRAGMENT_OUTPUT );

    rtt->addChild( sceneGraph );
    return rtt;
}
Example #4
0
void
DepthOffsetAdapter::setGraph(osg::Node* graph)
{
    if ( !_supported ) return;

    bool graphChanging =
        _graph.get() != graph;

    bool uninstall =
        (_graph.valid() && _graph->getStateSet()) &&
        (graphChanging || (_options.enabled() == false));

    bool install =
        (graph && graphChanging ) || 
        (graph && (_options.enabled() == true));

    if ( uninstall )
    {
        OE_TEST << LC << "Removing depth offset shaders" << std::endl;

        // uninstall uniforms and shaders.
        osg::StateSet* s = _graph->getStateSet();
        s->removeUniform( _biasUniform.get() );
        s->removeUniform( _rangeUniform.get() );
        VirtualProgram* vp = VirtualProgram::get( s );
        if ( vp )
        {
            vp->removeShader( "oe_doff_vertex" );
            vp->removeShader( "oe_doff_fragment" );
        }
    }

    if ( install )
    {
        OE_TEST << LC << "Installing depth offset shaders" << std::endl;

        // install uniforms and shaders.
        osg::StateSet* s = graph->getOrCreateStateSet();
        s->addUniform( _biasUniform.get() );
        s->addUniform( _rangeUniform.get() );

        VirtualProgram* vp = VirtualProgram::getOrCreate( s );
        vp->setFunction( "oe_doff_vertex", s_vertex, ShaderComp::LOCATION_VERTEX_VIEW );
        vp->setFunction( "oe_doff_fragment", s_fragment, ShaderComp::LOCATION_FRAGMENT_COLORING );
        s->setAttributeAndModes( vp, osg::StateAttribute::ON );
    }

    if ( graphChanging )
    {
        _graph = graph;
    }

    // always set Dirty when setGraph is called sine it may be called anytime
    // the subgraph changes (as can be detected by a computeBound)
    _dirty = (_options.automatic() == true);
}
Example #5
0
void
SimpleOceanNode::rebuild()
{
    this->removeChildren( 0, this->getNumChildren() );

    osg::ref_ptr<MapNode> mapNode;
    if (_parentMapNode.lock(mapNode))
    {
        const MapOptions&     parentMapOptions     = mapNode->getMap()->getMapOptions();
        const MapNodeOptions& parentMapNodeOptions = mapNode->getMapNodeOptions();

        // set up the map to "match" the parent map:
        MapOptions mo;
        mo.coordSysType() = parentMapOptions.coordSysType();
        mo.profile()      = mapNode->getMap()->getProfile()->toProfileOptions();

        // new data model for the ocean:
        Map* oceanMap = new Map( mo );

        // ditto with the map node options:
        MapNodeOptions mno;
        if ( mno.enableLighting().isSet() )
            mno.enableLighting() = *mno.enableLighting();

        RexTerrainEngineOptions terrainoptions;

        terrainoptions.enableBlending() = true;        // gotsta blend with the main node

        terrainoptions.color() = baseColor().get();

        terrainoptions.tileSize() = 5;

        mno.setTerrainOptions( terrainoptions );

        // make the ocean's map node:
        MapNode* oceanMapNode = new MapNode( oceanMap, mno );

        // set up the shaders.
        osg::StateSet* ss = this->getOrCreateStateSet();

        // if the caller requested a mask layer, install that now.
        if ( maskLayer().isSet() )
        {
            if ( !maskLayer()->maxLevel().isSet() )
            {
                // set the max subdivision level if it's not already specified in the 
                // mask layer options:
                maskLayer()->maxLevel() = maxLOD().get();
            }

            // make sure the mask is shared (so we can access it from our shader)
            // and invisible (so we can't see it)
            maskLayer()->shared() = true;
            maskLayer()->visible() = false;

            ImageLayer* layer = new ImageLayer("ocean-mask", maskLayer().get());
            oceanMap->addLayer( layer );

            ss->setDefine("OE_SIMPLE_OCEAN_USE_MASK");
            OE_INFO << LC << "Using mask layer \"" << layer->getName() << "\"\n";
        }

        // otherwise, install a "proxy layer" that will use the elevation data in the map
        // to determine where the ocean is. This approach is limited in that it cannot
        // detect the difference between ocean and inland areas that are below sea level.
        else
        {
            // install an "elevation proxy" layer that reads elevation tiles from the
            // parent map and turns them into encoded images for our shader to use.
            ImageLayerOptions epo( "ocean-proxy" );
            epo.cachePolicy() = CachePolicy::NO_CACHE;
            epo.shared() = true;
            epo.visible() = false;
            epo.shareTexUniformName() = "oe_ocean_proxyTex";
            epo.shareTexMatUniformName() = "oe_ocean_proxyMat";
            oceanMap->addLayer( new ElevationProxyImageLayer(mapNode->getMap(), epo) );
            OE_INFO << LC << "Using elevation proxy layer\n";
        }

        this->addChild( oceanMapNode );

        // install the shaders on the ocean map node.
        VirtualProgram* vp = VirtualProgram::getOrCreate( ss );
        vp->setName( "osgEarth SimpleOcean" );        
        Shaders shaders;
        shaders.loadAll(vp, 0L);

        // set up the options uniforms.

        _seaLevel = new osg::Uniform(osg::Uniform::FLOAT, "ocean_seaLevel");
        ss->addUniform( _seaLevel.get() );

        _lowFeather = new osg::Uniform(osg::Uniform::FLOAT, "ocean_lowFeather");
        ss->addUniform( _lowFeather.get() );

        _highFeather = new osg::Uniform(osg::Uniform::FLOAT, "ocean_highFeather");
        ss->addUniform( _highFeather.get() );

        _baseColor = new osg::Uniform(osg::Uniform::FLOAT_VEC4, "ocean_baseColor");
        ss->addUniform( _baseColor.get() );

        _maxRange = new osg::Uniform(osg::Uniform::FLOAT, "ocean_max_range");
        ss->addUniform( _maxRange.get() );

        _fadeRange = new osg::Uniform(osg::Uniform::FLOAT, "ocean_fade_range");
        ss->addUniform( _fadeRange.get() );

        _alphaUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_ocean_alpha");
        ss->addUniform( _alphaUniform.get() );

        // disable depth writes.
        ss->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0.0, 1.0, false) );

        // load up a surface texture
        osg::ref_ptr<osg::Image> surfaceImage;
        if ( textureURI().isSet() )
        {
            surfaceImage = textureURI()->getImage();
        }

        //if ( !surfaceImage.valid() )
        //{
        //    surfaceImage = createSurfaceImage();
        //}

        if ( surfaceImage.valid() )
        {
            osg::Texture2D* tex = new osg::Texture2D( surfaceImage.get() );
            tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
            tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
            tex->setWrap  ( osg::Texture::WRAP_S, osg::Texture::REPEAT );
            tex->setWrap  ( osg::Texture::WRAP_T, osg::Texture::REPEAT );

            ss->setTextureAttributeAndModes( 5, tex, 1 );
            ss->getOrCreateUniform( "ocean_surface_tex", osg::Uniform::SAMPLER_2D )->set( 5 );

            ss->setDefine("OE_SIMPLE_OCEAN_USE_TEXTURE");
            OE_INFO << LC << "Using a surface texture (" << surfaceImage->getFileName() << ")\n";
        }

        // remove backface culling so we can see underwater
        // (use OVERRIDE since the terrain engine sets back face culling.)
        ss->setAttributeAndModes( 
            new osg::CullFace(), 
            osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE );

        // Material.
        osg::Material* m = new osgEarth::MaterialGL3();
        m->setAmbient(m->FRONT_AND_BACK, osg::Vec4(.5,.5,.5,1));
        m->setDiffuse(m->FRONT_AND_BACK, osg::Vec4(1,1,1,1));
        m->setSpecular(m->FRONT_AND_BACK, osg::Vec4(0.2,0.2,0.2,1));
        m->setEmission(m->FRONT_AND_BACK, osg::Vec4(0,0,0,1));
        m->setShininess(m->FRONT_AND_BACK, 40.0);
        ss->setAttributeAndModes(m, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );

        // force apply options:
        applyOptions();
    }
}
    osg::Node* run(osg::Node* earthfile)
    {
        // 32-bit vertex shader, for reference only. This shader will exceed
        // the single-precision capacity and cause "jumping verts" at the 
        // camera make small movements.
        const char* vs32 =
            "#version 330 \n"
            "uniform mat4 osg_ViewMatrixInverse; \n"
            "flat out float isRed; \n"

            "void vertex(inout vec4 v32) \n"
            "{ \n"
            "    vec4 world = osg_ViewMatrixInverse * v32; \n"
            "    world /= world.w; \n"
            "    float len = length(world); \n"

            "    const float R = 6371234.5678; \n"
            
            "    isRed = 0.0; \n"
            "    if (len > R) \n"
            "        isRed = 1.0;"

            "}\n";

        // 64-bit vertex shader. This shader uses a double-precision inverse
        // view matrix and calculates the altitude all in double precision;
        // therefore the "jumping verts" problem in the 32-bit version is 
        // resolved. (Mostly-- you will still see the jumping if you view the 
        // earth from orbit, because the 32-bit vertex itself is very far from
        // the camera in view coordinates. If that is an issue, you need to pass
        // in 64-bit vertex attributes.)
        const char* vs64 = 
            "#version 330 \n"
            "#extension GL_ARB_gpu_shader_fp64 : enable \n"
            "uniform dmat4 u_ViewMatrixInverse64; \n"            // must use a 64-bit VMI.
            "flat out float isRed; \n"
            "flat out double vary64; \n"                         // just to test shadercomp framework

            "void vertex(inout vec4 v32) \n"
            "{ \n"
            "    dvec4 v64 = dvec4(v32); \n"                     // upcast to 64-bit, no precision loss
                                                                 // unless camera is very far away

            "    dvec4 world = u_ViewMatrixInverse64 * v64; \n"  // xform into world coords
            "    world /= world.w; \n"                           // divide by w
            "    double len = length(world.xyz); \n"             // get double-precision vector length.

            "    const double R = 6371234.5678; \n"              // arbitrary earth radius threshold
            
            "    isRed = (len > R) ? 1.0 : 0.0; \n"
            "}\n";

        // frag shader: color the terrain red if the incoming varying is non-zero.
        const char* fs =
            "#version 330 \n"
            "#extension GL_ARB_gpu_shader_fp64 : enable \n"
            "flat in float isRed; \n"
            "flat in double vary64; \n"
            "void fragment(inout vec4 color) \n"
            "{ \n"
            "    if (isRed > 0.0f) { \n"
            "        color.r = 1.0; \n"
            "        color.gb *= 0.5; \n"
            "    } \n"
            "} \n";

        // installs a double-precision inverse view matrix for our shader to use.
        struct VMI64Callback : public osg::NodeCallback
        {
            void operator()(osg::Node* node, osg::NodeVisitor* nv)
            {
                osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);

                osg::Uniform* u = new osg::Uniform(osg::Uniform::DOUBLE_MAT4, "u_ViewMatrixInverse64");
                u->set(cv->getCurrentCamera()->getInverseViewMatrix());
                
                osg::ref_ptr<osg::StateSet> ss = new osg::StateSet();
                ss->addUniform(u);
                cv->pushStateSet(ss.get());

                traverse(node, nv);

                cv->popStateSet();
            }
        };
        earthfile->setCullCallback(new VMI64Callback());

        osg::StateSet* ss = earthfile->getOrCreateStateSet();
        VirtualProgram* vp = VirtualProgram::getOrCreate(ss);
        vp->setFunction("vertex",   vs64, ShaderComp::LOCATION_VERTEX_VIEW);
        vp->setFunction("fragment", fs,   ShaderComp::LOCATION_FRAGMENT_COLORING);


        return earthfile;
    }
Example #7
0
// 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;
    }
}
void
ClampingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
{
    // To store technique-specific per-view info:
    LocalPerViewData* local = new LocalPerViewData();
    params._techniqueData = local;

    // create the projected texture:
    local->_rttTexture = new osg::Texture2D();
    local->_rttTexture->setTextureSize( *_textureSize, *_textureSize );
    local->_rttTexture->setInternalFormat( GL_DEPTH_COMPONENT );
    local->_rttTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
    local->_rttTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );

    // this is important. geometry that is outside the depth texture will clamp to the
    // closest edge value in the texture -- this is good when you are rendering a 
    // primitive that has one or more of its verts off-screen.
    local->_rttTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
    local->_rttTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
    //local->_rttTexture->setBorderColor( osg::Vec4(0,0,0,1) );

    // set up the RTT camera:
    params._rttCamera = new osg::Camera();
    params._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT );
    params._rttCamera->setClearDepth( 1.0 );
    params._rttCamera->setClearMask( GL_DEPTH_BUFFER_BIT );
    params._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );
    params._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize );
    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::DEPTH_BUFFER, local->_rttTexture.get() );

#ifdef DUMP_RTT_IMAGE
    local->_rttDebugImage = new osg::Image();
    local->_rttDebugImage->allocateImage(4096, 4096, 1, GL_RGB, GL_UNSIGNED_BYTE);
    memset( (void*)local->_rttDebugImage->getDataPointer(), 0xff, local->_rttDebugImage->getTotalSizeInBytes() );
    params._rttCamera->attach( osg::Camera::COLOR_BUFFER, local->_rttDebugImage.get() );
    params._rttCamera->setFinalDrawCallback( new DumpTex(local->_rttDebugImage.get()) );
#endif

#ifdef TIME_RTT_CAMERA
    params._rttCamera->setInitialDrawCallback( new RttIn() );
    params._rttCamera->setFinalDrawCallback( new RttOut() );
#endif

    // set up a StateSet for the RTT camera.
    osg::StateSet* rttStateSet = params._rttCamera->getOrCreateStateSet();

    rttStateSet->setMode(
        GL_BLEND, 
        osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);

    // prevents wireframe mode in the depth camera.
    rttStateSet->setAttributeAndModes(
        new osg::PolygonMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL ),
        osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
    
    // attach the terrain to the camera.
    // todo: should probably protect this with a mutex.....
    params._rttCamera->addChild( _engine ); // the terrain itself.

    // assemble the overlay graph stateset.
    local->_groupStateSet = new osg::StateSet();

    // Required for now, otherwise GPU-clamped geometry will jitter sometimes.
    // TODO: figure out why and fix it. This is a workaround for now.
    local->_groupStateSet->setDataVariance( osg::Object::DYNAMIC );

    local->_groupStateSet->setTextureAttributeAndModes( 
        _textureUnit, 
        local->_rttTexture.get(), 
        osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );

    // set up depth test/write parameters for the overlay geometry:
    local->_groupStateSet->setAttributeAndModes(
        new osg::Depth( osg::Depth::LEQUAL, 0.0, 1.0, true ),
        osg::StateAttribute::ON );

    local->_groupStateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );

    // uniform for the horizon distance (== max clamping distance)
    local->_horizonDistanceUniform = local->_groupStateSet->getOrCreateUniform(
        "oe_clamp_horizonDistance",
        osg::Uniform::FLOAT );

    // sampler for depth map texture:
    local->_groupStateSet->getOrCreateUniform(
        "oe_clamp_depthTex", 
        osg::Uniform::SAMPLER_2D )->set( _textureUnit );

    // matrix that transforms a vert from EYE coords to the depth camera's CLIP coord.
    local->_camViewToDepthClipUniform = local->_groupStateSet->getOrCreateUniform( 
        "oe_clamp_cameraView2depthClip", 
        osg::Uniform::FLOAT_MAT4 );

#ifdef SUPPORT_Z

    // matrix that transforms a vert from depth clip coords to depth view coords.
    local->_depthClipToDepthViewUniform = local->_groupStateSet->getOrCreateUniform(
        "oe_clamp_depthClip2depthView",
        osg::Uniform::FLOAT_MAT4 );

    // matrix that transforms a vert from depth view coords to camera view coords.
    local->_depthViewToCamViewUniform = local->_groupStateSet->getOrCreateUniform(
        "oe_clamp_depthView2cameraView",
        osg::Uniform::FLOAT_MAT4 );

#else

    // matrix that transforms a vert from depth-cam CLIP coords to EYE coords.
    local->_depthClipToCamViewUniform = local->_groupStateSet->getOrCreateUniform( 
        "oe_clamp_depthClip2cameraView", 
        osg::Uniform::FLOAT_MAT4 );

#endif

    // make the shader that will do clamping and depth offsetting.
    VirtualProgram* vp = VirtualProgram::getOrCreate(local->_groupStateSet.get());
    vp->setName( "ClampingTechnique" );
    vp->setFunction( "oe_clamp_vertex",   clampingVertexShader,   ShaderComp::LOCATION_VERTEX_VIEW );
    vp->setFunction( "oe_clamp_fragment", clampingFragmentShader, ShaderComp::LOCATION_FRAGMENT_COLORING );
}
// Generates the main shader code for rendering the terrain.
void
MPTerrainEngineNode::updateState()
{
    if ( _batchUpdateInProgress )
    {
        _stateUpdateRequired = true;
    }
    else
    {
        osg::StateSet* terrainStateSet = _terrain->getOrCreateStateSet();
        
        // 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 );

            // bind the vertex attributes generated by the tile compiler.
            vp->addBindAttribLocation( "oe_terrain_attr",  osg::Drawable::ATTRIBUTE_6 );
            vp->addBindAttribLocation( "oe_terrain_attr2", osg::Drawable::ATTRIBUTE_7 );

            // Vertex shader:
            std::string vs = Stringify() <<
                "#version " GLSL_VERSION_STR "\n"
                GLSL_DEFAULT_PRECISION_FLOAT "\n"
                "varying vec4 oe_layer_texc;\n"
                "varying vec4 oe_layer_tilec;\n"
                "void oe_mp_setup_coloring(inout vec4 VertexModel) \n"
                "{ \n"
                "    oe_layer_texc  = gl_MultiTexCoord" << _primaryUnit << ";\n"
                "    oe_layer_tilec = gl_MultiTexCoord" << _secondaryUnit << ";\n"
                "}\n";

            bool useTerrainColor = _terrainOptions.color().isSet();

            bool useBlending = _terrainOptions.enableBlending() == true;

            // Fragment Shader for normal blending:
            std::string fs = Stringify() <<
                "#version " GLSL_VERSION_STR "\n"
                GLSL_DEFAULT_PRECISION_FLOAT "\n"
                "varying vec4 oe_layer_texc; \n"
                "uniform sampler2D oe_layer_tex; \n"
                "uniform int oe_layer_uid; \n"
                "uniform int oe_layer_order; \n"
                "uniform float oe_layer_opacity; \n"
                << (useTerrainColor ?
                "uniform vec4 oe_terrain_color; \n" : ""
                ) <<
                "void oe_mp_apply_coloring(inout vec4 color) \n"
                "{ \n"
                << (useTerrainColor ?
                "    color = oe_terrain_color; \n" : ""
                ) <<
                //"    color = vec4(1,1,1,1); \n"
                "    vec4 texel; \n"
                "    if ( oe_layer_uid >= 0 ) { \n"
                "        texel = texture2D(oe_layer_tex, oe_layer_texc.st); \n"
                "        texel.a *= oe_layer_opacity; \n"
                "    } \n"
                "    else \n"
                "        texel = color; \n"
                "    "
                << (useBlending ?
                "    if ( oe_layer_order == 0 ) \n"
                "        color = texel*texel.a + color*(1.0-texel.a); \n" // simulate src_alpha, 1-src_alpha blens
                "    else \n" : ""
                ) <<
                "        color = texel; \n"
                "} \n";

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

            vp->setFunction( "oe_mp_setup_coloring", vs, ShaderComp::LOCATION_VERTEX_MODEL, 0.0 );
            vp->setFunction( "oe_mp_apply_coloring", fs, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.0 );

            // assemble color filter code snippets.
            bool haveColorFilters = false;
            {
                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( 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.0 );
                }
            }

            // binding for the terrain texture
            terrainStateSet->getOrCreateUniform( 
                "oe_layer_tex", osg::Uniform::SAMPLER_2D )->set( _primaryUnit );

            // binding for the secondary texture (for LOD blending)
            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 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 );

            // base terrain color.
            if ( useTerrainColor )
            {
                terrainStateSet->getOrCreateUniform(
                    "oe_terrain_color", osg::Uniform::FLOAT_VEC4 )->set( *_terrainOptions.color() );
            }
        }

        _stateUpdateRequired = false;
    }
}
Example #10
0
bool
BillboardExtension::connect(MapNode* mapNode)
{
    if ( !mapNode )
    {
        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
        return false;
    }

    OE_INFO << LC << "Connecting to MapNode.\n";

    if ( !_options.imageURI().isSet() )
    {
        OE_WARN << LC << "Illegal: image URI is required" << std::endl;
        return false;
    }

    if ( !_options.featureOptions().isSet() )
    {
        OE_WARN << LC << "Illegal: feature source is required" << std::endl;
        return false;
    }
    
    _features = FeatureSourceFactory::create( _options.featureOptions().value() );
    if ( !_features.valid() )
    {
        OE_WARN << LC << "Illegal: no valid feature source provided" << std::endl;
        return false;
    }

    //if ( _features->getGeometryType() != osgEarth::Symbology::Geometry::TYPE_POINTSET )
    //{
    //    OE_WARN << LC << "Illegal: only points currently supported" << std::endl;
    //    return false;
    //}

    _features->initialize( _dbOptions );

    osg::Vec3dArray* verts;
    if ( _features->getFeatureProfile() )
    {
        verts = new osg::Vec3dArray();
        
        OE_NOTICE << "Reading features...\n";
        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor();
        while ( cursor.valid() && cursor->hasMore() )
        {
            Feature* f = cursor->nextFeature();
            if ( f && f->getGeometry() )
            {
                if ( f->getGeometry()->getComponentType() == Geometry::TYPE_POLYGON )
                {
                    FilterContext cx;
                    cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) );

                    ScatterFilter scatter;
                    scatter.setDensity( _options.density().get() );
                    scatter.setRandom( true );
                    FeatureList featureList;
                    featureList.push_back(f);
                    scatter.push( featureList, cx );
                }

                // Init a filter to tranform feature in desired SRS 
                if (!mapNode->getMapSRS()->isEquivalentTo(_features->getFeatureProfile()->getSRS()))
                {
                    FilterContext cx;
                    cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) );

                    TransformFilter xform( mapNode->getMapSRS() );
                    FeatureList featureList;
                    featureList.push_back(f);
                    cx = xform.push(featureList, cx);
                }

                GeometryIterator iter(f->getGeometry());
                while(iter.hasMore()) {
                    const Geometry* geom = iter.next();
                    osg::ref_ptr<osg::Vec3dArray> fVerts = geom->createVec3dArray();
                    verts->insert(verts->end(), fVerts->begin(), fVerts->end());
                }
            }
        }
    }
    else
    {
        OE_WARN << LC << "Illegal: feature source has no SRS" << std::endl;
        return false;
    }


    if ( verts && verts->size() > 0 )
    {
        OE_NOTICE << LC << "Read " << verts->size() << " points.\n";

        //localize all the verts
        GeoPoint centroid;
        _features->getFeatureProfile()->getExtent().getCentroid(centroid);
        centroid = centroid.transform(mapNode->getMapSRS());

        OE_NOTICE << "Centroid = " << centroid.x() << ", " << centroid.y() << "\n";

        osg::Matrixd l2w, w2l;
        centroid.createLocalToWorld(l2w);
        w2l.invert(l2w);

        osg::MatrixTransform* mt = new osg::MatrixTransform;
        mt->setMatrix(l2w);

        OE_NOTICE << "Clamping elevations...\n";
        osgEarth::ElevationQuery eq(mapNode->getMap());
        eq.setFallBackOnNoData( true );
        eq.getElevations(verts->asVector(), mapNode->getMapSRS(), true, 0.005);
        
        OE_NOTICE << "Building geometry...\n";
        osg::Vec3Array* normals = new osg::Vec3Array(verts->size());

        osg::Vec4Array* colors = new osg::Vec4Array(verts->size());
        Random rng;

        for (int i=0; i < verts->size(); i++)
        {
            GeoPoint vert(mapNode->getMapSRS(), (*verts)[i], osgEarth::ALTMODE_ABSOLUTE);

            osg::Vec3d world;
            vert.toWorld(world);
            (*verts)[i] = world * w2l;

            osg::Vec3 normal = world;
            normal.normalize();
            (*normals)[i] = osg::Matrix::transform3x3(normal, w2l);

            double n = rng.next();
            (*colors)[i].set( n, n, n, 1 );
        }

        //create geom and primitive sets
        osg::Geometry* geometry = new osg::Geometry();
        geometry->setVertexArray( verts );
        geometry->setNormalArray( normals );
        geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
        geometry->setColorArray(colors);
        geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

        geometry->addPrimitiveSet( new osg::DrawArrays( GL_POINTS, 0, verts->size() ) );

        //create image and texture to render to
        osg::Texture2D* tex = new osg::Texture2D(_options.imageURI()->getImage(_dbOptions));
        tex->setResizeNonPowerOfTwoHint(false);
        tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
        tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
        tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
        tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);

        geometry->setName("BillboardPoints");

        osg::Geode* geode = new osg::Geode;
        geode->addDrawable(geometry);

        //osg::ref_ptr<StateSetCache> cache = new StateSetCache();
        //Registry::shaderGenerator().run(geode, cache.get());

        //set the texture related uniforms
        osg::StateSet* geode_ss = geode->getOrCreateStateSet();
        geode_ss->setTextureAttributeAndModes( 2, tex, 1 );
        geode_ss->getOrCreateUniform("billboard_tex", osg::Uniform::SAMPLER_2D)->set( 2 );

        float bbWidth = (float)tex->getImage()->s() / 2.0f;
        float bbHeight = (float)tex->getImage()->t();
        float aspect = (float)tex->getImage()->s() / (float)tex->getImage()->t();
        if (_options.height().isSet())
        {
            bbHeight = _options.height().get();
            if (!_options.width().isSet())
            {
                bbWidth = bbHeight * aspect / 2.0f;
            }
        }
        if (_options.width().isSet())
        {
            bbWidth = _options.width().get() / 2.0f;
            if (!_options.height().isSet())
            {
                bbHeight = _options.width().get() / aspect;
            }
        }

        geode_ss->getOrCreateUniform("billboard_width", osg::Uniform::FLOAT)->set( bbWidth );
        geode_ss->getOrCreateUniform("billboard_height", osg::Uniform::FLOAT)->set( bbHeight );
        geode_ss->setMode(GL_BLEND, osg::StateAttribute::ON);

        //for now just using an osg::Program
        //TODO: need to add GeometryShader support to the shader comp setup
        VirtualProgram* vp = VirtualProgram::getOrCreate(geode_ss);
        vp->setName( "osgEarth Billboard Extension" );

        ShaderPackage shaders;
        shaders.add( "Billboard geometry shader", billboardGeomShader );
        shaders.add( "Billboard fragment shader", billboardFragShader );
        shaders.loadAll( vp );

        geode_ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
        geode->setCullingActive(false);

        mt->addChild(geode);
        mapNode->getModelLayerGroup()->addChild(mt);

        return true;
    }

    return false;
}
Example #11
0
void
SimpleOceanNode::rebuild()
{
    this->removeChildren( 0, this->getNumChildren() );

    if ( _parentMapNode.valid() )
    {
        const MapOptions&     parentMapOptions     = _parentMapNode->getMap()->getMapOptions();
        const MapNodeOptions& parentMapNodeOptions = _parentMapNode->getMapNodeOptions();

        // set up the map to "match" the parent map:
        MapOptions mo;
        mo.coordSysType() = parentMapOptions.coordSysType();
        mo.profile()      = _parentMapNode->getMap()->getProfile()->toProfileOptions();

        // new data model for the ocean:
        Map* oceanMap = new Map( mo );

        // ditto with the map node options:
        MapNodeOptions mno;
        if ( mno.enableLighting().isSet() )
            mno.enableLighting() = *mno.enableLighting();

        MPTerrainEngineOptions mpoptions;
        mpoptions.heightFieldSkirtRatio() = 0.0;      // don't want to see skirts
        mpoptions.minLOD() = _options.maxLOD().get(); // weird, I know

        // so we can the surface from underwater:
        mpoptions.clusterCulling() = false;       // want to see underwater

        mpoptions.enableBlending() = true;        // gotsta blend with the main node

        mpoptions.color() = _options.baseColor().get();

        mno.setTerrainOptions( mpoptions );

        // make the ocean's map node:
        MapNode* oceanMapNode = new MapNode( oceanMap, mno );

        // if the caller requested a mask layer, install that now.
        if ( _options.maskLayer().isSet() )
        {
            if ( !_options.maskLayer()->maxLevel().isSet() )
            {
                // set the max subdivision level if it's not already specified in the 
                // mask layer options:
                _options.maskLayer()->maxLevel() = *_options.maxLOD();
            }

            // make sure the mask is shared (so we can access it from our shader)
            // and invisible (so we can't see it)
            _options.maskLayer()->shared() = true;
            _options.maskLayer()->visible() = false;

            ImageLayer* maskLayer = new ImageLayer( "ocean-mask", *_options.maskLayer() );
            oceanMap->addImageLayer( maskLayer );
        }

        // otherwise, install a "proxy layer" that will use the elevation data in the map
        // to determine where the ocean is. This approach is limited in that it cannot
        // detect the difference between ocean and inland areas that are below sea level.
        else
        {
            // install an "elevation proxy" layer that reads elevation tiles from the
            // parent map and turns them into encoded images for our shader to use.
            ImageLayerOptions epo( "ocean-proxy" );
            epo.cachePolicy() = CachePolicy::NO_CACHE;
            //epo.maxLevel() = *_options.maxLOD();
            oceanMap->addImageLayer( new ElevationProxyImageLayer(_parentMapNode->getMap(), epo) );
        }

        this->addChild( oceanMapNode );

        // set up the shaders.
        osg::StateSet* ss = this->getOrCreateStateSet();

        // install the shaders on the ocean map node.
        VirtualProgram* vp = VirtualProgram::getOrCreate( ss );
        vp->setName( "osgEarth SimpleOcean" );

        // use the appropriate shader for the active technique:
        std::string vertSource = _options.maskLayer().isSet() ? source_vertMask : source_vertProxy;
        std::string fragSource = _options.maskLayer().isSet() ? source_fragMask : source_fragProxy;

        vp->setFunction( "oe_ocean_vertex",   vertSource, ShaderComp::LOCATION_VERTEX_VIEW );
        vp->setFunction( "oe_ocean_fragment", fragSource, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.6f );

        // install the slot attribute(s)
        ss->getOrCreateUniform( "ocean_data", osg::Uniform::SAMPLER_2D )->set( 0 );

        // set up the options uniforms.

        _seaLevel = new osg::Uniform(osg::Uniform::FLOAT, "ocean_seaLevel");
        ss->addUniform( _seaLevel.get() );

        _lowFeather = new osg::Uniform(osg::Uniform::FLOAT, "ocean_lowFeather");
        ss->addUniform( _lowFeather.get() );

        _highFeather = new osg::Uniform(osg::Uniform::FLOAT, "ocean_highFeather");
        ss->addUniform( _highFeather.get() );

        _baseColor = new osg::Uniform(osg::Uniform::FLOAT_VEC4, "ocean_baseColor");
        ss->addUniform( _baseColor.get() );

        _maxRange = new osg::Uniform(osg::Uniform::FLOAT, "ocean_max_range");
        ss->addUniform( _maxRange.get() );

        _fadeRange = new osg::Uniform(osg::Uniform::FLOAT, "ocean_fade_range");
        ss->addUniform( _fadeRange.get() );

        // trick to mitigate z-fighting..
        ss->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0.0, 1.0, false) );
        ss->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );

        // load up a surface texture
        osg::ref_ptr<osg::Image> surfaceImage;
        ss->getOrCreateUniform( "ocean_has_surface_tex", osg::Uniform::BOOL )->set( false );
        if ( _options.textureURI().isSet() )
        {
            //TODO: enable cache support here?
            surfaceImage = _options.textureURI()->getImage();
        }

        if ( !surfaceImage.valid() )
        {
            surfaceImage = createSurfaceImage();
        }

        if ( surfaceImage.valid() )
        {
            osg::Texture2D* tex = new osg::Texture2D( surfaceImage.get() );
            tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
            tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
            tex->setWrap  ( osg::Texture::WRAP_S, osg::Texture::REPEAT );
            tex->setWrap  ( osg::Texture::WRAP_T, osg::Texture::REPEAT );

            ss->setTextureAttributeAndModes( 2, tex, 1 );
            ss->getOrCreateUniform( "ocean_surface_tex", osg::Uniform::SAMPLER_2D )->set( 2 );
            ss->getOrCreateUniform( "ocean_has_surface_tex", osg::Uniform::BOOL )->set( true );
        }

        // remove backface culling so we can see underwater
        // (use OVERRIDE since the terrain engine sets back face culling.)
        ss->setAttributeAndModes( 
            new osg::CullFace(), 
            osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE );

        // Material.
        osg::Material* m = new osg::Material();
        m->setAmbient(m->FRONT_AND_BACK, osg::Vec4(0,0,0,1));
        m->setDiffuse(m->FRONT_AND_BACK, osg::Vec4(1,1,1,1));
        m->setSpecular(m->FRONT_AND_BACK, osg::Vec4(0.1,0.1,0.1,1));
        m->setEmission(m->FRONT_AND_BACK, osg::Vec4(0,0,0,1));
        m->setShininess(m->FRONT_AND_BACK, 32.0);
        ss->setAttributeAndModes(m, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );

        // force apply options:
        applyOptions();
    }
}
void
GroundCoverLayer::buildStateSets()
{
    // assert we have the necessary TIUs:
    if (_groundCoverTexBinding.valid() == false) {
        OE_DEBUG << LC << "buildStateSets deferred.. bindings not reserved\n";
        return;
    }

    if (!_zonesConfigured) {
        OE_DEBUG << LC << "buildStateSets deferred.. zones not yet configured\n";
        return;
    }
    
    osg::ref_ptr<LandCoverDictionary> landCoverDict;
    if (_landCoverDict.lock(landCoverDict) == false) {
        OE_DEBUG << LC << "buildStateSets deferred.. land cover dictionary not available\n";
        return;
    }
    
    osg::ref_ptr<LandCoverLayer> landCoverLayer;
    if (_landCoverLayer.lock(landCoverLayer) == false) {
        OE_DEBUG << LC << "buildStateSets deferred.. land cover layer not available\n";
        return;
    }

    NoiseTextureFactory noise;
    osg::ref_ptr<osg::Texture> noiseTexture = noise.create(256u, 4u);

    GroundCoverShaders shaders;

    // Layer-wide stateset:
    osg::StateSet* stateset = getOrCreateStateSet();

    // bind the noise sampler.
    stateset->setTextureAttribute(_noiseBinding.unit(), noiseTexture.get());
    stateset->addUniform(new osg::Uniform(NOISE_SAMPLER, _noiseBinding.unit()));

    if (_maskLayer.valid())
    {
        stateset->setDefine("OE_GROUNDCOVER_MASK_SAMPLER", _maskLayer->shareTexUniformName().get());
        stateset->setDefine("OE_GROUNDCOVER_MASK_MATRIX", _maskLayer->shareTexMatUniformName().get());
    }

    // disable backface culling to support shadow/depth cameras,
    // for which the geometry shader renders cross hatches instead of billboards.
    stateset->setMode(GL_CULL_FACE, osg::StateAttribute::PROTECTED);

    // enable alpha-to-coverage multisampling for vegetation.
    stateset->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, 1);

    // uniform that communicates the availability of multisampling.
    if (osg::DisplaySettings::instance()->getMultiSamples())
    {
        stateset->setDefine("OE_GROUNDCOVER_HAS_MULTISAMPLES");
    }

    stateset->setAttributeAndModes(
        new osg::BlendFunc(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO),
        osg::StateAttribute::OVERRIDE);


    for (Zones::iterator z = _zones.begin(); z != _zones.end(); ++z)
    {
        Zone* zone = z->get();
        GroundCover* groundCover = zone->getGroundCover();
        if (groundCover)
        {
            if (!groundCover->getBiomes().empty() || groundCover->getTotalNumBillboards() > 0)
            {
                osg::StateSet* zoneStateSet = groundCover->getOrCreateStateSet();
                            
                // Install the land cover shaders on the state set
                VirtualProgram* vp = VirtualProgram::getOrCreate(zoneStateSet);
                vp->setName("Ground cover (" + groundCover->getName() + ")");
                shaders.loadAll(vp, getReadOptions());

                // Generate the coverage acceptor shader
                osg::Shader* covTest = groundCover->createPredicateShader(_landCoverDict.get(), _landCoverLayer.get());
                covTest->setName(covTest->getName() + "_GEOMETRY");
                covTest->setType(osg::Shader::GEOMETRY);
                vp->setShader(covTest);

                osg::Shader* covTest2 = groundCover->createPredicateShader(_landCoverDict.get(), _landCoverLayer.get());
                covTest->setName(covTest->getName() + "_TESSCONTROL");
                covTest2->setType(osg::Shader::TESSCONTROL);
                vp->setShader(covTest2);

                osg::ref_ptr<osg::Shader> layerShader = groundCover->createShader();
                layerShader->setType(osg::Shader::GEOMETRY);
                vp->setShader(layerShader.get());

                OE_INFO << LC << "Established zone \"" << zone->getName() << "\" at LOD " << getLOD() << "\n";

                osg::Texture* tex = groundCover->createTexture();

                zoneStateSet->setTextureAttribute(_groundCoverTexBinding.unit(), tex);
                zoneStateSet->addUniform(new osg::Uniform(GCTEX_SAMPLER, _groundCoverTexBinding.unit()));

                OE_DEBUG << LC << "buildStateSets completed!\n";
            }
            else
            {
                OE_WARN << LC << "ILLEGAL: ground cover layer with no biomes or no billboards defined\n";
            }
        }
        else
        {
            // not an error.
            OE_DEBUG << LC << "zone contains no ground cover information\n";
        }
    }
}
osg::Node*
ExtrudeGeometryFilter::push( FeatureList& input, FilterContext& context )
{
    reset( context );

    // minimally, we require an extrusion symbol.
    if ( !_extrusionSymbol.valid() )
    {
        OE_WARN << LC << "Missing required extrusion symbolology; geometry will be empty" << std::endl;
        return new osg::Group();
    }

    // establish the active resource library, if applicable.
    _wallResLib = 0L;
    _roofResLib = 0L;

    const StyleSheet* sheet = context.getSession() ? context.getSession()->styles() : 0L;

    if ( sheet != 0L )
    {
        if ( _wallSkinSymbol.valid() && _wallSkinSymbol->libraryName().isSet() )
        {
            _wallResLib = sheet->getResourceLibrary( *_wallSkinSymbol->libraryName() );

            if ( !_wallResLib.valid() )
            {
                OE_WARN << LC << "Unable to load resource library '" << *_wallSkinSymbol->libraryName() << "'"
                    << "; wall geometry will not be textured." << std::endl;
                _wallSkinSymbol = 0L;
            }
        }

        if ( _roofSkinSymbol.valid() && _roofSkinSymbol->libraryName().isSet() )
        {
            _roofResLib = sheet->getResourceLibrary( *_roofSkinSymbol->libraryName() );
            if ( !_roofResLib.valid() )
            {
                OE_WARN << LC << "Unable to load resource library '" << *_roofSkinSymbol->libraryName() << "'"
                    << "; roof geometry will not be textured." << std::endl;
                _roofSkinSymbol = 0L;
            }
        }
    }

    // calculate the localization matrices (_local2world and _world2local)
    computeLocalizers( context );

    // push all the features through the extruder.
    bool ok = process( input, context );

    // convert everything to triangles and combine drawables.
    if ( _mergeGeometry == true && _featureNameExpr.empty() )
    {
        for( SortedGeodeMap::iterator i = _geodes.begin(); i != _geodes.end(); ++i )
        {
            MeshConsolidator::run( *i->second.get() );
        }
    }

    // parent geometry with a delocalizer (if necessary)
    osg::Group* group = createDelocalizeGroup();
    
    // combines geometries where the statesets are the same.
    for( SortedGeodeMap::iterator i = _geodes.begin(); i != _geodes.end(); ++i )
    {
        group->addChild( i->second.get() );
    }
    _geodes.clear();

    // if we drew outlines, apply a poly offset too.
    if ( _outlineSymbol.valid() )
    {
        osg::StateSet* groupStateSet = group->getOrCreateStateSet();
        groupStateSet->setAttributeAndModes( new osg::PolygonOffset(1,1), 1 );
        if ( _outlineSymbol->stroke()->width().isSet() )
            groupStateSet->setAttributeAndModes( new osg::LineWidth(*_outlineSymbol->stroke()->width()), 1 );
    }

    // if we have textures, install a shader to draw them
    if ( _wallSkinSymbol.valid() || _roofSkinSymbol.valid() )
    {
        osg::StateSet* stateSet = group->getOrCreateStateSet();

        VirtualProgram* vp = new VirtualProgram();
        vp->setName("ExtrudeGeomFilter");
        vp->installDefaultColoringShaders( 1 );
        stateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );

        // a default empty texture will support any non-textured geometry 
        osg::Texture2D* tex = new osg::Texture2D( ImageUtils::createEmptyImage() );
        tex->setUnRefImageDataAfterApply( false );
        stateSet->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
        stateSet->getOrCreateUniform("tex0", osg::Uniform::SAMPLER_2D)->set(0);
    }

    return group;
}
    /**
     * Creates a complete set of positioned label nodes from a feature list.
     */
    osg::Node* createNode(
        const FeatureList&   input,
        const Style&         style,
        const FilterContext& context )
    {
        if ( style.get<TextSymbol>() == 0L && style.get<IconSymbol>() == 0L )
            return 0L;

        // copy the style so we can (potentially) modify the text symbol.
        Style styleCopy = style;
        TextSymbol* text = styleCopy.get<TextSymbol>();
        IconSymbol* icon = styleCopy.get<IconSymbol>();

        osg::Group* group = new osg::Group();
        
        StringExpression  textContentExpr ( text ? *text->content()  : StringExpression() );
        NumericExpression textPriorityExpr( text ? *text->priority() : NumericExpression() );
        NumericExpression textSizeExpr    ( text ? *text->size()     : NumericExpression() );
        StringExpression  iconUrlExpr     ( icon ? *icon->url()      : StringExpression() );
        NumericExpression iconScaleExpr   ( icon ? *icon->scale()    : NumericExpression() );
        NumericExpression iconHeadingExpr ( icon ? *icon->heading()  : NumericExpression() );

        for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i )
        {
            const Feature* feature = i->get();
            if ( !feature )
                continue;

            const Geometry* geom = feature->getGeometry();
            if ( !geom )
                continue;

            Style tempStyle = styleCopy;

            // evaluate expressions into literals.
            // TODO: Later we could replace this with a generate "expression evaluator" type
            // that we could pass to PlaceNode in the DB options. -gw

            if ( text )
            {
                if ( text->content().isSet() )
                    tempStyle.get<TextSymbol>()->content()->setLiteral( feature->eval( textContentExpr, &context ) );

                if ( text->size().isSet() )
                    tempStyle.get<TextSymbol>()->size()->setLiteral( feature->eval(textSizeExpr, &context) );
            }

            if ( icon )
            {
                if ( icon->url().isSet() )
                    tempStyle.get<IconSymbol>()->url()->setLiteral( feature->eval(iconUrlExpr, &context) );

                if ( icon->scale().isSet() )
                    tempStyle.get<IconSymbol>()->scale()->setLiteral( feature->eval(iconScaleExpr, &context) );

                if ( icon->heading().isSet() )
                    tempStyle.get<IconSymbol>()->heading()->setLiteral( feature->eval(iconHeadingExpr, &context) );
            }
            
            osg::Node* node = makePlaceNode(
                context,
                feature,
                tempStyle,
                textPriorityExpr);

            if ( node )
            {
                if ( context.featureIndex() )
                {
                    context.featureIndex()->tagNode(node, const_cast<Feature*>(feature));
                }

                group->addChild( node );
            }
        }

        VirtualProgram* vp = VirtualProgram::getOrCreate(group->getOrCreateStateSet());
        vp->setInheritShaders( false );

        return group;
    }
Example #15
0
bool
ShaderGenerator::processGeometry( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& replacement )
{
    // do nothing if there's no GLSL support
    if ( !Registry::capabilities().supportsGLSL() )
        return false;

    // State object with extra accessors:
    StateEx* state = static_cast<StateEx*>(_state.get());

    // check for a real osg::Program in the whole state stack. If it exists, bail out
    // so that OSG can use the program already in the graph. We never override a
    // full Program.
    osg::StateAttribute* program = state->getAttribute(osg::StateAttribute::PROGRAM);
    if ( dynamic_cast<osg::Program*>(program) != 0L )
        return false;

    // see if the current state set contains a VirtualProgram already. If so,
    // we will add to it if necessary.
    VirtualProgram* vp = dynamic_cast<VirtualProgram*>( ss->getAttribute(VirtualProgram::SA_TYPE) );

    // Check whether the lighting state has changed and install a mode uniform.
    if ( ss->getMode(GL_LIGHTING) != osg::StateAttribute::INHERIT )
    {
        if ( !replacement.valid() ) 
            replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL);

        ShaderFactory* sf = Registry::instance()->getShaderFactory();
        osg::StateAttribute::GLModeValue value = state->getMode(GL_LIGHTING); // from the state, not the ss.
        replacement->addUniform( sf->createUniformForGLMode(GL_LIGHTING, value) );
    }

    // if the stateset changes any texture attributes, we need a new virtual program:
    if (ss->getTextureAttributeList().size() > 0)
    {
        if ( !replacement.valid() ) 
            replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL);

        // work off the state's accumulated texture attribute set:
        int texCount = state->getNumTextureAttributes();

        if ( !vp )
        {
            vp = osg::clone( _defaultVP.get() );
            replacement->setAttributeAndModes( vp, osg::StateAttribute::ON );
        }

        // start generating the shader source.
        std::stringstream vertHead, vertBody, fragHead, fragBody;

        // compatibility strings make it work in GL or GLES.
        vertHead << "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION;
        fragHead << "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION;

        // function declarations:
        vertBody << "void " VERTEX_FUNCTION "()\n{\n";

        fragBody << "void " FRAGMENT_FUNCTION "(inout vec4 color)\n{\n";

        for( int t = 0; t < texCount; ++t )
        {
            if (t == 0)
            {
                fragBody << INDENT << MEDIUMP "vec4 texel; \n";
            }

            osg::StateAttribute* tex = state->getTextureAttribute( t, osg::StateAttribute::TEXTURE );
            if ( tex )
            {
                // see if we have a texenv; if so get its blending mode.
                osg::TexEnv::Mode blendingMode = osg::TexEnv::MODULATE;
                osg::TexEnv* env = dynamic_cast<osg::TexEnv*>(state->getTextureAttribute(t, osg::StateAttribute::TEXENV) );
                if ( env )
                {
                    blendingMode = env->getMode();
                    if ( blendingMode == osg::TexEnv::BLEND )
                    {
                        replacement->getOrCreateUniform( Stringify() << TEXENV_COLOR << t, osg::Uniform::FLOAT_VEC4 )->set( env->getColor() );
                    }
                }

                vertHead << "varying " MEDIUMP "vec4 " TEX_COORD << t << ";\n";
                vertBody << INDENT << TEX_COORD << t << " = gl_MultiTexCoord" << t << ";\n";

                fragHead << "varying " MEDIUMP "vec4 " TEX_COORD << t << ";\n";

                if ( dynamic_cast<osg::Texture1D*>(tex) )
                {
                    fragHead << "uniform sampler1D " SAMPLER << t << ";\n";
                    fragBody << INDENT "texel = texture1D(" SAMPLER << t << ", " TEX_COORD << t << ".x);\n";
                    replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_1D )->set( t );
                }
                else if ( dynamic_cast<osg::Texture2D*>(tex) )
                {
                    fragHead << "uniform sampler2D " SAMPLER << t << ";\n";
                    fragBody << INDENT "texel = texture2D(" SAMPLER << t << ", " TEX_COORD << t << ".xy);\n";
                    replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t );
                }
                else if ( dynamic_cast<osg::Texture3D*>(tex) )
                {
                    fragHead << "uniform sampler3D " SAMPLER << t << ";\n";
                    fragBody << INDENT "texel = texture3D(" SAMPLER << t << ", " TEX_COORD << t << ".xyz);\n";
                    replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_3D )->set( t );
                }

                // See http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
                switch( blendingMode )
                {
                case osg::TexEnv::REPLACE:
                    fragBody
                        << INDENT "color = texel; \n";
                    break;
                case osg::TexEnv::MODULATE:
                    fragBody
                        << INDENT "color = color * texel; \n";
                    break;
                case osg::TexEnv::DECAL:
                    fragBody
                        << INDENT "color.rgb = color.rgb * (1.0 - texel.a) + (texel.rgb * texel.a); \n";
                    break;
                case osg::TexEnv::BLEND:
                    fragHead
                        << "uniform " MEDIUMP "vec4 " TEXENV_COLOR << t << "\n;";
                    fragBody
                        << INDENT "color.rgb = color.rgb * (1.0 - texel.rgb) + (" << TEXENV_COLOR << t << ".rgb * texel.rgb); \n"
                        << INDENT "color.a   = color.a * texel.a; \n";
                    break;
                case osg::TexEnv::ADD:
                default:
                    fragBody
                        << INDENT "color.rgb = color.rgb + texel.rgb; \n"
                        << INDENT "color.a   = color.a * texel.a; \n";
                }
            }
        }

        // close out functions:
        vertBody << "}\n";
        fragBody << "}\n";

        // Extract the shader source strings (win compat method)
        std::string vertBodySrc, vertSrc, fragBodySrc, fragSrc;
        vertBodySrc = vertBody.str();
        vertHead << vertBodySrc;
        vertSrc = vertHead.str();
        fragBodySrc = fragBody.str();
        fragHead << fragBodySrc;
        fragSrc = fragHead.str();

        // inject the shaders:
        vp->setFunction( VERTEX_FUNCTION,   vertSrc, ShaderComp::LOCATION_VERTEX_PRE_LIGHTING );
        vp->setFunction( FRAGMENT_FUNCTION, fragSrc, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
    }

    return replacement.valid();
}
Example #16
0
osg::Node*
PolygonizeLinesFilter::push(FeatureList& input, FilterContext& cx)
{
    // compute the coordinate localization matrices.
    computeLocalizers( cx );

    // establish some things
    bool                    makeECEF   = false;
    const SpatialReference* featureSRS = 0L;
    const SpatialReference* mapSRS     = 0L;

    if ( cx.isGeoreferenced() )
    {
        makeECEF   = cx.getSession()->getMapInfo().isGeocentric();
        featureSRS = cx.extent()->getSRS();
        mapSRS     = cx.getSession()->getMapInfo().getProfile()->getSRS();
    }

    // The operator we'll use to make lines into polygons.
    const LineSymbol* line = _style.get<LineSymbol>();
    PolygonizeLinesOperator polygonize( line ? (*line->stroke()) : Stroke() );

    // Geode to hold all the geometries.
    osg::Geode* geode = new osg::Geode();

    // iterate over all features.
    for( FeatureList::iterator i = input.begin(); i != input.end(); ++i )
    {
        Feature* f = i->get();

        // iterate over all the feature's geometry parts. We will treat
        // them as lines strings.
        GeometryIterator parts( f->getGeometry(), false );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();

            // skip empty geometry
            if ( part->size() == 0 )
                continue;

            // transform the geometry into the target SRS and localize it about 
            // a local reference point.
            osg::Vec3Array* verts   = new osg::Vec3Array();
            osg::Vec3Array* normals = new osg::Vec3Array();
            transformAndLocalize( part->asVector(), featureSRS, verts, normals, mapSRS, _world2local, makeECEF );

            // turn the lines into polygons.
            osg::Geometry* geom = polygonize( verts, normals );
            geode->addDrawable( geom );

            // record the geometry's primitive set(s) in the index:
            if ( cx.featureIndex() )
                cx.featureIndex()->tagPrimitiveSets( geom, f );
        }
    }

    // attempt to combine geometries for better performance
    MeshConsolidator::run( *geode );

    // GPU performance optimization:
    VertexCacheOptimizer vco;
    geode->accept( vco );

    // If we're auto-scaling, we need a shader
    float minPixels = line ? line->stroke()->minPixels().getOrUse( 0.0f ) : 0.0f;
    if ( minPixels > 0.0f )
    {
        osg::StateSet* stateSet = geode->getOrCreateStateSet();

        VirtualProgram* vp = VirtualProgram::getOrCreate(stateSet);
        vp->setName( "osgEarth::PolygonizeLines" );

        const char* vs =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "attribute vec3   oe_polyline_center; \n"
            "uniform   float  oe_polyline_scale;  \n"
            "uniform   float  oe_polyline_min_pixels; \n"
            "uniform   mat3   oe_WindowScaleMatrix; \n"

            "void oe_polyline_scalelines(inout vec4 VertexMODEL) \n"
            "{ \n"
            "   if ( oe_polyline_scale != 1.0 || oe_polyline_min_pixels > 0.0 ) \n"
            "   { \n"
            "       vec4  center_model = vec4(oe_polyline_center*VertexMODEL.w, VertexMODEL.w); \n"
            "       vec4  vector_model = VertexMODEL - center_model; \n"
            "       if ( length(vector_model.xyz) > 0.0 ) \n"
            "       { \n"
            "           float scale = oe_polyline_scale; \n"

            "           vec4 vertex_clip = gl_ModelViewProjectionMatrix * VertexMODEL; \n"
            "           vec4 center_clip = gl_ModelViewProjectionMatrix * center_model; \n"
            "           vec4 vector_clip = vertex_clip - center_clip; \n"

            "           if ( oe_polyline_min_pixels > 0.0 ) \n"
            "           { \n"
            "               vec3 vector_win = oe_WindowScaleMatrix * (vertex_clip.xyz/vertex_clip.w - center_clip.xyz/center_clip.w); \n"
            "               float min_scale = max( (0.5*oe_polyline_min_pixels)/length(vector_win.xy), 1.0 ); \n"
            "               scale = max( scale, min_scale ); \n"
            "           } \n"

            "           VertexMODEL = center_model + vector_model*scale; \n"
            "        } \n"
            "    } \n"
            "} \n";

        vp->setFunction( "oe_polyline_scalelines", vs, ShaderComp::LOCATION_VERTEX_MODEL );
        vp->addBindAttribLocation( "oe_polyline_center", osg::Drawable::ATTRIBUTE_6 );

        // add the default scaling uniform.
        // good way to test:
        //    osgearth_viewer earthfile --uniform oe_polyline_scale 1.0 10.0
        osg::Uniform* scaleU = new osg::Uniform(osg::Uniform::FLOAT, "oe_polyline_scale");
        scaleU->set( 1.0f );
        stateSet->addUniform( scaleU, 1 );

        // the default "min pixels" uniform.
        osg::Uniform* minPixelsU = new osg::Uniform(osg::Uniform::FLOAT, "oe_polyline_min_pixels");
        minPixelsU->set( minPixels );
        stateSet->addUniform( minPixelsU, 1 );
    }

    return delocalize( geode );
}
Example #17
0
void
OverlayDecorator::initSubgraphShaders( osg::StateSet* set )
{
    VirtualProgram* vp = new VirtualProgram();
    vp->setName( "OverlayDecorator subgraph shader" );
    set->setAttributeAndModes( vp, osg::StateAttribute::ON );

    // sampler for projected texture:
    set->getOrCreateUniform( "osgearth_overlay_ProjTex", osg::Uniform::SAMPLER_2D )->set( *_textureUnit );

    // the texture projection matrix uniform.
    _texGenUniform = set->getOrCreateUniform( "osgearth_overlay_TexGenMatrix", osg::Uniform::FLOAT_MAT4 );

    std::stringstream buf;

    // vertex shader - subgraph
    buf << "#version 110 \n"
        << "uniform mat4 osgearth_overlay_TexGenMatrix; \n"
        << "uniform mat4 osg_ViewMatrixInverse; \n"

        << "void osgearth_overlay_vertex(void) \n"
        << "{ \n"
        << "    gl_TexCoord["<< *_textureUnit << "] = osgearth_overlay_TexGenMatrix * osg_ViewMatrixInverse * gl_ModelViewMatrix * gl_Vertex; \n"
        << "} \n";

    std::string vertexSource = buf.str();
    vp->setFunction( "osgearth_overlay_vertex", vertexSource, ShaderComp::LOCATION_VERTEX_POST_LIGHTING );

    // fragment shader - subgraph
    buf.str("");
    buf << "#version 110 \n"
        << "uniform sampler2D osgearth_overlay_ProjTex; \n";

    if ( _useWarping )
    {
        buf << "uniform float warp; \n"

            // because the built-in pow() is busted
            << "float mypow( in float x, in float y ) \n"
            << "{ \n"
            << "    return x/(x+y-y*x); \n"
            << "} \n"

            << "vec2 warpTexCoord( in vec2 src ) \n"
            << "{ \n"
            //      incoming tex coord is [0..1], so we scale to [-1..1]
            << "    vec2 srcn = vec2( src.x*2.0 - 1.0, src.y*2.0 - 1.0 ); \n" 

            //      we want to work in the [0..1] space on each side of 0, so can the abs
            //      and store the signs for later:
            << "    vec2 srct = vec2( abs(srcn.x), abs(srcn.y) ); \n"
            << "    vec2 sign = vec2( srcn.x > 0.0 ? 1.0 : -1.0, srcn.y > 0.0 ? 1.0 : -1.0 ); \n"

            //      apply the deformation using a deceleration curve:
            << "    vec2 srcp = vec2( 1.0-mypow(1.0-srct.x,warp), 1.0-mypow(1.0-srct.y,warp) ); \n"

            //      reapply the sign, and scale back to [0..1]:
            << "    vec2 srcr = vec2( sign.x*srcp.x, sign.y*srcp.y ); \n"
            << "    return vec2( 0.5*(srcr.x + 1.0), 0.5*(srcr.y + 1.0) ); \n"
            << "} \n";
    }

    buf << "void osgearth_overlay_fragment( inout vec4 color ) \n"
        << "{ \n"
        << "    vec2 texCoord = gl_TexCoord["<< *_textureUnit << "].xy / gl_TexCoord["<< *_textureUnit << "].q; \n";

    if ( _useWarping && !_visualizeWarp )
        buf  << "    texCoord = warpTexCoord( texCoord ); \n";

    buf << "    vec4 texel = texture2D(osgearth_overlay_ProjTex, texCoord); \n"  
        << "    color = vec4( mix( color.rgb, texel.rgb, texel.a ), color.a); \n"
        << "} \n";

    std::string fragmentSource = buf.str();
    vp->setFunction( "osgearth_overlay_fragment", fragmentSource, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
}
Example #18
0
// Generates the main shader code for rendering the terrain.
void
MPTerrainEngineNode::updateShaders()
{
    if ( _batchUpdateInProgress )
    {
        _shaderUpdateRequired = true;
    }
    else
    {
        osg::StateSet* terrainStateSet = _terrain->getOrCreateStateSet();

        VirtualProgram* vp = new VirtualProgram();
        vp->setName( "engine_mp:TerrainNode" );
        terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );

        // bind the vertex attributes generated by the tile compiler.
        vp->addBindAttribLocation( "oe_terrain_attr",  osg::Drawable::ATTRIBUTE_6 );
        vp->addBindAttribLocation( "oe_terrain_attr2", osg::Drawable::ATTRIBUTE_7 );

        // Vertex shader template:
        std::string vs =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "varying vec4 oe_layer_texc;\n"
            "varying vec4 oe_layer_tilec;\n"
            "void oe_mp_setup_coloring(inout vec4 VertexModel) \n"
            "{ \n"
            "    oe_layer_texc  = __GL_MULTITEXCOORD1__;\n"
            "    oe_layer_tilec = __GL_MULTITEXCOORD2__;\n"
            "}\n";

        // Fragment shader for normal blending:
        std::string fs =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "varying vec4 oe_layer_texc; \n"
            "uniform sampler2D oe_layer_tex; \n"
            "uniform int oe_layer_uid; \n"
            "uniform int oe_layer_order; \n"
            "uniform float oe_layer_opacity; \n"
            "void oe_mp_apply_coloring( inout vec4 color ) \n"
            "{ \n"
            "    vec4 texel; \n"
            "    if ( oe_layer_uid >= 0 ) { \n"
            "        texel = texture2D(oe_layer_tex, oe_layer_texc.st); \n"
            "        texel.a *= oe_layer_opacity; \n"
            "    } \n"
            "    else \n"
            "        texel = color; \n"
            "    if (oe_layer_order == 0 ) \n"
            "        color = texel*texel.a + color*(1.0-texel.a); \n" // simulate src_alpha, 1-src_alpha blens
            "    else \n"
            "        color = texel; \n"
            "} \n";

        // Fragment shader with pre-multiplied alpha blending:
        std::string fs_pma =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "varying vec4 oe_layer_texc; \n"
            "uniform sampler2D oe_layer_tex; \n"
            "uniform int oe_layer_uid; \n"
            "uniform int oe_layer_order; \n"
            "uniform float oe_layer_opacity; \n"
            "void oe_mp_apply_coloring_pma( inout vec4 color ) \n"
            "{ \n"
            "    vec4 texelpma; \n"

            // a UID < 0 means no texture.
            "    if ( oe_layer_uid >= 0 ) \n"
            "        texelpma = texture2D(oe_layer_tex, oe_layer_texc.st) * oe_layer_opacity; \n"
            "    else \n"
            "        texelpma = color * color.a * oe_layer_opacity; \n" // to PMA.

            // first layer must PMA-blend with the globe color.
            "    if (oe_layer_order == 0) { \n"
            "        color.rgb *= color.a; \n"
            "        color = texelpma + color*(1.0-texelpma.a); \n" // simulate one, 1-src_alpha blend
            "    } \n"

            "    else { \n"
            "        color = texelpma; \n"
            "    } \n"
            "} \n";

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


        // install the gl_MultiTexCoord* variable that uses the proper texture
        // image unit:
        replaceIn( vs, "__GL_MULTITEXCOORD1__", Stringify() << "gl_MultiTexCoord" << _primaryUnit );
        replaceIn( vs, "__GL_MULTITEXCOORD2__", Stringify() << "gl_MultiTexCoord" << _secondaryUnit );

        vp->setFunction( "oe_mp_setup_coloring", vs, ShaderComp::LOCATION_VERTEX_MODEL, 0.0 );

        if ( _terrainOptions.premultipliedAlpha() == true )
            vp->setFunction( "oe_mp_apply_coloring_pma", fs_pma, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.0 );
        else
            vp->setFunction( "oe_mp_apply_coloring", fs, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.0 );


        // assemble color filter code snippets.
        bool haveColorFilters = false;
        {
            std::stringstream cf_head;
            std::stringstream cf_body;
            const char* I = "    ";

            if ( _terrainOptions.premultipliedAlpha() == true )
            {
                // un-PMA the color before passing it to the color filters.
                cf_body << I << "if (color.a > 0.0) color.rgb /= color.a; \n";
            }

            // 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( terrainStateSet );
                        }
                        cf_body << I << "}\n";
                        ifStarted = true;
                    }
                }
            }

            if ( _terrainOptions.premultipliedAlpha() == true )
            {
                // re-PMA the color after it passes through the color filters.
                cf_body << I << "color.rgb *= color.a; \n";
            }

            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.0 );
            }
        }



        if ( _terrainOptions.premultipliedAlpha() == true )
        {
            // activate PMA blending.
            terrainStateSet->setAttributeAndModes( 
                new osg::BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),
                osg::StateAttribute::ON );
        }
        else
        {
            // activate standard mix blending.
            terrainStateSet->setAttributeAndModes( 
                new osg::BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA),
                osg::StateAttribute::ON );
        }

        // required for multipass tile rendering to work
        terrainStateSet->setAttributeAndModes(
            new osg::Depth(osg::Depth::LEQUAL, 0, 1, true) );

        // binding for the terrain texture
        terrainStateSet->getOrCreateUniform( 
            "oe_layer_tex", osg::Uniform::SAMPLER_2D )->set( _primaryUnit );

        // binding for the secondary texture (for LOD blending)
        terrainStateSet->getOrCreateUniform(
            "oe_layer_tex_parent", osg::Uniform::SAMPLER_2D )->set( _secondaryUnit );

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

        _shaderUpdateRequired = false;
    }
}
Example #19
0
void
VirtualProgram::apply( osg::State& state ) const
{
    if (_shaderMap.empty() && !_inheritSet)
    {
        // If there's no data in the VP, and never has been, unload any existing program.
        // NOTE: OSG's State processor creates a "global default attribute" for each type.
        // Sine we have no way of knowing whether the user created the VP or OSG created it
        // as the default fallback, we use the "_inheritSet" flag to differeniate. This
        // prevents any shader leakage from a VP-enabled node.
        const unsigned int contextID = state.getContextID();
        const osg::GL2Extensions* extensions = osg::GL2Extensions::Get(contextID,true);
        if( ! extensions->isGlslSupported() ) return;

        extensions->glUseProgram( 0 );
        state.setLastAppliedProgramObject(0);
        return;
    }

    // first, find and collect all the VirtualProgram attributes:
    ShaderMap         accumShaderMap;
    AttribBindingList accumAttribBindings;
    AttribAliasMap    accumAttribAliases;
    
    if ( _inherit )
    {
        const StateHack::AttributeVec* av = StateHack::GetAttributeVec( state, this );
        if ( av && av->size() > 0 )
        {
            // find the deepest VP that doesn't inherit:
            unsigned start = 0;
            for( start = (int)av->size()-1; start > 0; --start )
            {
                const VirtualProgram* vp = dynamic_cast<const VirtualProgram*>( (*av)[start].first );
                if ( vp && (vp->_mask & _mask) && vp->_inherit == false )
                    break;
            }
            
            // collect shaders from there to here:
            for( unsigned i=start; i<av->size(); ++i )
            {
                const VirtualProgram* vp = dynamic_cast<const VirtualProgram*>( (*av)[i].first );
                if ( vp && (vp->_mask && _mask) )
                {
                    for( ShaderMap::const_iterator i = vp->_shaderMap.begin(); i != vp->_shaderMap.end(); ++i )
                    {
                        addToAccumulatedMap( accumShaderMap, i->first, i->second );
                    }

                    const AttribBindingList& abl = vp->getAttribBindingList();
                    accumAttribBindings.insert( abl.begin(), abl.end() );

                    const AttribAliasMap& aliases = vp->getAttribAliases();
                    accumAttribAliases.insert( aliases.begin(), aliases.end() );
                }
            }
        }
    }
    
    // next add the local shader components to the map, respecting the override values:
    for( ShaderMap::const_iterator i = _shaderMap.begin(); i != _shaderMap.end(); ++i )
    {
        addToAccumulatedMap( accumShaderMap, i->first, i->second );
    }
    const AttribBindingList& abl = this->getAttribBindingList();
    accumAttribBindings.insert( abl.begin(), abl.end() );

    const AttribAliasMap& aliases = this->getAttribAliases();
    accumAttribAliases.insert( aliases.begin(), aliases.end() );


    if ( true ) //even with nothing in the map, we still want mains! -gw  //accumShaderMap.size() )
    {
        // next, assemble a list of the shaders in the map so we can use it as our
        // program cache key.
        // (Note: at present, the "cache key" does not include any information on the vertex
        // attribute bindings. Technically it should, but in practice this might not be an
        // issue; it is unlikely one would have two identical shader programs with different
        // bindings.)
        ShaderVector vec;
        vec.reserve( accumShaderMap.size() );
        for( ShaderMap::iterator i = accumShaderMap.begin(); i != accumShaderMap.end(); ++i )
        {
            ShaderEntry& entry = i->second;
            vec.push_back( entry.first.get() );
        }
        
        // see if there's already a program associated with this list:
        osg::Program* program = 0L;
        
        // look up the program:
        {
            Threading::ScopedReadLock shared( _programCacheMutex );
            
            ProgramMap::const_iterator p = _programCache.find( vec );
            if ( p != _programCache.end() )
            {
                program = p->second.get();
            }
        }
        
        // if not found, lock and build it:
        if ( !program )
        {
            Threading::ScopedWriteLock exclusive( _programCacheMutex );
            
            // look again in case of contention:
            ProgramMap::const_iterator p = _programCache.find( vec );
            if ( p != _programCache.end() )
            {
                program = p->second.get();
            }
            else
            {
                VirtualProgram* nc = const_cast<VirtualProgram*>(this);
                program = nc->buildProgram( state, accumShaderMap, accumAttribBindings, accumAttribAliases);
            }
        }
        
        // finally, apply the program attribute.
        program->apply( state );
    }
}
Example #20
0
void
PolygonizeLinesOperator::installShaders(osg::Node* node) const
{
    if ( !node )
        return;

    float minPixels = _stroke.minPixels().getOrUse( 0.0f );
    if ( minPixels <= 0.0f )
        return;

    osg::StateSet* stateset = node->getOrCreateStateSet();

    VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);

    // bail if already installed.
    if ( vp->getName().compare( SHADER_NAME ) == 0 )
        return;

    vp->setName( SHADER_NAME );

    const char* vs =
        "#version " GLSL_VERSION_STR "\n"
        GLSL_DEFAULT_PRECISION_FLOAT "\n"
        "in vec3 oe_polyline_center; \n"
        "uniform float oe_polyline_scale;  \n"
        "uniform float oe_polyline_min_pixels; \n"
        "uniform vec4 oe_PixelSizeVector; \n"

        "void oe_polyline_scalelines(inout vec4 vertex_model4) \n"
        "{ \n"
        "   const float epsilon = 0.0001; \n"

        "   vec4 center = vec4(oe_polyline_center, 1.0); \n"
        "   vec3 vector = vertex_model4.xyz - center.xyz; \n"
        
        "   float r = length(vector); \n"

        "   float activate  = step(epsilon, r*oe_polyline_min_pixels);\n"
        "   float pixelSize = max(epsilon, 2.0*abs(r/dot(center, oe_PixelSizeVector))); \n"
        "   float min_scale = max(oe_polyline_min_pixels/pixelSize, 1.0); \n"
        "   float scale     = mix(1.0, max(oe_polyline_scale, min_scale), activate); \n"

        "   vertex_model4.xyz = center.xyz + vector*scale; \n"
        "} \n";

    vp->setFunction( "oe_polyline_scalelines", vs, ShaderComp::LOCATION_VERTEX_MODEL, 0.5f );
    vp->addBindAttribLocation( "oe_polyline_center", ATTR_LOCATION );

    // add the default scaling uniform.
    // good way to test:
    //    osgearth_viewer earthfile --uniform oe_polyline_scale 1.0 10.0
    osg::Uniform* scaleU = new osg::Uniform(osg::Uniform::FLOAT, "oe_polyline_scale");
    scaleU->set( 1.0f );
    stateset->addUniform( scaleU, 1 );

    // the default "min pixels" uniform.
    osg::Uniform* minPixelsU = new osg::Uniform(osg::Uniform::FLOAT, "oe_polyline_min_pixels");
    minPixelsU->set( minPixels );
    stateset->addUniform( minPixelsU, 1 );

    // this will install and update the oe_PixelSizeVector uniform.
    node->addCullCallback( new PixelSizeVectorCullCallback(stateset) );
}
void
TextureCompositorMultiTexture::updateMasterStateSet(osg::StateSet*       stateSet,
                                                    const TextureLayout& layout    ) const
{
    int numSlots = layout.getMaxUsedSlot() + 1;
    int maxUnits = numSlots;

    if ( _useGPU )
    {
        // Validate against the max number of GPU texture units:
        if ( maxUnits > Registry::instance()->getCapabilities().getMaxGPUTextureUnits() )
        {
            maxUnits = Registry::instance()->getCapabilities().getMaxGPUTextureUnits();

            OE_WARN << LC
                << "Warning! You have exceeded the number of texture units available on your GPU ("
                << maxUnits << "). Consider using another compositing mode."
                << std::endl;
        }

        VirtualProgram* vp = static_cast<VirtualProgram*>( stateSet->getAttribute(VirtualProgram::SA_TYPE) );
        // see if we have any blended layers:
        bool hasBlending = layout.containsSecondarySlots( maxUnits );

        // Why are these marked as PROTECTED? See the comments in MapNode.cpp for the answer.
        // (Where it sets up the top-level VirtualProgram)

        vp->setFunction(
            "oe_multicomp_vertex",
            s_createTextureVertexShader(layout, hasBlending),
            ShaderComp::LOCATION_VERTEX_MODEL,
            0.0 );

        vp->setFunction(
            "oe_multicomp_fragment",
            s_createTextureFragShaderFunction(layout, maxUnits, hasBlending, _lodTransitionTime),
            ShaderComp::LOCATION_FRAGMENT_COLORING,
            0.0 );

        //vp->setShader(
        //    "osgearth_vert_setupColoring",
        //    s_createTextureVertexShader(layout, hasBlending),
        //    osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );

        //vp->setShader(
        //    "osgearth_frag_applyColoring",
        //    s_createTextureFragShaderFunction(layout, maxUnits, hasBlending, _lodTransitionTime),
        //    osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
    }

    else
    {
        // Forcably disable shaders
        stateSet->setAttributeAndModes( new osg::Program(), osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );

        // Validate against the maximum number of textures available in FFP mode.
        if ( maxUnits > Registry::instance()->getCapabilities().getMaxFFPTextureUnits() )
        {
            maxUnits = Registry::instance()->getCapabilities().getMaxFFPTextureUnits();
            OE_WARN << LC <<
                "Warning! You have exceeded the number of texture units available in fixed-function pipeline "
                "mode on your graphics hardware (" << maxUnits << "). Consider using another "
                "compositing mode." << std::endl;
        }

        // FFP multitexturing requires that we set up a series of TexCombine attributes:
        if (maxUnits == 1)
        {
            osg::TexEnv* texenv = new osg::TexEnv(osg::TexEnv::MODULATE);
            stateSet->setTextureAttributeAndModes(0, texenv, osg::StateAttribute::ON);
        }
        else if (maxUnits >= 2)
        {
            //Blend together the colors and accumulate the alpha values of textures 0 and 1 on unit 0
            {
                osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
                texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
                texenv->setCombine_Alpha(osg::TexEnvCombine::ADD);

                texenv->setSource0_RGB(osg::TexEnvCombine::TEXTURE0+1);
                texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource0_Alpha(osg::TexEnvCombine::TEXTURE0+1);
                texenv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource1_RGB(osg::TexEnvCombine::TEXTURE0+0);
                texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource1_Alpha(osg::TexEnvCombine::TEXTURE0+0);
                texenv->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource2_RGB(osg::TexEnvCombine::TEXTURE0+1);
                texenv->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);

                stateSet->setTextureAttributeAndModes(0, texenv, osg::StateAttribute::ON);
            }


            //For textures 2 and beyond, blend them together with the previous
            //Add the alpha values of this unit and the previous unit
            for (int unit = 1; unit < maxUnits-1; ++unit)
            {
                osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
                texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
                texenv->setCombine_Alpha(osg::TexEnvCombine::ADD);

                texenv->setSource0_RGB(osg::TexEnvCombine::TEXTURE0+unit+1);
                texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource0_Alpha(osg::TexEnvCombine::TEXTURE0+unit+1);
                texenv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource1_Alpha(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource2_RGB(osg::TexEnvCombine::TEXTURE0+unit+1);
                texenv->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);

                stateSet->setTextureAttributeAndModes(unit, texenv, osg::StateAttribute::ON);
            }

            //Modulate the colors to get proper lighting on the last unit
            //Keep the alpha results from the previous stage
            {
                osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
                texenv->setCombine_RGB(osg::TexEnvCombine::MODULATE);
                texenv->setCombine_Alpha(osg::TexEnvCombine::REPLACE);

                texenv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
                texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
                stateSet->setTextureAttributeAndModes(maxUnits-1, texenv, osg::StateAttribute::ON);
            }
        }
    }
}
int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);

    // help?
    if ( arguments.read("--help") )
        return usage(argv[0]);

    // set up a viewer:
    osgViewer::Viewer viewer(arguments);
    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );

    // install our default manipulator (do this before calling load)
    viewer.setCameraManipulator( new EarthManipulator() );

    // load an earth file, and support all or our example command-line options
    // and earth file <external> tags    
    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
    if ( node )
    {
        // Make a root group:
        osg::Group* root = new osg::Group();
        root->addChild( node );
        viewer.setSceneData( root );

        // Install a ClipNode. The ClipNode establishes positional state so it
        // doesn't need to parent anything. In this case it needs to be at the
        // top of the scene graph since out clip plane calculator assumes 
        // you're in world space.
        osg::ClipNode* clipNode = new osg::ClipNode();
        root->addChild( clipNode );
        
        // By default, the clip node will activate any clip planes you add to it
        // for its subgraph. Our clip node doesn't parent anything, but we include
        // this to demonstrate how you would disable that:
        clipNode->getOrCreateStateSet()->setMode(GL_CLIP_PLANE0, 0);
        
        // Create a ClipPlane we will use to clip to the visible horizon:
        osg::ClipPlane* cp = new osg::ClipPlane();
        clipNode->addClipPlane( cp );

        // This cull callback will recalcuate the position of the clipping plane
        // each frame based on the camera.
        const osgEarth::SpatialReference* srs = osgEarth::MapNode::get(node)->getMapSRS();
        clipNode->addCullCallback( new ClipToGeocentricHorizon(srs, cp) );

        // We also need a shader that will activate clipping in GLSL.
        VirtualProgram* vp = VirtualProgram::getOrCreate(root->getOrCreateStateSet());
        vp->setFunction("oe_clip_vert", clipvs, ShaderComp::LOCATION_VERTEX_VIEW);

        // Now everything is set up. The last thing to do is: anywhere in your
        // scene graph that you want to activate the clipping plane, set the 
        // corresponding mode on, like so:
        //
        // node->getOrCreateStateSet()->setMode(GL_CLIP_PLANE0, osg::StateAttribute::ON);
        //
        // If you are using symbology, you can use RenderSymbol::clipPlane(). Or in 
        // the earth file, for example:
        //
        //    render-depth-test: false;
        //    render-clip-plane: 0;

        return viewer.run();
    }
    else
    {
        return usage(argv[0]);
    }
}
Example #23
0
void
ShadowCaster::reinitialize()
{
    if ( !_supported )
        return;

    _shadowmap = 0L;
    _rttCameras.clear();

    int numSlices = (int)_ranges.size() - 1;
    if ( numSlices < 1 )
    {
        OE_WARN << LC << "Illegal. Must have at least one range slice." << std::endl;
        return ;
    }

    // create the projected texture:
    _shadowmap = new osg::Texture2DArray();
    _shadowmap->setTextureSize( _size, _size, numSlices );
    _shadowmap->setInternalFormat( GL_DEPTH_COMPONENT );
    _shadowmap->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
    _shadowmap->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
    _shadowmap->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER );
    _shadowmap->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER );
    _shadowmap->setBorderColor(osg::Vec4(1,1,1,1));

    // set up the RTT camera:
    for(int i=0; i<numSlices; ++i)
    {
        osg::Camera* rtt = new osg::Camera();
        Shadowing::setIsShadowCamera(rtt);
        rtt->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT );
        rtt->setClearDepth( 1.0 );
        rtt->setClearMask( GL_DEPTH_BUFFER_BIT );
        rtt->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );
        rtt->setViewport( 0, 0, _size, _size );
        rtt->setRenderOrder( osg::Camera::PRE_RENDER );
        rtt->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
        rtt->setImplicitBufferAttachmentMask(0, 0);
        rtt->attach( osg::Camera::DEPTH_BUFFER, _shadowmap.get(), 0, i );
        rtt->addChild( _castingGroup.get() );
        _rttCameras.push_back(rtt);
    }

    _rttStateSet = new osg::StateSet();

    // only draw back faces to the shadow depth map
    _rttStateSet->setAttributeAndModes( 
        new osg::CullFace(osg::CullFace::FRONT),
        osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

    _rttStateSet->addUniform(new osg::Uniform("oe_isShadowCamera", true), osg::StateAttribute::OVERRIDE);


    _renderStateSet = new osg::StateSet();
    
    std::string vertex = Stringify() << 
        "#version " GLSL_VERSION_STR "\n"
        GLSL_DEFAULT_PRECISION_FLOAT "\n"
        "uniform mat4 oe_shadow_matrix[" << numSlices << "]; \n"
        "varying vec4 oe_shadow_coord[" << numSlices << "]; \n"
        "void oe_shadow_vertex(inout vec4 VertexVIEW) \n"
        "{ \n"
        "    for(int i=0; i<" << numSlices << "; ++i) \n"
        "        oe_shadow_coord[i] = oe_shadow_matrix[i] * VertexVIEW;\n"
        "} \n";

    std::string fragment = Stringify() << 
        "#version " GLSL_VERSION_STR "\n"
        GLSL_DEFAULT_PRECISION_FLOAT "\n"
        "#extension GL_EXT_texture_array : enable \n"

        "uniform sampler2DArray oe_shadow_map; \n"
        "uniform vec4 oe_shadow_color; \n"
        "uniform float oe_shadow_blur; \n"
        "varying vec3 vp_Normal; \n"
        "varying vec4 oe_shadow_coord[" << numSlices << "]; \n"

        //TODO-run a generator and rplace
        "#define OE_SHADOW_NUM_SAMPLES 16\n"
        "const vec2 oe_shadow_samples[OE_SHADOW_NUM_SAMPLES] = vec2[]( vec2( -0.942016, -0.399062 ), vec2( 0.945586, -0.768907 ), vec2( -0.094184, -0.929389 ), vec2( 0.344959, 0.293878 ), vec2( -0.915886, 0.457714 ), vec2( -0.815442, -0.879125 ), vec2( -0.382775, 0.276768 ), vec2( 0.974844, 0.756484 ), vec2( 0.443233, -0.975116 ), vec2( 0.53743, -0.473734 ), vec2( -0.264969, -0.41893 ), vec2( 0.791975, 0.190909 ), vec2( -0.241888, 0.997065 ), vec2( -0.8141, 0.914376 ), vec2( 0.199841, 0.786414 ), vec2( 0.143832, -0.141008 )); \n"

        "float oe_shadow_rand(vec2 co){\n"
        "   return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n"
        "}\n"
        
        "vec2 oe_shadow_rot(vec2 p, float a) { \n"
        "    vec2 sincos = vec2(sin(a), cos(a)); \n"
        "    return vec2(dot(p, vec2(sincos.y, -sincos.x)), dot(p, sincos.xy)); \n"
        "}\n"

        // slow PCF sampling.
        "float oe_shadow_multisample(in vec3 c, in float refvalue, in float blur) \n"
        "{ \n"
        "    float shadowed = 0.0; \n"
        "    float a = 6.283185 * oe_shadow_rand(c.xy); \n"
        "    vec4 b = vec4(oe_shadow_rot(vec2(1,0),a), oe_shadow_rot(vec2(0,1),a)); \n"
        "    for(int i=0; i<OE_SHADOW_NUM_SAMPLES; ++i) { \n"
        "        vec2 off = oe_shadow_samples[i];\n"
        "        off = vec2(dot(off,b.xz), dot(off,b.yw)); \n"
        "        vec3 pc = vec3(c.xy + off*blur, c.z); \n"
        "        float depth = texture2DArray(oe_shadow_map, pc).r; \n"
        "        if ( depth < 1.0 && depth < refvalue ) { \n"
        "           shadowed += 1.0; \n"
        "        } \n"
        "    } \n"
        "    return 1.0-(shadowed/OE_SHADOW_NUM_SAMPLES); \n"
        "} \n"

        "void oe_shadow_fragment( inout vec4 color )\n"
        "{\n"
        "    float alpha = color.a; \n"
        "    float factor = 1.0; \n"

        // pre-pixel biasing to reduce moire/acne
        "    const float b0 = 0.001; \n"
        "    const float b1 = 0.01; \n"
        "    vec3 L = normalize(gl_LightSource[0].position.xyz); \n"
        "    vec3 N = normalize(vp_Normal); \n"
        "    float costheta = clamp(dot(L,N), 0.0, 1.0); \n"
        "    float bias = b0*tan(acos(costheta)); \n"

        // loop over the slices:
        "    for(int i=0; i<" << numSlices << " && factor > 0.0; ++i) \n"
        "    { \n"
        "        vec4 c = oe_shadow_coord[i]; \n"
        "        vec3 coord = vec3(c.x, c.y, float(i)); \n"

        "        if ( oe_shadow_blur > 0.0 ) \n"
        "        { \n"
        "            factor = min(factor, oe_shadow_multisample(coord, c.z-bias, oe_shadow_blur)); \n"
        "        } \n"
        "        else \n"
        "        { \n"
        "            float depth = texture2DArray(oe_shadow_map, coord).r; \n"
        "            if ( depth < 1.0 && depth < c.z-bias ) \n"
        "                factor = 0.0; \n"
        "        } \n"
        "    } \n"

        "    vec4 colorInFullShadow = color * oe_shadow_color; \n"
        "    color = mix(colorInFullShadow, color, factor); \n"
        "    color.a = alpha;\n"
        "}\n";

    VirtualProgram* vp = VirtualProgram::getOrCreate(_renderStateSet.get());

    vp->setFunction(
        "oe_shadow_vertex", 
        vertex, 
        ShaderComp::LOCATION_VERTEX_VIEW,
        0.9f );

    vp->setFunction(
        "oe_shadow_fragment",
        fragment,
        ShaderComp::LOCATION_FRAGMENT_LIGHTING,
        0.9f );

    // the texture coord generator matrix array (from the caster):
    _shadowMapTexGenUniform = _renderStateSet->getOrCreateUniform(
        "oe_shadow_matrix",
        osg::Uniform::FLOAT_MAT4,
        numSlices );

    // bind the shadow map texture itself:
    _renderStateSet->setTextureAttribute(
        _texImageUnit,
        _shadowmap.get(),
        osg::StateAttribute::ON );

    _renderStateSet->addUniform( new osg::Uniform("oe_shadow_map", _texImageUnit) );

    // blur factor:
    _shadowBlurUniform = _renderStateSet->getOrCreateUniform(
        "oe_shadow_blur",
        osg::Uniform::FLOAT);

    _shadowBlurUniform->set(_blurFactor);

    // shadow color:
    _shadowColorUniform = _renderStateSet->getOrCreateUniform(
        "oe_shadow_color",
        osg::Uniform::FLOAT_VEC4);

    _shadowColorUniform->set(_color);
}
void
DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
{
    // 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_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 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->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::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_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    }
    else
    {
        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    }

    // set up a StateSet for the RTT camera.
    osg::StateSet* rttStateSet = params._rttCamera->getOrCreateStateSet();

    // lighting is off. We don't want draped items to be lit.
    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 = VirtualProgram::getOrCreate(rttStateSet);
        vp->setName( "DrapingTechnique RTT" );
        vp->setInheritShaders( false );
        //rttStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
    }
    
    // active 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(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 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 ( _useShaders )
    {            
        // GPU path

        VirtualProgram* vp = VirtualProgram::getOrCreate(params._terrainStateSet);
        vp->setName( "DrapingTechnique terrain shaders");
        //params._terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );

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

        // vertex shader - subgraph
        std::string vs =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "uniform mat4 oe_overlay_texmatrix; \n"
            "varying vec4 oe_overlay_texcoord; \n"

            "void oe_overlay_vertex(inout vec4 VertexVIEW) \n"
            "{ \n"
            "    oe_overlay_texcoord = oe_overlay_texmatrix * VertexVIEW; \n"
            "} \n";

        vp->setFunction( "oe_overlay_vertex", vs, ShaderComp::LOCATION_VERTEX_VIEW );

        // fragment shader - subgraph
        std::string fs =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "uniform sampler2D oe_overlay_tex; \n"
            "varying vec4      oe_overlay_texcoord; \n"

            "void oe_overlay_fragment( inout vec4 color ) \n"
            "{ \n"
            "    vec4 texel = texture2DProj(oe_overlay_tex, oe_overlay_texcoord); \n"
            "    color = vec4( mix( color.rgb, texel.rgb, texel.a ), color.a); \n"
            "} \n";

        vp->setFunction( "oe_overlay_fragment", fs, ShaderComp::LOCATION_FRAGMENT_COLORING );
    }
    else
    {
        // FFP path
        local->_texGen = new osg::TexGen();
        local->_texGen->setMode( osg::TexGen::EYE_LINEAR );
        params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, local->_texGen.get(), 1 );

        osg::TexEnv* env = new osg::TexEnv();
        env->setMode( osg::TexEnv::DECAL );
        params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, env, 1 );
    }
}
Example #25
0
osg::StateSet*
Text::createStateSet()
{
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,8)
    // NOTE: Most of this is copied from the parent class, except for the 
    // added osgEarth defines and the VirtualProgram in place of the Program.
    osgText::Font* activeFont = getActiveFont();
    if (!activeFont) return 0;

    osgText::Font::StateSets& statesets = activeFont->getCachedStateSets();

    std::stringstream ss;
    ss<<std::fixed<<std::setprecision(3);

    osg::StateSet::DefineList defineList;
    if (_backdropType!=NONE)
    {
        ss.str("");
        ss << "vec4("<<_backdropColor.r()<<", "<<_backdropColor.g()<<", "<<_backdropColor.b()<<", "<<_backdropColor.a()<<")";

        defineList["BACKDROP_COLOR"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);


        if (_backdropType==OUTLINE)
        {
            ss.str("");
            ss <<_backdropHorizontalOffset;
            defineList["OUTLINE"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
        }
        else
        {
            osg::Vec2 offset(_backdropHorizontalOffset, _backdropVerticalOffset);
            switch(_backdropType)
            {
                case(DROP_SHADOW_BOTTOM_RIGHT) :    offset.set(_backdropHorizontalOffset, -_backdropVerticalOffset); break;
                case(DROP_SHADOW_CENTER_RIGHT) :    offset.set(_backdropHorizontalOffset, 0.0f); break;
                case(DROP_SHADOW_TOP_RIGHT) :       offset.set(_backdropHorizontalOffset, _backdropVerticalOffset); break;
                case(DROP_SHADOW_BOTTOM_CENTER) :   offset.set(0.0f, -_backdropVerticalOffset); break;
                case(DROP_SHADOW_TOP_CENTER) :      offset.set(0.0f, _backdropVerticalOffset); break;
                case(DROP_SHADOW_BOTTOM_LEFT) :     offset.set(-_backdropHorizontalOffset, -_backdropVerticalOffset); break;
                case(DROP_SHADOW_CENTER_LEFT) :     offset.set(-_backdropHorizontalOffset, 0.0f); break;
                case(DROP_SHADOW_TOP_LEFT) :        offset.set(-_backdropHorizontalOffset, _backdropVerticalOffset); break;
                default : break;
            }

            ss.str("");
            ss << "vec2("<<offset.x()<<", "<<offset.y()<<")";

            defineList["SHADOW"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
        }
    }

    {
        ss<<std::fixed<<std::setprecision(1);

        ss.str("");
        ss << float(_fontSize.second);

        defineList["GLYPH_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);

        ss.str("");
        ss << float(activeFont->getTextureWidthHint());
        defineList["TEXTURE_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
    }

    if (_shaderTechnique>osgText::GREYSCALE)
    {
        defineList["SIGNED_DISTANCE_FIELD"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON);
    }

#if 0
    OSG_NOTICE<<"Text::createStateSet() defines:"<<defineList.size()<<std::endl;
    for(osg::StateSet::DefineList::iterator itr = defineList.begin();
        itr != defineList.end();
        ++itr)
    {
        OSG_NOTICE<<"   define["<<itr->first<<"] = "<<itr->second.first<<std::endl;
    }
#endif

    // osgEarth:: add defines
#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE)
    defineList["OSGTEXT_GLYPH_ALPHA_FORMAT_IS_RED"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON);
#endif
    defineList[OE_LIGHTING_DEFINE] = osg::StateSet::DefinePair("", osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);

    // The remaining of this method is exclusive so we don't corrupt the
    // stateset cache when creating text objects from multiple threads. -gw
    static Threading::Mutex mutex;
    Threading::ScopedMutexLock lock(mutex);

    if (!statesets.empty())
    {
        for(osgText::Font::StateSets::iterator itr = statesets.begin();
            itr != statesets.end();
            ++itr)
        {
            if ((*itr)->getDefineList()==defineList)
            {
                // OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<<itr->get()<<std::endl;
                return itr->get();
            }
            else
            {
            }
        }
    }

    osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;

    stateset->setDefineList(defineList);

    statesets.push_back(stateset.get());

    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    stateset->setMode(GL_BLEND, osg::StateAttribute::ON);


#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
    osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
    if (_shaderTechnique==osgText::NO_TEXT_SHADER && shaderHint==osg::DisplaySettings::SHADER_NONE)
    {
        stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
        return stateset.release();
    }
#endif

    // set up the StateSet to use shaders
    stateset->addUniform(new osg::Uniform("glyphTexture", 0));
    
    // osgEarth: add shaders
    VirtualProgram* vp = VirtualProgram::getOrCreate(stateset.get());
    vp->setName("osgEarth::Text");
    osgEarth::Shaders coreShaders;
    coreShaders.load(vp, coreShaders.TextVertex);
    coreShaders.load(vp, coreShaders.TextFragment);

    return stateset.release();
#else
    return 0L;
#endif
}
Example #26
0
// 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;
    }
}
// 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();
        
        // 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 );

            // bind the vertex attributes generated by the tile compiler.
            vp->addBindAttribLocation( "oe_terrain_attr",  osg::Drawable::ATTRIBUTE_6 );
            vp->addBindAttribLocation( "oe_terrain_attr2", osg::Drawable::ATTRIBUTE_7 );

            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.loadFunction( vp, package.VertexModel );
            package.loadFunction( vp, package.VertexView );
            package.loadFunction( vp, package.Fragment );
            

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

            
            // 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.
                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( 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", -1.0f) );
            
            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) );
        }

        _stateUpdateRequired = false;
    }
}
Example #28
0
osg::Node*
createFramebufferPass(App& app)
{
    osg::Node* quad = createFramebufferQuad(app);
    
    osg::StateSet* stateset = quad->getOrCreateStateSet();

    static const char* vertSource =
        "varying vec4 texcoord;\n"
        "void effect_vert(inout vec4 vertexView)\n"
        "{\n"
        "    texcoord = gl_MultiTexCoord0; \n"
        "}\n";

    static const char* fragSource =
        "#version 120\n"
        "#extension GL_ARB_texture_rectangle : enable\n"
        "uniform sampler2DRect gcolor;\n"
        "uniform sampler2DRect gnormal;\n"
        "uniform sampler2DRect gdepth;\n"
        "varying vec4 texcoord;\n"

        "void effect_frag(inout vec4 color)\n"
        "{\n"
        "    color = texture2DRect(gcolor, texcoord.st); \n"
        "    float depth = texture2DRect(gdepth, texcoord.st).r; \n"
        "    vec3 normal = texture2DRect(gnormal,texcoord.st).xyz *2.0-1.0; \n"

        // sample radius in pixels:
        "    float e = 5.0; \n"

        // sample the normals around our pixel and find the approximate
        // deviation from our center normal:
        "    vec3 avgNormal =\n"
        "       texture2DRect(gnormal, texcoord.st+vec2( e, e)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2(-e, e)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2(-e,-e)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2( e,-e)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2( 0, e)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2( e, 0)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2( 0,-e)).xyz + \n"
        "       texture2DRect(gnormal, texcoord.st+vec2(-e, 0)).xyz;  \n"
        "    avgNormal = normalize((avgNormal/8.0)*2.0-1.0); \n"
        "    float deviation = clamp(dot(normal, avgNormal),0.0,1.0); \n"

        // set a blur factor based on the normal deviation, so that we
        // blur more around edges.
        "    e = 2.5 * (1.0-deviation); \n"

        "    vec4 blurColor = \n"
        "       color + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2( e, e)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2(-e, e)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2(-e,-e)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2( e,-e)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2( 0, e)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2( e, 0)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2( 0,-e)) + \n"
        "       texture2DRect(gcolor, texcoord.st+vec2(-e, 0));  \n"
        "    blurColor /= 9.0; \n"

        // blur the color and darken the edges at the same time
        "    color.rgb = blurColor.rgb * deviation; \n"
        "}\n";

    VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
    vp->setFunction("effect_vert", vertSource, ShaderComp::LOCATION_VERTEX_VIEW);
    vp->setFunction("effect_frag", fragSource, ShaderComp::LOCATION_FRAGMENT_COLORING);

    stateset->setTextureAttributeAndModes(0, app.gcolor, 1);
    stateset->addUniform(new osg::Uniform("gcolor", 0));
    stateset->setTextureAttributeAndModes(1, app.gnormal, 1);
    stateset->addUniform(new osg::Uniform("gnormal", 1));
    stateset->setTextureAttributeAndModes(2, app.gdepth, 1);
    stateset->addUniform(new osg::Uniform("gdepth", 2));
    stateset->setMode( GL_LIGHTING, 0 );

    float w = app.gcolor->getTextureWidth();
    float h = app.gcolor->getTextureHeight();

    osg::Camera* camera = new osg::Camera();
    camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
    camera->setViewMatrix( osg::Matrix::identity() );
    camera->setProjectionMatrixAsOrtho2D( -w/2, (-w/2)+w, -h/2, (-h/2)+h );

    camera->addChild( quad );
    return camera;
}
Example #29
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 #30
0
void makeVisibleVP(osg::StateSet* ss)
{
    VirtualProgram* vp = VirtualProgram::getOrCreate(ss);
    vp->setFunction("oe_instancing_setPos", IG_VS, ShaderComp::LOCATION_VERTEX_MODEL, -FLT_MAX);
    vp->addBindAttribLocation( "xfb_position", XFB_SLOT );
}