文档章节

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

o
 osc_y8yehimr
发布于 2019/03/20 11:37
字数 939
阅读 56
收藏 0

精选30+云产品,助力企业轻松上云!>>>

前言

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的重载有很多,我们可以试着自己进行分析一下。

总结

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

cull

这时我们还要回到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&)函数一定要研究透。

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

Java线程池

前言 Java中对线程池的抽象是ThreadPoolExecutor类,Executors是一个工具类,内置了多种创建线程池的方法: newFixedThreadPool:固定长度线程池 newCachedThreadPool :可缓存线程池 newSin...

nullpointerxyz
8分钟前
19
0
Python笔记:用Python制作二维码

这些年,二维码在我国的日常使用频率特别大。因为其具有简单及安全性吧!除了用网络工具制作二维码,其实用JavaScript或Python也可以制作二维码,而且更有个性。 示例一(制作普通黑白二维码...

tengyulong
20分钟前
0
0
Redis-初体验/数据结构

定义: Redis 是 C 语言开发的一个开源的(遵从 BSD 协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。它是一种 NoSQL(not-only sql,泛指非关系型数据库...

心田已荒
23分钟前
15
0
如何在保留订单的同时从列表中删除重复项? - How do you remove duplicates from a list whilst preserving order?

问题: Is there a built-in that removes duplicates from list in Python, whilst preserving order? 是否有内置的程序在保留顺序的同时从Python列表中删除重复项? I know that I can us...

fyin1314
今天
29
0
以太坊智能合约开发常见的10个安全问题

本文介绍CheckMarx安全研究小组通过扫描公开的以太坊智能合约所发现的Solidity智能合约开发中常见的十大安全问题,其中__未检查的外部调用__ 和 高成本循环 分列排行榜前两名。该安全问题排行...

区块链教程
今天
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部