osgEarth多图层渲染

osgearth的多个layer同时渲染,使用的技术是多pass渲染,即,将一个瓦片的mesh,应用多个不同的的layer进行渲染,一个layer就是一个渲染pass。

   /**
   * Everything necessary to render a single terrain tile.
      REX renders the terrain in multiple passes, one pass for each visible layer.
*/
struct TileRenderModel
    {
        /** Samplers that are bound for every rendering pass (elevation, normal map, etc.) */
        Samplers _sharedSamplers;
    /** Samplers bound for each visible layer (color) */
    RenderingPasses _passes;

    /** Add a new rendering pass to the end of the list. */
    RenderingPass& addPass()
    {
        _passes.resize(_passes.size()+1);
        return _passes.back();
    }

    /** Look up a rendering pass by the corresponding layer ID */
    const RenderingPass* getPass(UID uid) const
    {
        for (unsigned i = 0; i < _passes.size(); ++i) {
            if (_passes[i].sourceUID() == uid)
                return &_passes[i];
        }
        return 0L;
    }

    /** Look up a rendering pass by the corresponding layer ID */
    RenderingPass* getPass(UID uid)
    {
        for (unsigned i = 0; i < _passes.size(); ++i) {
            if (_passes[i].sourceUID() == uid)
                return &_passes[i];
        }
        return 0L;
    }

    /** Deallocate GPU objects associated with this model */
    void releaseGLObjects(osg::State* state) const
    {
        for (unsigned s = 0; s<_sharedSamplers.size(); ++s)
            if (_sharedSamplers[s]._texture.valid() && _sharedSamplers[s]._matrix.isIdentity())
                _sharedSamplers[s]._texture->releaseGLObjects(state);

        for (unsigned p = 0; p<_passes.size(); ++p)
            _passes[p].releaseGLObjects(state);
    }

    /** Resize GL buffers associated with this model */
    void resizeGLObjectBuffers(unsigned size)
    {
        for (unsigned s = 0; s<_sharedSamplers.size(); ++s)
            if (_sharedSamplers[s]._texture.valid() && _sharedSamplers[s]._matrix.isIdentity())
                _sharedSamplers[s]._texture->resizeGLObjectBuffers(size);

        for (unsigned p = 0; p<_passes.size(); ++p)
            _passes[p].resizeGLObjectBuffers(size);
    }
};

TileNode::merge函数,在upatetraverse中调用,更新多个layer的渲染资源的绑定,如图片,渲染状态等

void
TileNode::merge(const TerrainTileModel* model, const RenderBindings& bindings)
{
    bool newElevationData = false;

    const SamplerBinding& color = bindings[SamplerBinding::COLOR];
    if (color.isActive())
    {
        for(TerrainTileColorLayerModelVector::const_iterator i = model->colorLayers().begin();
            i != model->colorLayers().end();
            ++i)
        {
            TerrainTileImageLayerModel* model = dynamic_cast<TerrainTileImageLayerModel*>(i->get());
            if (model)
            {
                if (model->getTexture())
                {
                    RenderingPass* pass = _renderModel.getPass(model->getImageLayer()->getUID());
                    if (!pass)
                    {
                        pass = &_renderModel.addPass();
                        pass->setLayer(model->getLayer());

                        // This is a new pass that just showed up at this LOD
                        // Since it just arrived at this LOD, make the parent the same as the color.
                        if (bindings[SamplerBinding::COLOR_PARENT].isActive())
                        {
                            pass->samplers()[SamplerBinding::COLOR_PARENT]._texture = model->getTexture();
                            pass->samplers()[SamplerBinding::COLOR_PARENT]._matrix = *model->getMatrix();
                        }
                    }
                    pass->samplers()[SamplerBinding::COLOR]._texture = model->getTexture();
                    pass->samplers()[SamplerBinding::COLOR]._matrix = *model->getMatrix();

                    // Handle an RTT image layer:
                    if (model->getImageLayer() && model->getImageLayer()->useCreateTexture())
                    {
                        // Check the texture's userdata for a Node. If there is one there,
                        // render it to the texture using the Tile Rasterizer service.
                        // TODO: consider hanging on to this texture and not applying it to
                        // the live tile until the RTT is complete. (Prevents unsightly flashing)
                        GeoNode* rttNode = dynamic_cast<GeoNode*>(model->getTexture()->getUserData());

                        if (rttNode && _context->getTileRasterizer())
                        {
                            _context->getTileRasterizer()->push(rttNode->_node.get(), model->getTexture(), rttNode->_extent);
                        }
                    }

                    // check to see if this data requires an image update traversal.
                    if (_imageUpdatesActive == false)
                    {
                        for(unsigned i=0; i<model->getTexture()->getNumImages(); ++i)
                        {
                            if (model->getTexture()->getImage(i)->requiresUpdateCall())
                            {
                                ADJUST_UPDATE_TRAV_COUNT(this, +1);
                                _imageUpdatesActive = true;
                                break;
                            }
                        }
                    }
                }
            }

            else // non-image color layer (like splatting, e.g.)
            {
                TerrainTileColorLayerModel* model = i->get();
                if (model && model->getLayer())
                {
                    RenderingPass* pass = _renderModel.getPass(model->getLayer()->getUID());
                    if (!pass)
                    {
                        pass = &_renderModel.addPass();
                        pass->setLayer(model->getLayer());
                    }
                }
            }
        }
    }

    // Elevation:
    const SamplerBinding& elevation = bindings[SamplerBinding::ELEVATION];
    if (elevation.isActive() && model->elevationModel().valid() && model->elevationModel()->getTexture())
    {
        osg::Texture* tex = model->elevationModel()->getTexture();

        // always keep the elevation image around because we use it for bounding box computation:
        tex->setUnRefImageDataAfterApply(false);

        _renderModel._sharedSamplers[SamplerBinding::ELEVATION]._texture = tex;
        _renderModel._sharedSamplers[SamplerBinding::ELEVATION]._matrix.makeIdentity();

        setElevationRaster(tex->getImage(0), osg::Matrixf::identity());

        newElevationData = true;
    } 

    // Normals:
    const SamplerBinding& normals = bindings[SamplerBinding::NORMAL];
    if (normals.isActive() && model->normalModel().valid() && model->normalModel()->getTexture())
    {
        osg::Texture* tex = model->normalModel()->getTexture();
        // keep the normal map around because we might update it later in "ping"
        tex->setUnRefImageDataAfterApply(false);

        _renderModel._sharedSamplers[SamplerBinding::NORMAL]._texture = tex;
        _renderModel._sharedSamplers[SamplerBinding::NORMAL]._matrix.makeIdentity();

        updateNormalMap();
    }

    // Other Shared Layers:
    for (unsigned i = 0; i < model->sharedLayers().size(); ++i)
    {
        TerrainTileImageLayerModel* layerModel = model->sharedLayers()[i].get();
        if (layerModel->getTexture())
        {
            // locate the shared binding corresponding to this layer:
            UID uid = layerModel->getImageLayer()->getUID();
            unsigned bindingIndex = INT_MAX;
            for(unsigned i=SamplerBinding::SHARED; i<bindings.size() && bindingIndex==INT_MAX; ++i) {
                if (bindings[i].isActive() && bindings[i].sourceUID().isSetTo(uid)) {
                    bindingIndex = i;
                }                   
            }

            if (bindingIndex < INT_MAX)
            {
                osg::Texture* tex = layerModel->getTexture();
                _renderModel._sharedSamplers[bindingIndex]._texture = tex;
                _renderModel._sharedSamplers[bindingIndex]._matrix.makeIdentity();
            }
        }
    }

    // Patch Layers
    for (unsigned i = 0; i < model->patchLayers().size(); ++i)
    {
        TerrainTilePatchLayerModel* layerModel = model->patchLayers()[i].get();
    }

    if (_childrenReady)
    {
        for (int i = 0; i < 4; ++i)
        {
            TileNode* child = getSubTile(i);
            if (child)
                child->refreshInheritedData(this, bindings);
        }
    }

    if (newElevationData)
    {
        _context->getEngine()->getTerrain()->notifyTileAdded(getKey(), this);
    }
}
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
osgEarth中,加载二维瓦片地图需要进行以下步骤: 1. 创建地球模型(Earth Model):首先,你需要创建一个osgEarth的地球模型,用于加载和渲染地图数据。你可以使用 osgEarth::Map 或者 osgEarth::MapNode 类来创建地球模型。 2. 添加图层(Layer):在地球模型中,你需要添加一个图层来加载二维瓦片地图数据。osgEarth支持多种图层类型,例如图片图层、矢量图层、高程图层等。对于二维瓦片地图,你可以使用 osgEarth::ImageLayer 类来创建和添加图层。 3. 配置瓦片源(TileSource):对于二维瓦片地图,你需要配置一个瓦片源来提供地图数据。osgEarth支持多种瓦片源类型,如WMS、TMS、WMTS等。你可以通过 osgEarth::TileSourceOptions 类来设置瓦片源的参数,并使用 osgEarth::ImageLayer 类的方法将瓦片源添加到地球模型中。 ``` osgEarth::TileSourceOptions options; options.url() = "http://example.com/tileserver/{z}/{x}/{y}.png"; osgEarth::ImageLayer* imageLayer = new osgEarth::ImageLayer("Tile Layer", options); map->addLayer(imageLayer); ``` 4. 设置视口(Viewpoint):在加载地图之前,你可以设置一个初始的视口(Viewpoint),用于指定地图的默认视角和位置。你可以使用 osgEarth::Viewpoint 类来定义视口,并使用 osgEarth::Map 或者 osgEarth::MapNode 类的方法设置初始视口。 ``` osgEarth::Viewpoint initialViewpoint("Initial View", 0.0, 0.0, 100000.0); map->setInitialViewpoint(initialViewpoint); ``` 5. 创建地球操纵器(EarthManipulator):osgEarth提供了地球操纵器用于交互式操作地球场景。你可以创建一个地球操纵器,并将其附加到 osgViewer::Viewer 或者 osgEarth::View 类上,以实现用户与地图的交互。 ``` osgEarth::Util::EarthManipulator* earthManipulator = new osgEarth::Util::EarthManipulator(); viewer->setCameraManipulator(earthManipulator); ``` 6. 加载和显示地图:最后,你可以使用 osgViewer::Viewer 或者 osgEarth::View 类的方法来加载和显示地图。osgEarth会根据配置的图层、瓦片源等信息,自动加载并渲染地图数据。 ``` viewer->setSceneData(mapNode); viewer->run(); ``` 以上是一个基本的加载二维瓦片地图的流程,具体的实现细节会根据你的需求和使用的API有所不同。你可以参考osgEarth的文档和示例代码,了解更多关于加载二维瓦片地图的详细信息和具体用法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值