예제 #1
0
파일: Fog.cpp 프로젝트: 2php/osgearth
void FogEffect::attach( osg::StateSet* stateSet )
{
    VirtualProgram* vp = VirtualProgram::getOrCreate( stateSet );
    Shaders pkg;
    pkg.load( vp, pkg.Fog_Vertex );
    pkg.load( vp, pkg.Fog_Fragment );
    _statesets.push_back(stateSet);
}
예제 #2
0
void
PointDrawable::setupState()
{
    // Create the singleton state set for the shader. This stateset will be
    // shared by all PointDrawable instances so OSG will sort them together.
    if (!_sharedStateSet.valid())
    {
        static Threading::Mutex s_mutex;
        s_mutex.lock();
        if (!_sharedStateSet.valid())
        {
            _sharedStateSet = new osg::StateSet();

            _sharedStateSet->setTextureAttributeAndModes(0, new osg::PointSprite(), osg::StateAttribute::ON);

            if (_gpu)
            {
                VirtualProgram* vp = VirtualProgram::getOrCreate(_sharedStateSet.get());
                Shaders shaders;
                shaders.load(vp, shaders.PointDrawable);
                _sharedStateSet->setMode(GL_PROGRAM_POINT_SIZE, 1);
            }
            else
            {
                //todo
            }

            s_isCoreProfile = Registry::capabilities().isCoreProfile();
        }
        s_mutex.unlock();
    }
}
예제 #3
0
RexTerrainEngineNode::RexTerrainEngineNode() :
TerrainEngineNode     ( ),
_terrain              ( 0L ),
_update_mapf          ( 0L ),
_tileCount            ( 0 ),
_tileCreationTime     ( 0.0 ),
_batchUpdateInProgress( false ),
_refreshRequired      ( false ),
_stateUpdateRequired  ( false )
{
    // unique ID for this engine:
    _uid = Registry::instance()->createUID();

    // always require elevation.
    _requireElevationTextures = true;

    // install an elevation callback so we can update elevation data
    _elevationCallback = new ElevationChangedCallback( this );

    // static shaders.
    if ( Registry::capabilities().supportsGLSL() )
    {
        osg::StateSet* stateset = getOrCreateStateSet();
        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
        Shaders package;
        package.load(vp, package.SDK);
    }

    // TODO: replace with a "renderer" object that can return statesets
    // for different layer types, or something.
    _imageLayerStateSet = new osg::StateSet();
}
예제 #4
0
void
GeodeticGraticule::installEffect()
{
    if (_mapNode.valid() == false)
        return;

    // shader components
    osg::StateSet* stateset = _mapNode->getTerrainEngine()->getSurfaceStateSet();
    VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);

    // configure shaders
    Shaders package;
    package.load(vp, package.Graticule_Vertex);
    package.load(vp, package.Graticule_Fragment);
    
    stateset->addUniform(new osg::Uniform(COLOR_UNIFORM, options().color().get()));
    stateset->addUniform(new osg::Uniform(WIDTH_UNIFORM, options().lineWidth().get()));
}
예제 #5
0
void
BumpMapTerrainEffect::onInstall(TerrainEngineNode* engine)
{
    if ( engine && _bumpMapTex.valid() )
    {
        osg::StateSet* stateset = engine->getSurfaceStateSet();

        // install the NormalMap texture array:
        if ( engine->getResources()->reserveTextureImageUnit(_bumpMapUnit, "BumpMap") )
        {
            // NormalMap sampler
            _bumpMapTexUniform = stateset->getOrCreateUniform(BUMP_SAMPLER, osg::Uniform::SAMPLER_2D);
            _bumpMapTexUniform->set( _bumpMapUnit );
            stateset->setTextureAttribute( _bumpMapUnit, _bumpMapTex.get() );

            // configure shaders
            VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);

            Shaders package;            
            package.define( "OE_USE_NORMAL_MAP", false ); //engine->normalTexturesRequired() );

            //package.load( vp, package.VertexModel );
            package.load( vp, package.VertexView );
            package.load( vp, _octaves <= 1? package.FragmentSimple : package.FragmentProgressive );

            if ( _octaves > 1 )
                stateset->addUniform(new osg::Uniform("oe_bumpmap_octaves", _octaves));

            stateset->addUniform(new osg::Uniform("oe_bumpmap_maxRange", _maxRange));
            stateset->addUniform(new osg::Uniform("oe_bumpmap_slopeFactor", 1.0f));
            stateset->addUniform(new osg::Uniform("oe_bumpmap_baseLOD", (float)_baseLOD));

            stateset->addUniform( _scaleUniform.get() );
            stateset->addUniform( _intensityUniform.get() );
        }
        else
        {
            OE_WARN << LC << "Failed to allocation a texture image unit!\n";
        }
    }
}
예제 #6
0
void
AlphaEffect::install(osg::StateSet* stateset)
{
    if (stateset)
    {
        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
        if (vp)
        {
            vp->setName( "osgEarth.AlphaEffect" );
            Shaders pkg;
            pkg.load(vp, pkg.AlphaEffectFragment);
            stateset->addUniform(_alphaUniform.get());
        }
    }
}
예제 #7
0
RexTerrainEngineNode::RexTerrainEngineNode() :
TerrainEngineNode     ( ),
_terrain              ( 0L ),
_update_mapf          ( 0L ),
_tileCount            ( 0 ),
_tileCreationTime     ( 0.0 ),
_batchUpdateInProgress( false ),
_refreshRequired      ( false ),
_stateUpdateRequired  ( false ),
_selectionInfo        ( 0L )
{
    // unique ID for this engine:
    _uid = Registry::instance()->createUID();

    // always require elevation.
    _requireElevationTextures = true;

    // Register our render bins protos.
    {
        // Mutex because addRenderBinPrototype isn't thread-safe.
        Threading::ScopedMutexLock lock(_renderBinMutex);

        // generate uniquely named render bin prototypes for this engine:
        //_surfaceRenderBinPrototype = new SurfaceBin();
        //osgUtil::RenderBin::addRenderBinPrototype( _surfaceRenderBinPrototype->getName(), _surfaceRenderBinPrototype.get() );
    }

    // install an elevation callback so we can update elevation data
    _elevationCallback = new ElevationChangedCallback( this );

    // static shaders.
    if ( Registry::capabilities().supportsGLSL() )
    {
        osg::StateSet* stateset = getOrCreateStateSet();
        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
        Shaders package;
        package.load(vp, package.SDK);
    }

    _surfaceSS = new osg::StateSet();
}
예제 #8
0
void
ContourMap::onInstall(TerrainEngineNode* engine)
{
    if ( engine )
    {
        if ( !engine->getResources()->reserveTextureImageUnit(_unit, "ContourMap") )
        {
            OE_WARN << LC << "Failed to reserve a texture image unit; disabled." << std::endl;
            return;
        }

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

        // Install the texture and its sampler uniform:
        stateset->setTextureAttributeAndModes( _unit, _xferTexture.get(), osg::StateAttribute::ON );
        stateset->addUniform( _xferSampler.get() );
        _xferSampler->set( _unit );

        // (By the way: if you want to draw image layers on top of the contoured terrain,
        // set the "priority" parameter to setFunction() to a negative number so that it draws
        // before the terrain's layers.)
        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);

        Shaders pkg;
        //pkg.load(vp, pkg.ContourMap_Vertex);
        pkg.load(vp, pkg.ContourMap_Fragment);

        // Install some uniforms that tell the shader the height range of the color map.
        stateset->addUniform( _xferMin.get() );
        _xferMin->set( _xfer->getMinimum() );

        stateset->addUniform( _xferRange.get() );
        _xferRange->set( _xfer->getMaximum() - _xfer->getMinimum() );

        stateset->addUniform( _opacityUniform.get() );
    }
}
예제 #9
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;
    }
}
예제 #10
0
// Generates the main shader code for rendering the terrain.
void
MPTerrainEngineNode::updateState()
{
    if ( _batchUpdateInProgress )
    {
        _stateUpdateRequired = true;
    }
    else
    {
        if ( _elevationTextureUnit < 0 && elevationTexturesRequired() )
        {
            getResources()->reserveTextureImageUnit( _elevationTextureUnit, "MP Engine Elevation" );
        }

        osg::StateSet* terrainStateSet = getTerrainStateSet();
        if ( !terrainStateSet )
            return;
        
        // required for multipass tile rendering to work
        terrainStateSet->setAttributeAndModes(
            new osg::Depth(osg::Depth::LEQUAL, 0, 1, true) );

        // activate standard mix blending.
        terrainStateSet->setAttributeAndModes( 
            new osg::BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA),
            osg::StateAttribute::ON );

        // install shaders, if we're using them.
        if ( Registry::capabilities().supportsGLSL() )
        {
            VirtualProgram* vp = new VirtualProgram();
            vp->setName( "osgEarth.engine_mp.TerrainNode" );
            terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );

            Shaders package;

            package.replace( "$MP_PRIMARY_UNIT",   Stringify() << _primaryUnit );
            package.replace( "$MP_SECONDARY_UNIT", Stringify() << (_secondaryUnit>=0?_secondaryUnit:0) );

            package.define( "MP_USE_BLENDING", (_terrainOptions.enableBlending() == true) );

            package.load( vp, package.EngineVertexModel );
            package.load( vp, package.EngineVertexView );
            package.load( vp, package.EngineFragment );
            
            if ( this->normalTexturesRequired() )
            {
                package.load( vp, package.NormalMapVertex );
                package.load( vp, package.NormalMapFragment );

                terrainStateSet->addUniform( new osg::Uniform("oe_tile_normalTex", _normalMapUnit) );
            }

            // terrain background color; negative means use the vertex color.
            Color terrainColor = _terrainOptions.color().getOrUse( Color(1,1,1,-1) );
            terrainStateSet->addUniform(new osg::Uniform("oe_terrain_color", terrainColor));

            if ( _update_mapf )
            {
                // assemble color filter code snippets.
                bool haveColorFilters = false;
                {
                    // Color filter frag function:
                    std::string fs_colorfilters =
                        "#version " GLSL_VERSION_STR "\n"
                        GLSL_DEFAULT_PRECISION_FLOAT "\n"
                        "uniform int oe_layer_uid; \n"
                        "$COLOR_FILTER_HEAD"
                        "void oe_mp_apply_filters(inout vec4 color) \n"
                        "{ \n"
                            "$COLOR_FILTER_BODY"
                        "} \n";

                    std::stringstream cf_head;
                    std::stringstream cf_body;
                    const char* I = "    ";

                    // second, install the per-layer color filter functions AND shared layer bindings.
                    ImageLayerVector imageLayers;
                    _update_mapf->getLayers(imageLayers);

                    bool ifStarted = false;
                    int numImageLayers = imageLayers.size();
                    for( int i=0; i<numImageLayers; ++i )
                    {
                        ImageLayer* layer = imageLayers[i].get();
                        if ( layer->getEnabled() )
                        {
                            // install Color Filter function calls:
                            const ColorFilterChain& chain = layer->getColorFilters();
                            if ( chain.size() > 0 )
                            {
                                haveColorFilters = true;
                                if ( ifStarted ) cf_body << I << "else if ";
                                else             cf_body << I << "if ";
                                cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n";
                                for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j )
                                {
                                    const ColorFilter* filter = j->get();
                                    cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n";
                                    cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n";
                                    filter->install( terrainStateSet );
                                }
                                cf_body << I << "}\n";
                                ifStarted = true;
                            }
                        }
                    }

                    if ( haveColorFilters )
                    {
                        std::string cf_head_str, cf_body_str;
                        cf_head_str = cf_head.str();
                        cf_body_str = cf_body.str();

                        replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str );
                        replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str );

                        vp->setFunction(
                            "oe_mp_apply_filters",
                            fs_colorfilters,
                            ShaderComp::LOCATION_FRAGMENT_COLORING,
                            0.5f );
                    }
                }
            }

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

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

                // binding for the default secondary texture matrix
                osg::Matrixf parent_mat;
                parent_mat(0,0) = 0.0f;
                terrainStateSet->getOrCreateUniform(
                    "oe_layer_parent_matrix", osg::Uniform::FLOAT_MAT4 )->set( parent_mat );
            }

            // uniform for accessing the elevation texture sampler.
            if ( elevationTexturesRequired() )
            {
                terrainStateSet->getOrCreateUniform(
                    "oe_terrain_tex", osg::Uniform::SAMPLER_2D)->set( _elevationTextureUnit );
            }

            // uniform that controls per-layer opacity
            terrainStateSet->getOrCreateUniform(
                "oe_layer_opacity", osg::Uniform::FLOAT )->set( 1.0f );

            // uniform that conveys the layer UID to the shaders; necessary
            // for per-layer branching (like color filters)
            // UID -1 => no image layer (no texture)
            terrainStateSet->getOrCreateUniform(
                "oe_layer_uid", osg::Uniform::INT )->set( -1 );

            // uniform that conveys the render order, since the shaders
            // need to know which is the first layer in order to blend properly
            terrainStateSet->getOrCreateUniform(
                "oe_layer_order", osg::Uniform::INT )->set( 0 );

            // default min/max range uniforms. (max < min means ranges are disabled)
            terrainStateSet->addUniform( new osg::Uniform("oe_layer_minRange", 0.0f) );
            terrainStateSet->addUniform( new osg::Uniform("oe_layer_maxRange", FLT_MAX) );
            terrainStateSet->addUniform( new osg::Uniform("oe_layer_attenuationRange", _terrainOptions.attentuationDistance().get()) );
            
            terrainStateSet->getOrCreateUniform(
                "oe_min_tile_range_factor",
                osg::Uniform::FLOAT)->set( *_terrainOptions.minTileRangeFactor() );

            // special object ID that denotes the terrain surface.
            terrainStateSet->addUniform( new osg::Uniform(
                Registry::objectIndex()->getObjectIDUniformName().c_str(), OSGEARTH_OBJECTID_TERRAIN) );

            // assign the uniforms for each shared layer.
            if ( _update_mapf )
            {
                ImageLayerVector imageLayers;
                _update_mapf->getLayers(imageLayers);

                int numImageLayers = imageLayers.size();
                for( int i=0; i<numImageLayers; ++i )
                {
                    ImageLayer* layer = imageLayers[i].get();
                    if ( layer->getEnabled() && layer->isShared() )
                    {
                        terrainStateSet->addUniform( new osg::Uniform(
                            layer->shareTexUniformName()->c_str(),
                            layer->shareImageUnit().get() ) );
                        
                    }
                }
            }
        }

        _stateUpdateRequired = false;
    }
}
예제 #11
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;
    }
}
예제 #12
0
void
DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
{
    // create the projected texture:
    osg::Texture2D* projTexture = new DrapingTexture(); // new osg::Texture2D();
    projTexture->setTextureSize( *_textureSize, *_textureSize );
    projTexture->setInternalFormat( GL_RGBA );
    projTexture->setSourceFormat( GL_RGBA );
    projTexture->setSourceType( GL_UNSIGNED_BYTE );
    projTexture->setFilter( osg::Texture::MIN_FILTER, _mipmapping? osg::Texture::LINEAR_MIPMAP_LINEAR: osg::Texture::LINEAR );
    projTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
    projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER );
    projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER );
    //projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE );
    projTexture->setBorderColor( osg::Vec4(0,0,0,0) );

    // set up the RTT camera:
    params._rttCamera = new DrapingCamera(); //new osg::Camera();
    params._rttCamera->setClearColor( osg::Vec4f(0,0,0,0) );
    // this ref frame causes the RTT to inherit its viewpoint from above (in order to properly
    // process PagedLOD's etc. -- it doesn't affect the perspective of the RTT camera though)
    params._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT );
    params._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize );
    params._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );
    params._rttCamera->setRenderOrder( osg::Camera::PRE_RENDER );
    params._rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
    params._rttCamera->setImplicitBufferAttachmentMask(0, 0);
    params._rttCamera->attach( osg::Camera::COLOR_BUFFER0, projTexture, 0, 0, _mipmapping );

    if ( _attachStencil )
    {
        OE_INFO << LC << "Attaching a stencil buffer to the RTT camera" << std::endl;

        // try a depth-packed buffer. failing that, try a normal one.. if the FBO doesn't support
        // that (which is doesn't on some GPUs like Intel), it will automatically fall back on 
        // a PBUFFER_RTT impl
        if ( Registry::capabilities().supportsDepthPackedStencilBuffer() )
        {
#ifdef OSG_GLES2_AVAILABLE 
            params._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8_EXT );
#else
            params._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT );
#endif
        }
        else
        {
            params._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX );
        }

        params._rttCamera->setClearStencil( 0 );
        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    }
    else
    {
        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT );
    }

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

    osg::StateAttribute::OverrideValue forceOff =
        osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE;

    rttStateSet->addUniform( Registry::shaderFactory()->createUniformForGLMode(GL_LIGHTING, forceOff) );
    rttStateSet->setMode( GL_LIGHTING, forceOff );
    
    // activate blending within the RTT camera's FBO
    if ( _rttBlending )
    {
        //Setup a separate blend function for the alpha components and the RGB components.  
        //Because the destination alpha is initialized to 0 instead of 1
        osg::BlendFunc* blendFunc = 0;        
        if (Registry::capabilities().supportsGLSL(140u))
        {
            //Blend Func Separate is only available on OpenGL 1.4 and above
            blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        }
        else
        {
            blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        }

        rttStateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
    }
    else
    {
        rttStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
    }

    // attach the overlay group to the camera. 
    // TODO: we should probably lock this since other cull traversals might be accessing the group
    //       while we are changing its children.
    params._rttCamera->addChild( params._group );

    // overlay geometry is rendered with no depth testing, and in the order it's found in the
    // scene graph... until further notice.
    rttStateSet->setMode(GL_DEPTH_TEST, 0);
    rttStateSet->setBinName( "TraversalOrderBin" );

    // add to the terrain stateset, i.e. the stateset that the OverlayDecorator will
    // apply to the terrain before cull-traversing it. This will activate the projective
    // texturing on the terrain.
    params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, projTexture, osg::StateAttribute::ON );

    // fire up the local per-view data:
    LocalPerViewData* local = new LocalPerViewData();
    params._techniqueData = local;
    
    if ( _maxFarNearRatio > 1.0 )
    {
        // Custom clipper that accounts for the projection matrix warping.
        // Without this, you will get geometry beyond the original ortho far plane.
        // (i.e. geometry from beyond the horizon will show through the earth)
        // When the projection matrix has been warped, verts with Z=1.0 are no longer
        // always on the far plane (only when y=-1) because of the perspective divide (w).
        // So we need to test the Z directly (without w) and clip. NOTE: this seems to work
        // fine, although I think it would be proper to clip at the fragment level with 
        // alpha. We shall see.
        const char* warpClip =
            "#version " GLSL_VERSION_STR "\n"
            "void oe_overlay_warpClip(inout vec4 vclip) { \n"
            "    if (vclip.z > 1.0) vclip.z = vclip.w+1.0; \n"
            "} \n";
        VirtualProgram* rtt_vp = VirtualProgram::getOrCreate(rttStateSet);
        rtt_vp->setFunction( "oe_overlay_warpClip", warpClip, ShaderComp::LOCATION_VERTEX_CLIP );
    }

    // Assemble the terrain shaders that will apply projective texturing.
    VirtualProgram* terrain_vp = VirtualProgram::getOrCreate(params._terrainStateSet);
    terrain_vp->setName( "Draping terrain shaders");

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

    // the texture projection matrix uniform.
    local->_texGenUniform = params._terrainStateSet->getOrCreateUniform(
        "oe_overlay_texmatrix", osg::Uniform::FLOAT_MAT4 );

    // shaders
    Shaders pkg;
    pkg.load( terrain_vp, pkg.DrapingVertex );
    pkg.load( terrain_vp, pkg.DrapingFragment );
}