osgEarth多图层渲染

本文介绍了osgEarth中的多层渲染技术,特别是如何通过TileRenderModel使用多pass渲染,每个layer对应一个渲染通道。TileNode的merge函数详细展示了如何在upateTraversal中合并不同层的渲染资源,包括纹理、渲染状态和更新机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值