OpenSceneGraph源码分析:osgUtil模块

11 篇文章 7 订阅

osgUtil(OSG Utilities)模块提供了场景更新、裁剪、绘制、数据统计等公用工具。

OpenGL is a state machine. --- OpenGL Programming Guide

 一、帧循环

int ViewerBase::run()
{
    if (!isRealized())
    {
        realize();
    }

    unsigned int runTillFrameNumber = osg::UNINITIALIZED_FRAME_NUMBER;
    osg::getEnvVar("OSG_RUN_FRAME_COUNT", runTillFrameNumber);

    while(!done() && (runTillFrameNumber==osg::UNINITIALIZED_FRAME_NUMBER || getViewerFrameStamp()->getFrameNumber()<runTillFrameNumber))
    {
        double minFrameTime = _runMaxFrameRate>0.0 ? 1.0/_runMaxFrameRate : 0.0;
        osg::Timer_t startFrameTick = osg::Timer::instance()->tick();
        if (_runFrameScheme==ON_DEMAND)
        {
            if (checkNeedToDoFrame())
            {
                frame();
            }
            else
            {
                // we don't need to render a frame but we don't want to spin the run loop so make sure the minimum
                // loop time is 1/100th of second, if not otherwise set, so enabling the frame microSleep below to
                // avoid consume excessive CPU resources.
                if (minFrameTime==0.0) minFrameTime=0.01;
            }
        }
        else
        {
            frame();
        }

        // work out if we need to force a sleep to hold back the frame rate
        osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
        double frameTime = osg::Timer::instance()->delta_s(startFrameTick, endFrameTick);
        if (frameTime < minFrameTime) OpenThreads::Thread::microSleep(static_cast<unsigned int>(1000000.0*(minFrameTime-frameTime)));
    }

    return 0;
}

二、场景更新

void Viewer::updateTraversal()
{
    if (_done) return;

    double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

    _updateVisitor->reset();
    _updateVisitor->setFrameStamp(getFrameStamp());
    _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());

    _scene->updateSceneGraph(*_updateVisitor);

    // if we have a shared state manager prune any unused entries
    if (osgDB::Registry::instance()->getSharedStateManager())
        osgDB::Registry::instance()->getSharedStateManager()->prune();

    // update the Registry object cache.
    osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp());
    osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp());


    if (_updateOperations.valid())
    {
        _updateOperations->runOperations(this);
    }

    if (_incrementalCompileOperation.valid())
    {
        // merge subgraphs that have been compiled by the incremental compiler operation.
        _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp());
    }

    {
        // Do UpdateTraversal for slaves with their own subgraph
        for(unsigned int i=0; i<getNumSlaves(); ++i)
        {
            osg::View::Slave& slave = getSlave(i);
            osg::Camera* camera = slave._camera.get();
            if(camera && !slave._useMastersSceneData)
            {
                camera->accept(*_updateVisitor);
            }
        }
    }

    {
        // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
        // leave that to the scene update traversal.
        osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
        _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);

        if (_camera.valid()) _camera->accept(*_updateVisitor);

        for(unsigned int i=0; i<getNumSlaves(); ++i)
        {
            osg::View::Slave& slave = getSlave(i);
            osg::Camera* camera = slave._camera.get();
            if (camera && slave._useMastersSceneData)
            {
                camera->accept(*_updateVisitor);
            }
        }

        _updateVisitor->setTraversalMode(tm);
    }

    if (_cameraManipulator.valid())
    {
        setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
                            getCameraManipulator()->getFusionDistanceValue() );

        _cameraManipulator->updateCamera(*_camera);
    }

    updateSlaves();

    if (getViewerStats() && getViewerStats()->collectStats("update"))
    {
        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

        // update current frames stats
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
    }
}

三、渲染

3.1 整体流程

3.2 关键组件

  • StateSet

Stores a set of modes and attributes which represent a set of OpenGL state. Notice that a StateSet contains just a subset of the whole OpenGL state. In OSG, each Drawable and each Node has a reference to a StateSet. These StateSets can be shared between different Drawables and Nodes (that is, several Drawables and Nodes can reference the same StateSet). Indeed, this practice is recommended whenever possible, as this minimizes expensive state changes in the graphics pipeline.

  • RenderBin

Renderbin contains geometries to be rendered as a group, renderbins are rendered once each.  They can improve efficiency or use different rendering algorithms.

A renderBin can contain further renderBins producing a tree hierarchy of renderBins. 

  • StateGraph

StateGraph - contained in a renderBin, defines the scene to be drawn.

  • State

Encapsulates the current applied OpenGL modes, attributes and vertex arrays settings, implements lazy state updating and provides accessors for querying the current state.

The venerable Red Book says that "OpenGL is a state machine", and this class represents the OpenGL state in OSG. Furthermore,State State also has other important features:

It works as a stack of states (see pushStateSet() and popStateSet()). Manipulating this stack of OpenGL states manually is seldom needed, since OSG does this in the most common situations.

It implements lazy state updating. This means that, if one requests a state change and that particular state is already in the requested state, no OpenGL call will be made. This ensures that the OpenGL pipeline is not stalled by unnecessary state changes.

It allows to query the current OpenGL state without calls to glGet*(), which typically stall the graphics pipeline (see, for instance, captureCurrentState() and getModelViewMatrix()).

  • RenderLeaf

Container class for all data required for rendering of drawables. 

  • RenderStage

Used for encapsulate a complete stage in rendering - setting up of viewport, the projection and model matrices and rendering the RenderBin's enclosed with this RenderStage.

RenderStage also has a dependency list of other RenderStages, each of which must be called before the rendering of this stage.  These 'pre' rendering stages are used for advanced rendering techniques like multistage pixel shading or impostors.

3.3 裁剪

为了提成后续OpenGL渲染的性能,osgUtil::CullVisitor依据裁剪设置osg::CullSettings,在遍历场景图过程中使用osg::CullingSet完成可见性裁剪,在这过程中,依据节点状态集StateSet,生成了以osgUtil::StateGraph为内部节点、osgUtil::RenderLeaf为叶子节点的状态树,并将状态图根节点存储到osgUtil::SceneView::_stateGraph中。于此同时,也生成了以OSGUtil::RenderStage为根节点、以osgUtil::RenderBin为节点的渲染树

注:OSGUtil::RenderStage派生于osgUtil::RenderBin。

3.4 绘制

渲染树由RenderStage、RenderBin等节点构成,用于控制可绘制体的渲染顺序。在遍历渲染树的过程中,使用osg::State加载了可绘制体的OpenGL状态(包括模型视图矩阵、投影矩阵、OpenGL渲染属性等),

// State

inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
{
    if (ms.valid && ms.last_applied_value != enabled)
    {
        ms.last_applied_value = enabled;

        if (enabled) glEnable(mode);
        else glDisable(mode);

        if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);

        return true;
    }
    else
        return false;
}

/** apply an attribute if required, passing in attribute and appropriate attribute stack */
inline bool applyAttribute(const StateAttribute* attribute, AttributeStack& as)
{
    if (as.last_applied_attribute != attribute)
    {
        if (!as.global_default_attribute.valid()) as.global_default_attribute = attribute->cloneType()->asStateAttribute();

        as.last_applied_attribute = attribute;
        attribute->apply(*this);

        const ShaderComponent* sc = attribute->getShaderComponent();
        if (as.last_applied_shadercomponent != sc)
        {
            as.last_applied_shadercomponent = sc;
            _shaderCompositionDirty = true;
        }

        if (_checkGLErrors == ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);

        return true;
    }
    else
        return false;
}
// State.cpp

void State::applyProjectionMatrix(const osg::RefMatrix* matrix)
{
    if (_projection!=matrix)
    {
        if (matrix)
        {
            _projection=matrix;
        }
        else
        {
            _projection=_identity;
        }

        if (_useModelViewAndProjectionUniforms)
        {
            if (_projectionMatrixUniform.valid()) _projectionMatrixUniform->set(*_projection);
            updateModelViewAndProjectionMatrixUniforms();
        }
#ifdef OSG_GL_MATRICES_AVAILABLE
        glMatrixMode( GL_PROJECTION );
            glLoadMatrix(_projection->ptr());
        glMatrixMode( GL_MODELVIEW );
#endif
    }
}

void State::loadModelViewMatrix()
{
    if (_useModelViewAndProjectionUniforms)
    {
        if (_modelViewMatrixUniform.valid()) _modelViewMatrixUniform->set(*_modelView);
        updateModelViewAndProjectionMatrixUniforms();
    }

#ifdef OSG_GL_MATRICES_AVAILABLE
    glLoadMatrix(_modelView->ptr());
#endif
}

void State::applyModelViewMatrix(const osg::RefMatrix* matrix)
{
    if (_modelView!=matrix)
    {
        if (matrix)
        {
            _modelView=matrix;
        }
        else
        {
            _modelView=_identity;
        }

        loadModelViewMatrix();
    }
}

然后调用Drawable::draw()完成可绘制体的绘制。

inline void Drawable::draw(RenderInfo& renderInfo) const

网络资料

OpenGL Wikihttps://www.khronos.org/opengl/wiki/

参考文献

Dave Shreiner. OpenGL Programming Guide (7th Edition). 

王锐. OpenSceneGraph三维渲染引擎设计与实践. 清华大学出版社, 2009.

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值