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

前言

通过 CullVisitor 的使用,我们已经成功地构建了 OSG 系统的状态树和渲染树,并在这一过程中使用 isCulled 函数剔除了场景中对渲染没有助益的对象(在下一次遍历时,还会重新审核所有的节点,上一次被剔除的节点可能在新的循环中将被显示出来)。

RenderStage::sort 

在上一节我们提到,在状态树和渲染树构建完毕之后,我们将依次执行RenderStage::sort 和 StateGraph::prune 函数,以完成对渲染树中数据的排序和优化。RenderStage::sort 函数的执行是按照前序渲染台,当前渲染台,后序渲染台的顺序进行的,其中前序渲染台(RenderStage::_preRenderList)和后序渲染台(_postRenderList)是通过Camera::setRenderOrder 实现的,它们保存了指定摄像机及其场景子树的渲染树结构。

渲染树及其各个分支中数据的排序工作事实上是通过 RenderBin::sortImplementation 函数实现的,如果我们希望实现自定义的渲染树排序动作,通过 RenderBin::setSortCallback 函数为根节点渲染台(可以从摄像机的 SceneView 对象中取得)设置新的排序回调即可。

注意需要排序的对象仅仅是渲染树中各个渲染元(RenderBin)中保存的状态节点(StateGraph)或者渲染叶(RenderLeaf),渲染元之间不需要进行排序(那样会打乱实际的绘制顺序)。

在前前几节中我们反复说过,StateSet 对象的渲染细节可以设置为“RenderBin”(不透明体)或者“DepthSortedBin”(透明体,按深度排序)。对于设置为“RenderBin”或者缺省形式的渲染状态来说,再次进行排序的意义实际上不大;因此 OSG 事实上仅针对“DepthSortedBin”渲染元中的各个渲染叶(RenderLeaf)进行排序,排序函数为 RenderBin::sortBackToFront,其中按照深度值降序的原则使用 std::sort 执行所有元素的排序动作。这里面的深度值是在CullVisitor::apply(Geode&)函数中计算出来的。

除了上文介绍的“RenderBin”所使用的排序方式(SORT_BY_STATE,但事实上是不排序)和“DepthSortedBin”所使用的方式(SORT_BACK_TO_FRONT)之外,OSG 还内置了另外两种排序的方式,可以使用 RenderBin::setSortMode 加以指定:

1、SORT_BY_STATE_THEN_FRONT_TO_BACK:首先获取当前渲染元所保存的所有头状态节点(StateGraph),将每个节点中所有的渲染叶对象按深度升序排序;然后将各个状态节点按最小深度值升序排序(即,保存有深度值最小的渲染叶的节点排在最前)。

2、SORT_FRONT_TO_BACK:与 SORT_BACK_TO_FRONT 方式正相反,采用深度值升序的原则执行所有元素的排序。结束了渲染树的排序之后,StateGraph::prune 函数的工作仅仅是查找状态树(StateGraph)中有没有无效的状态节点,并将它们删除。

cull的最后一步

现在我们又要回到osgUtil:: SceneView::cullStage ()。场景筛选的最后一步是统计出场景中动态对象(DYNAMIC)的数目,并保存到 SceneView 的成员变量_dynamicObjectCount 中,供线程同步时使用。负责统计的函数是 RenderBin::computeNumberOfDynamicRenderLeaves,它负责统计所有 RenderLeaf::_dynamic 设置为 true 的渲染叶的数目。而这个_dynamic 变量则是由对应的

Drawable 对象或者包含此渲染叶的 StateGraph 节点的数据变度值所决定的(状态节点的状态变度则由其中的 StateSet 对象决定)。在用户程序中,设置数据变动的方式众所周知:obj->setDataVariance( osg::Object::DYNAMIC );

好,那我们就要正式结束sceneView::cull 函数的讲解了。下一步就是要探究render函数了。

原文链接  http://www.3wwang.cn/blog/article.ftl?id=56

猜你喜欢

转载自blog.csdn.net/u014177758/article/details/88715020