array 发表于 2008-9-9 13:44:25

OSG原创教程:最长的一帧(20)

当前位置:osgUtil/SceneView.cpp第670行,osgUtil:: SceneView::cull ()
首先我们来看一个场景构建的实例,并希望借此机会了解一下“状态节点”StateGraph和“渲染叶”RenderLeaf所构成的状态树,“渲染台”RenderStage及“渲染元”RenderBin所构成的渲染树,这两棵树之间错综复杂的关系,以及它们与场景节点树之间更为错综复杂的关系(真是让人冒汗)。

附图1

上面的场景结构图中,叶节点_geode3,以及所有六个几何对象均设置了关联的渲染状态集(StateSet),且几何体1和几何体2共享了同一个StateSet。图中用“ss”加上数字代号来标识这些StateSet对象,后面括号中的两个参数分别表示setRenderBinDetails的两个设置项(“-”表示空字串,“R”表示“RenderBin”,“D”表示“DepthSortedBin”)。用代码来表示的话,即是:ss03->setRenderBinDetails( 0, “” );
ss11->setRenderBinDetails( 0, “” );
ss13->setRenderBinDetails( -1, “RenderBin” );
ss14->setRenderBinDetails( 1, “RenderBin” );
ss15->setRenderBinDetails( 10, “DepthSortedBin” );
ss16->setRenderBinDetails( 10, “DepthSortedBin” );注意,“setRenderBinDetails(0, “”)”是缺省的设置,这里写出来是为了便于区别;此外,OSG中所有的Drawable几何体对象都会自动关联一个StateSet对象,无论用户是否在自己的程序中作了设置。

进入渲染后台之后,OSG将为这个场景生成“状态树”,它是由“状态节点”StateGraph和“渲染叶”RenderLeaf所组成的:

附图2


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

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

[*]1、状态树是根据渲染状态(StateSet)来生成的,那些没有设置StateSet的场景节点将不会影响状态树的构架;
[*]2、场景中的Drawable对象在状态树中被置入分别的渲染叶(RenderLeaf)中,而一个或多个渲染叶必然被一个状态树末端的节点(StateGraph)所拥有;
[*]3、共享同一个渲染状态的Drawable对象(图中的_drawable1和_drawable2)在状态树中将置入同一个末端节点。


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

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

附图3

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

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

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

附图4

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

最后,我们分别用一句话来总结“状态树”与“渲染树”的这几个组成类。之所以选择在经历了如此冗长的篇幅之后再作定义,也是为了便于读者进行归纳和总结,或者在阅读和实践的过程中提出自己的见解。

[*]osgUtil::StateGraph:状态树的分枝节点(状态节点),负责管理场景树中的一个渲染状态(StateSet)对象,末端的StateGraph节点还负责维护一个 “渲染叶”(RenderLeaf)的列表。
[*]osgUtil::RenderLeaf:状态树的叶节点(渲染叶),负责管理和绘制场景树末端的一个几何体(Drawable)对象。
[*]osgUtil::RenderStage:渲染树的根节点(渲染台),负责管理默认渲染顺序的所有末端StateGraph节点(附带“渲染叶”),并保存了“前序渲染”(pre-render)和“后序渲染”(post-render)的渲染台指针的列表。
[*]osgUtil::RenderBin:渲染树的分枝节点(渲染元),负责管理自定义渲染顺序的末端StateGraph节点(附带“渲染叶”);渲染树的根节点和分枝节点最多只能有“RenderBin”和“DepthSortedBin”两类子节点,但可以根据不同的渲染顺序号衍生出多个子节点,它们在渲染时将按照顺序号升序的次序执行绘制。


解读成果:
状态树(StateGraph/ RenderLeaf),渲染树(RenderStage/ RenderBin)。
悬疑列表:
什么是“渲染目标实现方式”?Operation对象在线程中的应用时机是什么?

teli 发表于 2008-9-10 14:04:01

谢谢

shengrendan2 发表于 2008-9-27 16:56:31

:kiss:

umls_lx 发表于 2011-11-1 10:02:39

如果按照您的说法
请问 _ss15State 和 _ss16State还有用么?

StackSnow 发表于 2012-9-10 21:36:49

:)

w910916 发表于 2012-10-26 11:04:45

在哪里可以下载最长的一针的pdf和源代码呀{:3_55:}
页: [1]
查看完整版本: OSG原创教程:最长的一帧(20)