OSG 作为老牌的开源渲染引擎之一,有一定的用户群体,不少个人、企业、科研机构都在使用OSG进行开发。随着不少商业渲染引擎的开源与准门槛的降低(比如Unity3D 授权费用比较低,中小企业甚至个人都能负担的起授权费用,UE开源且准门槛也比降低了不少 ),OSG, OGRE这样的开源渲染引擎正在逐步走向没落。虽然OSG同样走向没落,但对于自研引擎或基于OSG的二次开发的商业应用,OSG还有很大的参考价值。尤其在仿真视景领域或CAD领域,OSG还能大展头角。虽然它的渲染已经过时了,基于固定管线的特效系统API老旧,但引擎架构并没有过时。如果对渲染效果要求不高,或对OSG渲染部分进行深度改造支持PBR甚至光追渲染,还能发挥它很大的价值,尤其在CAD领域对渲染引擎功能需不像游戏引擎需求那么多,比如音视频,动画,材质,各种编辑工具的开发,并且OSG以C++接口封装成动态库的形式提供渲染服务,使用灵活,更容易以组件的形式嵌入到软件中提供渲染服务。
一、OSG亮点
-
强大的仿真视景功能,支持多视口、多窗口、 立体渲染,多设备集群渲染, POWER WALL , CAVE模式;
-
多线程并发渲染;
-
支持大规模数据分页渲染;
-
自己的跨平台线程库 OpenThreads;
-
支持多种剔除策略;
-
渲染属性可以重载、覆盖,以支持材质重载覆盖;
-
使用栈技术跟踪OpenGL状态,减少了OpenGL 函数调用,并使用状态树根据渲染属性对实体进行分组,宏观上减少了OpenGL函数调用与状态切换;
-
渲染树能够使用户对物体渲染顺序得到更好的控制;
-
对视口、窗口操作,事件处理进行了比较好的封装,方便用户使用;
-
跨平台;
-
支持扩展;
OSG 以插件的形式,允许用户自定义插件来读取多种格式的模型。
二、OSG 架构
OSG 以中间件的形式(middleware) 对外提供服务,核心库是Core OSG 。OSG Plugins 以插件形式扩展OSG 提供对第三方格式的读写。
三、OSG 为什么能进行高效渲染?
OSG 能提供高效的渲染得益于它的场景组织、多种场景剔除模式,多线程渲染以及渲染状态排序策略,这是OSG的灵魂所在,也是整个引擎架构的特点。
1、OSG后台渲染流程
从上图可以看出, OSG在执行渲染时主要组件是 SceneView, CullVisitor, StateGraph, RenderStage, State。SceneView是后台场景图管理与遍历的执行者,SceneView 调用CullVisitor 生成渲染树与状态树, 最终通过遍历渲染树绘制场景。
-
OSG 前、后台划分
OSG中,与用户直接交互的系统前端工具 GraphicsWindow, View, Viewer, CompositeViewer均通过osgViewerer库定义, 渲染后台的功能类 CullVisitor, StateGraph, RenderLeaf, RenderState, RenderBin , SceneView 均为osgUtil库的组成部分。
- 前台接口
视图(View)和视景器(Viewer和 CompositeViewer)负责将相机节点及其子树应用于系统仿真过程,并加载漫游器、交互事件处理器和各种场景浏览的辅助部件。
GraphicsContext 表示相机的底层图形窗口或者缓存,并且传递了各种各样的用户交互事件。
两者共同完成了场景数据的管理和用户交互的系统前端工作。
- 后台接口
状态树(StateGraph/RenderLeaf)、裁剪访问器(CullVisitor)、OSG状态机(State类),完成系统后台的全部OpenGL渲染工作。
2、裁剪
背面裁剪,视锥体裁剪,遮挡裁剪,细节裁剪,聚集裁剪等组合;
3、场景的多线程渲染
a.单线程模型
传统的实时渲染实现方式,它将每一帧的渲染事件分为3个阶段:用户更新阶段(Update), 场景裁剪阶段(Cull)以及场景绘制阶段(Draw)。
b.多设备裁剪绘制模型
这是一种早期针对多个图形设备同时运行的系统多线程设计方法,系统根据窗口中开启的图形窗口(或缓存对象)的数目,为每一个图形设备开启一个任务线程,执行各自的场景裁剪和绘制的更新。这种模式下不需要过多考虑线程安全性问题,但每一帧结束前必须强制同步所有设备线程,保证下一帧开始时, 所有线程绘制已经结束,避免渲染数据突然被新的更新更改。
c.多设备绘制模型
d、多相机绘制模型
效率最高、 最复杂的模型, 最大限度的利用cpu, 将更新、裁剪、绘制工作分离开来,同步进行,提升渲染效率。这一线程模型将最大限度地发回多任务,多图形设备,CPU系统的场景渲染能力,是目前使用OSG 开发的系统首选多线程渲染方案。
这里我们特别要摘清设备这个概念,一般我们提到设备都是特指硬件设备,比如物理显示器等。OSG的设备就是窗口window。相机特指视口,视口是指窗口内逻辑划分的矩形显示区域 。
OSG线程模型主要是针对多窗口,多视口、多设备的情况做的优化策略,但对于单窗口单视口的情况没有起到多少加速显示的作用,虽然OSG多设备裁剪绘制模型(DrawThreadPerContext)在主线程中可以分担一部分裁剪工作。CAD之类的软件大多数都是在单窗口且单视口模式下工作,所以如果要对OSG进行扩展,就要加入单窗口单视口的多线程模型,在这种线程模式下,我们就要对场景中所有显示对象做批量处理划分,根据系统负载情况,自动开启一定数量的工作者线程,类似于OSG相机绘制模型,一部分线程负责裁剪剔除,一部分线程负责绘制的并行管线。这对大场景模型显示提速非常有用。
CAD类软件的显示提速的主要难点在于场景中的对象多数是动态的,而且由于选择交互的需要不利于将相同显示属性的对象做一次预处理合并再批量绘制。mesh数量巨大,多数是nurbs曲面细分后的面片,边界曲线,合并后的拆分复杂度较高,会造成性能瓶颈,要改进也只能在显示时模拟次级索引做手脚。