예제 #1
0
void
OceanSurfaceContainer::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();

        QuadTreeTerrainEngineOptions to;
        to.heightFieldSkirtRatio() = 0.0;  // don't want to see skirts
        to.clusterCulling() = false;       // want to see underwater
        to.enableBlending() = true;        // gotsta blend with the main node
        mno.setTerrainOptions( to );

        // make the ocean's map node:
        MapNode* oceanMapNode = new MapNode( oceanMap, mno );
        
        // install a custom compositor. Must do this before adding any image layers.
        oceanMapNode->setCompositorTechnique( new OceanCompositor() );

        // 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 options uniforms.
        osg::StateSet* ss = this->getOrCreateStateSet();

        _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() );

        // trick to prevent z-fighting..
        ss->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0.0, 1.0, false) );
        ss->setRenderBinDetails( 15, "RenderBin" );

        // load up a surface texture
        ss->getOrCreateUniform( "ocean_has_tex1", osg::Uniform::BOOL )->set( false );
        if ( _options.textureURI().isSet() )
        {
            //TODO: enable cache support here:
            osg::Image* image = _options.textureURI()->getImage();
            if ( image )
            {
                osg::Texture2D* tex = new osg::Texture2D( image );
                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( 1, tex, 1 );
                ss->getOrCreateUniform( "ocean_tex1", osg::Uniform::SAMPLER_2D )->set( 1 );
                ss->getOrCreateUniform( "ocean_has_tex1", 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 );

        apply( _options );
    }
}