节点树

首先我们来看一个场景构建的实例,并通过它来了解一下“状态节点”StateGraph 和“渲染叶”RenderLeaf 所构成的状态树“渲染台”RenderStage 和“渲染元”RenderBin 所构成的渲染树,进一步了解这两棵树之间错综复杂的关系,以及理解它们与场景节点树之间更加复杂的关系。

上面是一个虚构的场景结构图,其中叶节点_geode3,以及所有六个几何对象均设置了关联的渲染状 态集(StateSet),且几何体 1 和几何体 2 共享了同一个 StateSet(ss11(0,-))。图中用“ss”加上数字代 号来标识这些 StateSet 对象,后面括号中的两个参数分别表示 setRenderBinDetails 的两个设 置项(“-”表示空字串,“R”表示“RenderBin”,“D”表示“DepthSortedBin”)。也就是

1
2
3
4
5
6
ss03->setRenderBinDetails( 0, “” );
ss11->setRenderBinDetails( 0, “” );
ss13->setRenderBinDetails( -1, “RenderBin” );
ss14->setRenderBinDetails( 1, “RenderBin” );
ss15->setRenderBinDetails( 10, “DepthSortedBin” );
ss16->setRenderBinDetails( 10, “DepthSortedBin” );

注意1、这个函数有两个传入参数,整型数表示渲染的顺序,以 0 为标准,小于 0 的渲染状态集(亦即包含了这个StateSet的StateGraph状态节点)将排列在前,大于0的则排列在后;字符串参数“RenderBin”或者“DepthSortedBin”作为名称时有特殊含义,其中“RenderBin”表示在渲染树中新建分支进行渲染,“DepthSortedBin”表示新建分支,并且所有要渲染的数据将按照深度值降序进行排序。

注意2、 “setRenderBinDetails(0, “”)”是缺省的设置,这里写出来是为了便于区别;我们还要知道 OSG 中所有的 Drawable 几何体对象都会自动关联一个 StateSet 对象,无论用户是否在自己 的程序中作了设置。 进入渲染后台之后,OSG 将为这个场景生成“状态树”。

状态树

它是由“状态节点”StateGraph 和“渲染叶”RenderLeaf 所组成的:

图中的“状态根节点”和“局部状态节点”都是由状态树自动生成的,其中“局部状态节点”的主要 工作是保存和维护一些渲染后台自动创建的渲染属性;而“全局状态节点”主要工作则保存了一个名 为_globalStateSet 的渲染状态集对象。它的取值是场景主摄像机的 StateSet,换句话说,任何对状态树的遍历都将首先及至 场景主摄像机的渲染状态,然后才是各个节点的渲染状态,这就是_globalStateSet 的功用所 在了。

而整个状态树的构建过程则可以参考上面的场景树结构图,其规则为

1、状态树是根据渲染状态(StateSet)来生成的,那些没有设置 StateSet 的场景节点将 不会影响状态树的构架;

2、场景中的 Drawable 对象在状态树中被分别置入各自的渲染叶(RenderLeaf)中,而一个 或多个渲染叶必然被一个状态树末端的节点(StateGraph)所拥有;

3、共享同一个渲染状态的 Drawable 对象(图中的_drawable1 和_drawable2)在状态树 中将置入同一个末端节点。

生成状态树的同时,OSG 渲染后台还将生成对应的“渲染树”, 其组成为一个 RenderStage 对象和多个 RenderBind 对象。如果我们不使用 setRenderBinDetails 设置 StateSet 的渲染细节 的话,那么所有状态树中末端节点(其中必然包含了一个或多个“渲染叶”)都会按遍历顺序保存到渲染树根节点(渲染台)中,渲染树的构建也就到此结束。

渲染树

但是,如果我们对于场景中部件的渲染顺序有特殊要求的话,那么渲染树也会因而变得 复杂,上面的场景示例后可能得到如下的一株“渲染树” :

根据渲染顺序的不同,渲染树生出了三个分支。相应的状态节点置入各个渲染元 (RenderBin)分枝中,其中渲染细节设置为“RenderBin”的状态节点(StateGraph)所处 的渲染元也可称为“不透明体渲染元”;而设置为“DepthSortedBin”的状态节点则将其附带 的渲染叶(RenderLeaf)送入“透明体渲染元”,于其中采用按深度值降序的方式排序绘制, 以获得正确的透明体渲染结果;未设置渲染细节的状态节点则直接由根节点(渲染台, RenderStage)负责维护。

一个渲染元中可以保存一个或多个状态节点(或渲染叶);一个状态节点(或渲染叶) 只能置入一个渲染元中。

上面的场景结构中,我们并没有设置 Geode 节点_geode3 的渲染细节。如果设置它也采 用“RenderBin”或者“DepthSortedBin”方式,按照指定的渲染顺序号来绘制,那么在渲染 树中_geode3 节点及其附带的几何体将构成更复杂的结构形式。例如: ss03->setRenderBinDetails( 1, “RenderBin” ); 其它均不变。此时虽然ss03和ss14的渲染细节设置完全一样,但是由于关联ss03和ss14 的节点之间是父子的关系,因此渲染树的结构将变为:

注意两个渲染状态(StateSet)的渲染顺序号相同时,它们不一定放入同一个“渲染元” 中,这还取决于两个 StateSet 对象在状态树中所处的层次。有关渲染细节设置的例子,可以 参考 osghangglide。

最后,我们分别用一句话来总结“状态树”与“渲染树”的这几个组成类。

osgUtil::StateGraph:状态树的分枝节点(状态节点),负责管理场景树中的一个渲染状 态(StateSet)对象,末端的 StateGraph 节点还负责维护一个 “渲染叶” (RenderLeaf)的列 表。

osgUtil::RenderLeaf:状态树的叶节点(渲染叶),负责管理和绘制场景树末端的一个几 何体(Drawable)对象。

osgUtil::RenderStage:渲染树的根节点(渲染台),负责管理默认渲染顺序的所有末端 StateGraph 节点(附带“渲染叶”),并保存了“前序渲染” (pre-render)和“后序渲染” (post-render) 的渲染台指针的列表。

osgUtil::RenderBin:渲染树的分枝节点(渲染元),负责管理自定义渲染顺序的末端 StateGraph 节点(附带“渲染叶”);渲染树的根节点和分枝节点多只能有“RenderBin” 和“DepthSortedBin”两类子节点,但可以根据不同的渲染顺序号衍生出多个子节点,它们 在渲染时将按照顺序号升序的次序执行绘制。

原文链接 探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系

探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系的更多相关文章

  1. 探索未知种族之osg类生物---呼吸分解之渲染遍历二

    那么今天我们就正式进入osg整个呼吸动作之中最复杂的一个动作,ViewerBase::renderingTraversals(),我们先介绍renderingTraversals的开头的简单的几步操作 ...

  2. 探索未知种族之osg类生物---呼吸分解之渲染遍历一

    总结 前面我们基本上已经完成对ViewerBase::frame()函数的探究,只剩下renderingTraversals()渲染遍历的探究,虽然就剩下了一个函数,但是这却是最重要的,不可少的一个步 ...

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

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

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

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

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

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

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

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

  7. 探索未知种族之osg类生物---器官初始化一

    我们把ViewerBase::frame()比作osg这类生物的肺,首先我们先来大概的看一下‘肺’长什么样子,有哪几部分组成.在这之前得对一些固定的零件进行说明,例如_done代表osg的viewer ...

  8. 探索未知种族之osg类生物---起源

    任何程序都是有生命的,是生命就需要呼吸.例如普通的windows程序,当运行完main()函数后,就需要进入消息循环,来监听用户的各种操作,以便做出及时的回应.这样的每次循环就像生命的每次呼吸,来维持 ...

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

    前言 在osgUtil::CullVisitor,我们发现apply函数的重载中,有CullVisitor::apply(Group& node),CullVisitor::apply(Swi ...

随机推荐

  1. mysql数据库的理解

    1.索引结构原理: 普通的Btree(binary search tree)就是二叉树,如下图 B+ Tree索引类型则是二叉树的升级版,每个节点存的是 <num ,最后存排序的ROWID Ha ...

  2. python 模拟百度搜索

    import urllib.request def Url(url): flag = input("请输入要搜索的关键字:") headers_ = { "User-Ag ...

  3. jquery 防止当前页面被Iframe嵌套,防止登录页面Iframe被嵌套

    <script type="text/javascript"> if (top.location != location) { top.location.href = ...

  4. 根据URL地址获取对应的HTML,根据对应的URL下载图片

    核心代码(获取HTML): #region 根据URL地址获取信息GET public static String GetResult(string url) { return GetResult(u ...

  5. Centos6、7下安装Nginx的两种方法

    一,通过yum命令安装 1.操作系统版本的确认很重要,因为下一步我们要依靠这个来创建yum源文件 2.创建 nginx.repo vi /etc/yum.repos.d/nginx.repo 文件内容 ...

  6. JAVA REENTRANTLOCK、SEMAPHORE 的实现与 AQS 框架

    引言 ReentrantLock是JDK提供的一个可重入互斥锁,所谓可重入就是同一个锁允许被已经获得该锁的线程重新获得.可重入锁的好处可以在递归算法中使用锁,不可重入锁则导致无法在递归算法中使用锁.因 ...

  7. Burp Suite设置代理

    一.确认代理信息 打开Burp Suite,查看proxy->options,看到Interface一栏为127.0.0.1:8080. 二.在Firefox中设置代理服务器 可以下载工具Fox ...

  8. 一个萌新对redis的理解

    redis是用来保存一些常用的数据到内存,以加快数据读取,减少直接访问DB流量以降低DB压力.既然是放到内存的,那我们怎么样保证用户使用的时候不会出现与数据的差异呢,其实这叫“如何报证缓存数据的一致性 ...

  9. selenium IDE安装与使用

    官网介绍: Selenium IDE是一个Firefox插件,它记录并回放用户与浏览器的交互.使用它来创建简单的脚本或者帮助进行探索性测试. 安装流程: 只支持用火狐浏览器安装,可以用火狐浏览器的应用 ...

  10. javascript中如何判断变量类型

    typeof 只能判断基本类型,如number.string.boolean.当遇上引用类型变量就没那么好用了,结果都是object.使用Object.prototype.toString.call( ...