前言

osgUtil::CullVisitor,我们发现apply函数的重载中,有CullVisitor::apply(Group& node),CullVisitor::apply(Switch& node), CullVisitor::apply(LOD& node),CullVisitor::apply(Geode& node),CullVisitor::apply(Node& node)是一样的函数内容。所以这五个函数我们就挑出CullVisitor::apply(Node& node)进行探究。

CullVisitor::apply(Node& node)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void CullVisitor::apply(Node& node)
{
    if (isCulled(node)) return;
 
    // push the culling mode.
    pushCurrentMask();
 
    // push the node's state.
    StateSet* node_state = node.getStateSet();
    if (node_state) pushStateSet(node_state);
 
    handle_cull_callbacks_and_traverse(node);
 
    // pop the node's state off the geostate stack.
    if (node_state) popStateSet();
 
    // pop the culling mode.
    popCurrentMask();
}

1、执行isCulled函数(在父类osg::CullStack中)

1
2
3
4
5
6
7
8
9
10
11
12
inline bool isCulled(const osg::Node& node)
{
     if (node.isCullingActive())
     {
          return getCurrentCullingSet().isCulled(node.getBound());
      }
     else
     {
          getCurrentCullingSet().resetCullingMask();
          return false;
      }
}

通过node.isCullingActive()来判断,node是否开启了被cull的开关(osg::Node::isCullingActive方法在满足1)没有任意的孩子节点设置为不被剔除;2)自身的_cullingActive属性也得为true;3)包围盒可用。三个条件下才返回true)。

当为true时,通过osg::CullingSet下的isCulled判断是否满足1)在视椎体内;2)是否为小物体;3)是否被遮挡节点遮挡。满足其中一个则返回true,代表这个节点要被剔除。如果node.isCullingActive()为false则意味着不对这个节点进行剔除操作。也就是说执行的isCulled 函数,是 OSG 场景筛选的主要工

具:如果这个函数的返回值为 true,说明当前节点(及其子树)应当被裁减出场景图形。

2、node满足不被cull的条件后,执行的是 pushCurrentMask 函数,它的工作是记录当前节点视锥体筛选计算的结果(即,视锥体的哪几个面与节点的包围球有交集),并将这个结果压入堆栈,以便为下一次的计算提供方便。我们可以到 osg::Polytope::contains 的重载函数中认识这个过程。

3、这一步就是我们上一节说到的状态树和渲染树的创建。获取节点的渲染状态(StateSet),如果存在的话,使用pushStateSet函数,将这个 StateSet 对象置入到当前的状态树和渲染树中,并添加到对应的状态节点/渲染元中,或者为其新建一个相关的节点。

4、如果设定了裁剪回调函数,那么它的调用时机就是在这里。当然如果没有设置回调函数,那么就要在这里遍历这个node下的所有的子节点,进行cull操作。

5、后面就是是从堆栈中依次弹出模型的StateSet,以及恢复遍历掩码和筛选设置的原先值。

这就是整个cull在遇到node节点时发生的动作。当然cullVisitor的apply的重载有很多,我们可以试着自己进行分析一下。

总结

这样我们就完成了,对场景中所有节点的裁剪操作以及构建完成了状态树和渲染树,我们进行完成了下图的内容

这时我们还要回到SceneView::CullStage()函数中,就会看到我们在前面提到过但是没有深入讲解的两个函数

1
2
3
renderStage->sort();//渲染台排序
 
rendergraph->prune();//状态树的优化

为了方便大家的理解,请大家一定要走一遍osgUtil::CullVisitor::apply(Camera&)函数。因为RenderStage::sort 函数的排序是按照前序渲染台,当前渲染台,后序渲染台的顺序进行的,其中前序渲染台(RenderStage::_preRenderList)和后序渲染台(_postRenderList)是 osgUtil::CullVisitor::apply(Camera&)实现的,所以osgUtil::CullVisitor::apply(Camera&)函数一定要研究透。

探索未知种族之osg类生物---渲染遍历之裁剪三的更多相关文章

  1. 探索未知种族之osg类生物---渲染遍历之裁剪一

    前言 上面我们用了四节课的内容,讲解了一些osg概念性的内部原理.希望大家可以再看今天的讲解之前先再仔细的研究一下前四节的内容.这样你就会对整个osg的渲染过程有一个更加清晰的认知,有助于理解下面两个 ...

  2. 探索未知种族之osg类生物---渲染遍历之裁剪二

    前言 上一节我们大致上过了一遍sceneView::cull()函数,通过研究,我们发现上图中的这一部分的代码才是整个cull过程的核心部分.所以今天我们来仔细的研究一下这一部分. sceneView ...

  3. 探索未知种族之osg类生物---渲染遍历之认识SceneView

    前言 我们在进行osg程序的开发时,最常用到的场景管理方式是“场景节点树”的结构,     a 场景树底端的叶节点(osg::Geode)包含了各种需要渲染的几何体的顶点和渲染状态信息:     b  ...

  4. 探索未知种族之osg类生物---渲染遍历之器官协作

    好了,现在我们经过三节的介绍我们已经大体上明确了单线程模型(SingleThreaded)下 OSG 渲染遍历的工作流程.事实上无论是场景的筛选render还是绘制cull工作,最后都要归结到场景视图 ...

  5. 探索未知种族之osg类生物---渲染遍历之Renderer::draw()简介

    我们今天进入上一节的遗留问题Renderer::draw()的探究. 1.从_drawQueue中取出其中一个sceneView对象.SceneView是对scene和view类的封装,通过他可以方便 ...

  6. 探索未知种族之osg类生物--渲染遍历之GraphicsContext::runOperations

    osg::GraphicsContext::runOperations().我们先来看一下这个函数的执行过程. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  7. 探索未知种族之osg类生物---渲染遍历之Renderer简介

    我们继续renderingTraversals()的探究.我们接着上一节的”阻塞渲染线程”后就要遍历所有摄像机的渲染器(Renderer),执行 Renderer::cull 场景筛选的操作.我们在r ...

  8. 《探索未知种族之osg类生物》目录

    精力有限,博客园不在更新<探索未知种族之osg类生物>.在这里列出所有文章目录(持续更新)有兴趣的同学可以看看. 探索未知种族之osg类生物[目录] 前序 探索未知种族之osg类生物--- ...

  9. [转][osg]探索未知种族之osg类生物【目录】

    作者:3wwang 原文链接:http://www.3wwang.cn/html/article_58.html 前序 探索未知种族之osg类生物---起源 ViewBase::frame函数中的Vi ...

随机推荐

  1. Hexo:创建属于你自己的博客

    step: 1.install node.js,git,github 2.npm install -g hexo-cli 3.mkdir hexo 4.cd hexo mkdir blog 5.cd ...

  2. Android 开发 实现文本搜索功能

    核心逻辑方法: /** * 搜索item * @param searchContent 需要搜索的文本内容 */ public void searchItem(String searchContent ...

  3. Docker笔记——Docker安装及制作镜像

    1 Docker安装本文中Docker运行环境为Ubuntu 14.04.1 LTS 3.13.0-32-generic x64参考:https://docs.docker.com/v1.11/eng ...

  4. vue 单独页面body css 样式设置

    给某个page下template中的第一个div设置如下样式: .body-bg { position: absolute; width: 100%; height: 100%; top:; left ...

  5. 创建只读账号oracle

    1.创建用户,指定哪个表空间create user test2 identified by "123" default tablespace BDCDJ_XC temporary ...

  6. MVC人员管理系统

    基本都要使用C控制器中的两个action来完成操作,一个用于从主界面跳转到新页面.同时将所需操作的数据传到新界面,另一个则对应新界面的按钮,用于完成操作.将数据传回主界面以及跳转回主界面.根据不同情况 ...

  7. Delphi Exif

    这久要用到读取JPG 的 Exif 信息,先是在盒子里下了个Demo,但是那个太老了,是2003年的,后来下载了个CCR 1.5.1是可以使用了,但是我个人用的是Delphi 2007,似乎CCR 1 ...

  8. Java JTable列顺序和列宽度保存在用户本地

    上周碰到了一个棘手的需求,就是要把用JTable的列顺序和列宽度保存下来,这次用户调整了列宽度,关闭程序,下次再打开时,这个列的宽还是要保持,因为SWing的特性,都是在程序启动时就确定了列顺序和列宽 ...

  9. IIS下uploadify上传大文件出现404错误(提示上传文件大小超过400M)

    原因:由于IIS7下的默认设置限制了上传大小,所以Web.Config中的大小设置也就失效了. 解决步骤: 1.打开IIS管理器,找到Default Web Site(也就是你的发布站点),先进行停止 ...

  10. ssh命令详解

    1.简介: Secure Shell(缩写为SSH),由IETF的网络工作小组(Network Working Group)所制定:SSH为一项创建在应用层和传输层基础上的安全协议,为计算机上的She ...