探索未知种族之osg类生物---渲染遍历之认识SceneView
前言
我们在进行osg程序的开发时,最常用到的场景管理方式是“场景节点树”的结构,
a 场景树底端的叶节点(osg::Geode)包含了各种需要渲染的几何体的顶点和渲染状态信息;
b 组节点(osg::Group)及其派生出的各种特殊功能节点则作为场景树的各个枝节节点,它们也可以拥有不同的渲染状态;
c 整个场景的根节点(root)有且只有一个节点可以直接作为,使用setSceneData 将其设置给场景的视景器系统,即等同于将整个场景树传递给 OSG 的渲染和显示系统
d 节点所附带的渲染状态集(osg::StateSet)用来保存节点和几何体的各种渲染属性(osg::StateAttribute,例如纹理,雾效,材质,Alpha校验等)和模式开关,一个状态集中可以包含多种不同的渲染属性和开关,处于场景树底端的节点将继承并综合各级父节点的渲染状态,实现几何形状的正确渲染
场景视图(SceneView)成员简介
通过上面几节关于renderingTraversals的介绍,我们大概了解到OSG 渲染后台的主体是场景视图(SceneView),而场景视图(SceneView)同样实现了“树状结构”的管理方式,并据此实现了多个专用于渲染工作的内部类。所以我们先介绍一下场景视图(SceneView)中重要的集中内部类。
1、osgUtil::CullVisitor:“筛选访问器”。虽然同样是继承自 osg::NodeVisitor,不过这个访问器在整个 OSG 系统中可是起了举足轻重的作用。当我们使用它遍历场景图形的各个节点时,CullVisitor 将会对每一个遇到的节点执行场景筛选的工作,判断它是否会超出视截锥体范围,过于渺小,或者被遮挡节点(OccluderNode)挡住,从而将这些无助益于场景浏览的物体筛选并剔除,降低场景绘制的资源消耗。我们甚至可以使用 SceneView::setCullVisitor 来构建和指定使用自己设计的筛选访问器,不过CullVisitor只能在系统渲染后台的环境中使用。
2、osg::RenderInfo:“渲染信息”管理器。这个类负责保存和管理与场景绘制息息相关的几个重要数据:当前场景的视景器,当前场景对应的所有摄像机,以及当前所有 OpenGL 渲染状态和顶点数据(使用第十七日所述的 osg::State 类保存)。这些数据将在场景筛选和渲染时为 OSG 系统后台的工作提供重要依据。
3、osgUtil:: StateGraph: “状态节点”。我们可以对比场景树的组节点(Group),将 StateGraph理解为 OSG 渲染后台的组节点。它的组织结构与场景图形的节点结构类似,但是状态树的构建主要以节点的渲染状态集(StateSet)为依据:设置了 StateSet 的场景节点,其渲染状态会被记录到“状态节点”中,并保持它在原场景树中的相对位置;状态节点采用映射表std::map 来组织它的子节点,同一层次的子节点如果渲染状态相同,则合并到同一个“状态节点”中 。
4、osgUtil::RenderLeaf:“渲染叶”。我们可以把 RenderLeaf 理解为 OSG 渲染后台状态树的叶节点。但是,状态树的叶节点绝非等同于场景树的 Geode 节点;事实上,“渲染叶”的工作主要是记录场景树中存在的各种 Drawable 对象(以及与之相关的投影矩阵,模型视点矩阵等信息)。每个“状态节点”中都包含了一个渲染叶的列表(StateGraph::_leaves),不过只有最末端的“状态节点”会负责记录场景中的“渲染叶”。
5、osgUtil::RenderStage:“渲染台”。OSG 的渲染后台除了使用“状态树”来组织和优化节点的渲染状态之外,还有另外一种用于场景实际渲染的组织结构,我们称之为“渲染树”,“渲染树”的根节点就是“渲染台”。通常来说,由于 OSG 后台只有一个渲染树结构,因此应当也只有一个“渲染台”存在;不过 OSG 还提供了“设置摄像机渲染顺序”的功能,即 Camera::setRenderOrder。设置为PRE_RENDER 的摄像机子树将在主摄像机之前执行渲染,通常我们可以由此实现诸如“纹理烘焙”(Render To Texture)的高级功能(参见 osgprerender 例子);设置为 POST_RENDER的摄像机子树将在主摄像机之后执行渲染,一些必须在最后进行渲染的场景对象,例如 HUD显示牌,可以置为这类摄像机的子节点。注意,把视景器(Viewer)的主/从摄像机设置为 PRE_RENDER 或 POST_RENDER 往往是没有意义的。所谓从摄像机组(View::_slaves),其功能主要是实现同一场景的分窗口以及分屏幕显示(参见 osgcamera 例子)。如果您希望实现诸如 HUD 显示,简单鹰眼图等功能时,应当向场景树中添加新的摄像机节点,并设置与主摄像机不同的观察矩阵和投影矩阵。
6、osgUtil::RenderBin:“渲染元”。它是 OSG 渲染树的分支节点,不过对于没有特殊要求的场景渲染来说,更多的渲染树分支也许并不需要:场景中需要渲染的元素及其渲染属性被保存到各个“状态节点”和“渲染叶”当中;渲染树只要按照遍历的顺序,把这些数据记录到作为根节点的“渲染台”当中(即分别保存到 std::vector 成员量 RenderBin::_stateGraphList和 RenderBin::_renderLeafList 当中,注意 RenderStage 派生自 RenderBin),就可以执行场景的绘制工作了。
自定义渲染顺序处理
很多时候我们需要某些几何体在其它对象之前被绘制,比如天空总是要被任何飞过的物体所遮挡;很多时候我们也需要在大部分对象绘制完成之后才绘制某个几何体的数据(例如 HUD 文字总是显示在所有对象之上)。这种情况下,就有必要对“渲染台”中的数据进行排序,甚至为其创建新的分支“渲染元”,以实现这种复杂的渲染顺序处理。
在程序中,渲染顺序通过 StateSet::setRenderBinDetails 实现设置。这个函数有两个传入参数,
参数1:整型数表示渲染的顺序,以 0 为标准,小于 0 的渲染状态集(亦即包含了这个StateSet的StateGraph状态节点)将排列在前,大于0的则排列在后;
参数2:字符串参数“RenderBin”或者“DepthSortedBin”作为名称时有特殊含义,其中“RenderBin”表示在渲染树中新建分支进行渲染,“DepthSortedBin”表示新建分支,并且所有要渲染的数据将按照深度值降序进行排序。
注意,当字符串参数不为“RenderBin”或“DepthSortedBin”时,渲染顺序的设定也是无效的;当字符串参数和整型参数均有效时,OSG 系统将尝试寻找同类型的渲染元节点并将 StateSet 记录到此“渲染元”中,或者创建新的“渲染元”节点。
|
1
2
3
4
5
6
7
8
9
10
11
|
// 缺省渲染方式,渲染顺序 0,此时状态节点直接置入“渲染台”stateSet->setRenderBinDetails( 0, “” );// 渲染顺序-1(先渲染),此时渲染树中将新建一个“渲染元”节点stateSet->setRenderBinDetails( -1, “RenderBin” );// 渲染顺序 10,此时将新建一个“渲染元”,并按深度值降序排序各元素stateSet->setRenderBinDetails( 10, “DepthSortedBin” ); |
为了简化操作,用户程序还可以使用 StateSet::setRenderingHint 来设置渲染的顺序,这个函数的传入参数可以为枚举量 OPAQUE_BIN 或 TRANSPARENT_BIN。前者可以指定该渲染状态用于不透明物体的渲染,后者则指定该渲染状态用于透明物体的渲染,此时 OSG自动将其渲染顺序置后,并设置它所管理的“状态节点”和“渲染叶”数据按照深度值降序进行排序。关于 setRenderBinDetails 与 setRenderingHint 的关系,也可以这样解释:
|
1
2
3
4
5
6
7
8
9
|
stateSet->setRenderingHint ( OPAQUE_BIN );stateSet->setRenderingHint ( TRANSPARENT_BIN );//分别等价于:stateSet->setRenderBinDetails( 0, “RenderBin” );stateSet->setRenderBinDetails( 10, “DepthSortedBin” ); |
原文链接 http://www.3wwang.cn/blog/article.ftl?id=47
探索未知种族之osg类生物---渲染遍历之认识SceneView的更多相关文章
- 探索未知种族之osg类生物---渲染遍历之器官协作
好了,现在我们经过三节的介绍我们已经大体上明确了单线程模型(SingleThreaded)下 OSG 渲染遍历的工作流程.事实上无论是场景的筛选render还是绘制cull工作,最后都要归结到场景视图 ...
- 探索未知种族之osg类生物---渲染遍历之裁剪一
前言 上面我们用了四节课的内容,讲解了一些osg概念性的内部原理.希望大家可以再看今天的讲解之前先再仔细的研究一下前四节的内容.这样你就会对整个osg的渲染过程有一个更加清晰的认知,有助于理解下面两个 ...
- 探索未知种族之osg类生物---渲染遍历之Renderer::draw()简介
我们今天进入上一节的遗留问题Renderer::draw()的探究. 1.从_drawQueue中取出其中一个sceneView对象.SceneView是对scene和view类的封装,通过他可以方便 ...
- 探索未知种族之osg类生物--渲染遍历之GraphicsContext::runOperations
osg::GraphicsContext::runOperations().我们先来看一下这个函数的执行过程. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- 探索未知种族之osg类生物---渲染遍历之Renderer简介
我们继续renderingTraversals()的探究.我们接着上一节的”阻塞渲染线程”后就要遍历所有摄像机的渲染器(Renderer),执行 Renderer::cull 场景筛选的操作.我们在r ...
- 探索未知种族之osg类生物---渲染遍历之裁剪三
前言 在osgUtil::CullVisitor,我们发现apply函数的重载中,有CullVisitor::apply(Group& node),CullVisitor::apply(Swi ...
- 探索未知种族之osg类生物---渲染遍历之裁剪二
前言 上一节我们大致上过了一遍sceneView::cull()函数,通过研究,我们发现上图中的这一部分的代码才是整个cull过程的核心部分.所以今天我们来仔细的研究一下这一部分. sceneView ...
- 《探索未知种族之osg类生物》目录
精力有限,博客园不在更新<探索未知种族之osg类生物>.在这里列出所有文章目录(持续更新)有兴趣的同学可以看看. 探索未知种族之osg类生物[目录] 前序 探索未知种族之osg类生物--- ...
- [转][osg]探索未知种族之osg类生物【目录】
作者:3wwang 原文链接:http://www.3wwang.cn/html/article_58.html 前序 探索未知种族之osg类生物---起源 ViewBase::frame函数中的Vi ...
随机推荐
- myeclipse在过时的环境下部署项目出现的问题
开发环境 操作系统:xp sp3 2002 (ps:客户公司环境只有这个老古董) 开发工具:myeclipse2014 32位 jdk: 1.7_49 32位 DB:DB2 9.1 32位 ...
- Revit 命令添加下拉框
在学习revit制作下拉框时,需要分为三个步骤: 1.创建一个面板(panel). RibbonPanel panel10 = application.CreateRibbonPanel(Global ...
- C# 委托类型及使用
转载声明:转载本文是为了方便自己查看,有需要的朋友建议查看原文(注:原文中有作者纠正的评论,我没有搬运)原文地址:http://www.cnblogs.com/akwwl/p/3232679.html ...
- zabbix 邮件报警配置
zabbxi 邮件告警推送有两种方式: 1.使用zabbix服务端的本地邮箱账号发送,邮件名为:user@hostname.localdomain,user为发送邮件的用户,hostname为zabb ...
- hdfs webhdfs 写文件(create file)
# _*_ coding=utf-8 _*_ import sys import os hosts = {} cmd1 = ''' curl -i -X PUT "http://%s:500 ...
- [python]关于函数传入参数
在传入参数时有两个特殊参数,*args,**kwargs,功能如下: def foo(*args, **kwargs): print 'args = ', args print 'kwargs = ' ...
- idea的环境设置
IDEA的个人配置与常用操作 IDEA的个人配置 1.修改代码编辑器 新版的IDEA默认使用vim编辑器(linux下的一个工具),虽然熟练掌握后可以提高工作效率,但是学习成本很大,不习惯的可以选择关 ...
- 程序员常用字体(vs2008字体修改方案)
字体不仅是设计师手中重要的武器,对我们开发人员来说,字体的选择也有许多讲究,一个好的.适合展示代码的字体,应该具备以下要素: 等宽的字符 简洁.清晰并且规范的字符形状 支持ASCII码为128以上的扩 ...
- [SF] Symfony 在 console 中结合 Workerman
在web框架的console中,命令不再是直接指定入口文件,如以往 php test.php start,而是类似 php app/console do 的形式. workerman 对命令的解析是 ...
- 一个jQuery对象绑定多个事件
1.两个事件有两种不同的方法 jQuery("#id").click(func1(){}).mouseover(func2(){}) ; 2.两个事件调用同一种方法 jquery( ...