1 前言
我曾经细致阅读过OGRE和OSG官方提供的文档,有《Pro OGRE
3D Programming》、OGRE自带手册(manual)、王锐老师等翻译的《OpenSceneGraph Quick
Guide》,同时在网络上查阅了大量的OGRE架构源码分析的文章。简单使用过OSG,对OSG的场景管理器设计和编程风格有所了解,而在近期的项目中大量使用OGRE,相对于OSG,对OGRE的认识比较深刻一些。目前OGRE的最新版本是1.7,OSG的最新版本是2.9.7。
本文是对OGRE和OSG这两大三维图形绘制引擎的一个不全面的个人比较,主要简单介绍它们在运行效率、平台支持、资源管理、场景树管理、功能支持、可扩展性、易用性和相关支持方面的异同,而不是评论谁优谁劣(当然本人也没这资历),通过了解差异后,根据不同项目要求做出不同选择。
因为本人使用这两个绘制引擎的时间不长、运用的功能特性也不全,所以有些比较结论可能不合理,欢迎指正,通过交流,共同进步。
2 绘制引擎简介
2.1 OGRE
OGRE是Object-Oriented Graphics
Rendering
Engine(面向对象的图形绘制引擎)的简称,是一个用C++开发的面向对象且使用灵活的3D引擎,是一个被广泛使用的开源三维图形渲染库。它成功地被应用于诸多三维仿真领域,其中包括网络游戏和一些商业的三维仿真项目。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。引擎中的类库对更底层的系统库(如:Direct3D和OpenGL)的全部使用细节进行了抽象,并提供了基于现实世界对象的接口和其它类。OGRE的主要特性有:
~效率特性
简单、易用的面向对象接口设计使你能更容易地渲染3D场景,并使你的实现产品独立于渲染API(如Direct3D、OpenGL、Glide等等)。
可扩展的程序框架(framework)使你能更快的编写出更好的程序。
为了节省你的宝贵时间,OGRE会自动处理常见的需求,如渲染状态管理,空间裁剪,半透物体排序等等。
清晰、整洁的设计加上全面的文档支持。
在很多商业产品(特别是电子游戏)上得到应用,并被证实是一个稳定的引擎。
~平台和3D API支持
支持Direct3D和OpenGL。
多平台支持,支持Windows(所有版本)、Linux和Mac OSX。
在Windows平台上可以使用Visual C++或Code::Blocks编译。
在Linux平台和Mac OSX平台(使用XCode)上可以使用gcc 3+编译。
~材质、Shader支持
强大的材质声明语言使你可以在代码之外维护材质资源。
支持顶点和像素着色器(Shader),同时支持低级的汇编着色器和高级的着色器,如Cg、D3D中的HLSL和GLSL,并为许多常用的常量提供自动的绑定的,如世界视点矩阵、光照状态、视点世界坐标等。
支持固定渲染管线的全部功能,如多纹理、多遍绘制融合、纹理坐标生成和修改、为低端的不可编程显卡提供独立的颜色融合操作。
支持多个材质技术,你可以设计不同显卡配置的不同技术,OGRE自动选择最佳的技术。
支持材质的LOD;你的材质可以在它们远离视点时减少资源消耗。
支持从PNG、JPEG、TGA、BMP或DDS等文件中加载纹理;支持不常见的1D纹理、立体纹理、立体盒纹理和压缩纹理(DXT、S3TC)。
可以通过插件实时提供及更新纹理,如从视频上。
支持透射纹理映射(Projective Texturing)。
~网格Meshes
灵活的网格数据格式支持,独立于顶点缓存、序号缓存、顶点声明和缓存映射。
支持渐进的网格LOD,可以自动或手动生成。
支持用Bézier样条实现的曲面。
静态几何分批绘制。
~动画
支持复杂的骨骼动画
灵活的形状动画支持
支持场景节点动画,并提供样条插值
普通动画路径支持可插入的物体适配器(不是很清楚,详见官网说明)
场景特性
拥有高效率和高度可配置性的场景管理器,并且支持多种场景类型。使用系统默认的场景组织方法,或通过亲自编写插件使用自己的场景组织方法。
提供的BspSceneManager插件是快速的室内渲染器,它支持加载Quake3关卡和shader脚本分析。
多等级的场景组织体系;场景结点支持物体的附属(attach),并带动附属物体一起运动,实现了类似于关节的运动继承体系。
~特效
粒子系统包括可以通过编写插件来扩展的粒子发射器(emitter)和粒子特效影响器(affector)。通过脚本语言可以不用重新编译就设置和更改粒子属性。支持并自动管理粒子池,从而提升粒子系统 的性能。
支持天空盒、天空面和天空圆顶,使用非常简单。
支持公告板,以实现特效。
自动管理透明物体(系统自动帮你设置渲染顺序和深度缓冲)
~其它特性
资源管理和文档加载(ZIP、PK3)。
支持高效的插件体系结构,它允许你不重新编译就扩展引擎的功能。
运用“Controllers”你可以方便地改变一个数值。例如通过生命值动态改变一个飞船的防护罩的颜色值。
支持内存泄露检测的内存调试管理器
通过ReferenceAppLayer例程了解如何让OGRE与其它库协同工作,如做碰撞可信度的ODE库。
可以用XMLConverter让二进制格式文件与XML相互转换,方便交流和编辑。
2.2 OSG
OSG是OpenSceneGraph的简称,是一个开放源码、跨平台的图形开发包。它为诸如飞行器仿真,游戏,虚拟现实,科学计算可视化这样的高性能图形应用程序开发而设计。它基于场景图的概念,它提供一个在OpenGL之上的面向对象的框架,从而能把开发者从实现和优化底层图形的调用中解脱出来,并且它为图形应用程序的快速开发提供很多附加的实用工具。
它完全是由标准C++程序和
OpenGL写的,充分利用STL和设计模式,发挥开源开发模型的优势来提供一个免费的开发库,并且重点集中在用户的需求上。随着使用一个全特性的场景图OpenSceneGraph的关键优势在于它的性能、可扩展性、可移植性和快速开发(productivity),更具体的来说:
~性能
支持视图投影剔除(view frustum
culling)、隐藏面剔除(occlusion culling)、小特性剔除(small feature
culling)、细节层次节点(LOD)、OpenGL状态排序(state sorting)、顶点数组、顶点缓冲对象(vertex buffer
objects)、OpenGL着色语言和把显示列表(display
lists)作为场景图内核的一部分。它们共同使OpenSceneGraph成为一个高性能的图形库。OpenSceneGraph也支持绘制流程(drawing
process)的定制,比如场景图的连续细节层次(CLOD)的网格(参见虚拟地形项目和Delta3D)。
~快速开发
场景图的内核封装了包括最新扩展的大部分OpenGL功能,提供诸如剔除和排序的渲染优化功能,同样提供能快速开发高性能图形应用程序的一整套补充库。应用程序开发者可以更关心实质性内容和如何操控这些它们,而不再是底层的代码
通过学习已有的场景图,比如:Performer和Open
Inventor,把它们同像设计模式这样现代软件工程理念联合起来,加上早期开发周期中的大量反馈信息,设计一个清晰的可扩展的库已经成为可能。用户可以很简单的适应OpenSceneGraph并且把它集成到自己的应用程序中
~数据装载
为了读入和写出数据库,数据库支持库(osgDB)支持动态的插件机制,从而支持大量数据格式,目前的发布版本有55种单独的插件支持3D数据和图像格式的装载。
支持的3D数据格式包括COLLADA、LightWave
(.lwo)、Alias Wavefront (.obj)、OpenFlight (.flt),多线程页面调度支持的TerraPage
(.txp)、Carbon Graphics GEO (.geo)、3D Studio MAX (.3ds)、Peformer
(.pfb)、AutoCAd (.dxf)、Quake Character Models (.md2)、Direct
X (.x)和Inventor Ascii 2.0 (.iv)/ VRML 1.0 (.wrl)、Designer Workshop
(.dw)、AC3D (.ac) 和自带的.osg ASCII 文本格式。
支持的图像格式包括.rgb、.gif、.jpg、.png、.tiff、.pic、.bmp、.dds
(包含压缩的一系列Mip贴图影像)、.tga 和quicktime
(在OSX环境下),全范围的高质量、抗锯齿字体也能通过freetype插件支持,基于字体的图像也可以通过.txf插件支持。
用户也可以通过与一个同盟项目(VirtualPlanetBuilder)生成大规模地形空间数据(multi GB),使用OpenSceneGraph的自带数据分页调度支持来查看这些数据。
~节点工具箱
这个场景图同样有一套节点工具集,它们是可以在你的应用程序中编译或者在运行时装载的独立库:
osgParticle——粒子系统
osgText——高质量抗锯齿文本
osgFX——特效框架结构
osgShadow——阴影框架结构
osgManipulator——交互控制
osgSim——虚拟仿真相关的效果
osgTerrain——地形绘制
osgAnimation——动画
osgVolume——体绘制(通过Dicom插件支持医学数据)
~可移植性
场景图的内核已经被设计成尽量少的依赖具体的平台,很少的部分超出了标准C++程序和OpenGL。这就使得这个场景图可以快速移植到大部分系统中——最开始在IRIX开发,然后移植到Linux,接着到Windows,再后来就是FreeBSD,
Mac OSX,Solaris,HP-UX, AIX 甚至是PlayStation2!
完全独立与窗口操作系统的场景图内核库使得用户在它上面可以增加他们自己的指定窗口库和应用程序,在发布版本中osgViewer库提供自带窗口支持,可支持Windows
(Win32), Unix (X11) 和 OSX
(Carbon)。osgViewer库也可以轻松的和你的窗口开发包集成起来,作为OpenSceneGraph-2.0发布版本的一部分,有例子演示了如何在Qt,
GLUT, FLTK, SDL, WxWidget, Cocoa
and MFC中的使用。
~可伸缩性
场景图内核的可扩展性使得它不仅仅可运行在便携式设备,甚至高端的多核、多GPU的系统和集群上。这可能是因为场景图内核为OpenGL
的显示列表和纹理对象支持多重图形渲染环境(multiple graphics
contexts),剔除和绘制的遍历过程被设计成隐藏渲染数据为局部变量,这样可以以几乎只读的方式使用场景图内核。这样就允许多对剔除—绘制过程运行在多个CPU上,CPU则是绑定在多个图形子系统之上。对多图形设备渲染环境和多线程的支持可以在osgViewer中方便使用,发布版本中所有的例子都可以以多线程和多GPU的方式运行。
~多语言支持
OpenSceneGraph以社区项目的形式支持多种语言,比如Java,Lua和Python。
3 OGRE与OSG的异同
通过上一节的简介可以大致了解到这两大3D绘制引擎的功能特性,同时也容易察觉到两者的异同。下面就两者的具体说明:
~设计和体系
如果你曾经使用传统而基本的方法进行过3D应用程序开发(换句话说,就是有使用OpenGL或者Direct3D这种底层API的经验),你会了解到它们有一些相似而且繁琐的过程:通过调用API设置渲染状态;通过调用API传送几何体信息;通过调用API通知GPU渲染;清理;返回到第一步,直到渲染完一帧进入下一帧。这个过程会让你陷入纷杂的API操作之中,相对于真正的应用,可能你会被浪费在基本的几何体操作中去。如果使用面向对象的方法来渲染几何体,就可以从几何体级别的处理工作中抽离出来,转而处理具体的场景和在场景中的物体。其中的物体包括:可活动的物体、静态物体组成的场景本身、灯光、摄像机以及其他。你只需简单的把物体放到场景之中,OGRE或OSG绘制引擎可以帮助你完成杂乱的几何渲染处理。也是为什么我们在开发3D应用程序时不直接使用OpenGL或D3D的原因。
OGRE和OSG在架构设计上存在着许多共同之处,都是为了兼顾系统的高效性、可移植性和可扩展性,采用了以下设计理念和工具进行系统的设计和构建:
ANSI标准C++
C++标准模板库(STL)
设计模式(Design patterns, Gamma95)
通过设计模式的一些模式如Abstract
Factory、Listener、Adopter、Singleton等,提高程序库的扩展性并易于与其它库协同工作。如OSG和OGRE库都有大量的功能强大插件支持,并可以同第三方界面库(如Qt、MFC、WxWidget等)分工合作。
但两者也存在着一些明显的不同之处。OGRE从它的命名上可以直接看出,它是一个面向对象的三维绘制引擎。相比OpenGL和D3D的显明带有面向过程特征的API,经过抽象的面向对象API更简明,使用更方便。而OSG是在OpenGL基础上提供了很多使用方便的功能包,并没有对底层图形接口(OpenGL)进行抽象。下面《Pro
OGRE 3D Programming》中关于面向对象的优势所在的论述:
嗯,现在的图形引擎就像任何庞大的软件系统。在一开始很苗条,但很快变成惊人复杂的怪兽,让人难以理解它。这样大的系统难于管理,任何对系统的修改都可能影响其可靠性。而在这样一个不断出现新技术和手段的领域,修改又是必不可少。大量的使用c函数调用也无法对这一情况有任何改善
—— 即使所有的函数都是同一个人写的。通常会发现,几个月以后,一小段代码也会变得复杂难懂;该如何组织这些函数也会变成一个难题。
面对对象是解决复杂性问题的一个常用手段。它逐步的把代码分解到函数中,把函数和表示状态的数据用类组织起来,以表示现实中的各种概念。它能让你把复杂性隐藏在容易确定的代码包当中,只暴露出简单易用的接口。这样你就有了可以搭建在一起的“建筑材料”。你也可以通过组织这些材料使它们有一致的外部接口,而在内部,实现这些接口的方法却各不相同。这同样减少了复杂性,因为开发者只需要学习一种接口。
同时,OGRE只专注于绘制,不负责其它模块,如用户界面、声音、网络、碰撞检测等,其它模块都是以插件的形式存在。而OSG提供了更多的功能,如前者所没有的功能,如虚拟仿真、体绘制、分页地形加载(最新OGRE1.7也引入了部分相关功能)等。所以如果是要利用现有成熟模块的项目可以使用OSG,而需要开发更成熟更商业化的产品可以使用OGRE。
~平台支持
从前面的特性分析可以看出,OGRE与OSG对平台的支持的侧重点有所不同,如OGRE侧重于成熟的商业化的平台,如D3D及主流图形操作系统,从而可以。而OSG强调支持多
个操作系统,如FreeBSD、Solaris、HP-UX、AIX等,只要是支持OpenGL的平台,OSG就有可能支持。由于大部分游戏及商业软件是基于D3D的,而OGRE对D3D提供了很好的支持,所以如果是开始游戏,OGRE是一个很好的选择。
~资源管理
不管地形、纹理还是字体等一切对象,绘制它们都需要不同的资源。如何加载、重用、卸载这些资源是非常重要的,因此,有专门的一批类来完成这些事情。OGRE提供了一个功能完美的资源管理系统,包括对材质、Shader、粒子系统等一系列资源的分离于代码外的管理。OGRE定义了功能强大的材质声明文件,可以在文件中直接定义纹理、绘制状态、Shader等信息,从OGRE1.6起还支持简单的变量和声明继承等,极大的方便了资源管理工作,更代码思路更清晰。
在图形引擎中,有大量的状态管理和上下文相关操作的代码。封装能把这些代码放在独立的资源声明文件中,这样以来代码就更容易理解。而且由于封装避免了复制代码方式的重用,也使得程序变得更可靠。且这些资源声明文件也是独立于平台的,这是OGRE作为一个成熟的3D绘制引擎的一个重大特性。
场景树管理
OGRE与OSG都有一个场景树在管理整个场景的相关信息,通过场景树可以方便的管理场景物体,并且在向底层接口提交绘制操作前进行一些软裁剪和绘制顺序调整工作。同时OGRE与OSG的场景树上每个节点所代表的内容是不同的。
首先,Ogre对场景图的操作维持在接口级别;它并不关心去操作图形的具体算法实现。换言之,Ogre只是通过API来操作场景图,进而忽略了具体的算法实现。其次,Ogre的场景图接口只负责维护场景结构。节点中没有包含任何固有的内容和管理方法。具体的内容被放置到一种可渲染(Renderable)对象之中,它提供了场景中全部几何图形(包括活动的的或者其他所有的)。它们的渲染的属性(也可以说是材质)被包含在实体(Entity)对象中,在实体对象里面同样包含着一个或多个子实体(SubEntity)对象,这些子实体才是是真正可以被渲染对象。
场景图形树结构的顶部是一个根节点。从根节点向下延伸,各个组节点中均包含了几何信息和用于控制其外观的渲染状态信息。
ORGE《Pro OGRE 3D Programming》中提到:
虽然没有得到权威的论证,但我还是坚信场景图和场景内容的分离的设计一定是整个Ogre项目中最亮眼的地方。虽然看起来它是一个如此的简单易懂,不过对于那些仍然坚守“传统的设计方法”来完成场景图设计的人仍然会难以理解。
在传统设计中(就是很多商业和开源3D引擎所采用的)将场景内容和场景结构放到一个继承体系中,并将场景内容生硬的作为场景节点的子类。我断言这是一个极其失败的设计方案。如果不修改所有的子类,基本上是没有办法更改或者扩充图形算法的,因此让修改基类的接口非常困难,进而导致以后的维护工作变得举步维艰。此外这种“所有节点源自同一节点类型”的设计思想会让整个程序变得凝固且难以复用(至少从维护的观点看):当增加新的基类功能方法或者属性的时候,不管是否真的需要,这些都强迫的塞入所有子类。最后导致哪怕是对基本功能做很小的修改,都会牵一发会动全身,
导致开发维护最终变得难与控制。这种糟糕的设计理念让陷入的人们痛苦不堪,从而希望摆脱这种逻辑采用全新的设计方法。
可以看出OGRE是出于可维护性和可扩展性才选择这种场景树管理方式的。配合OGRE强大的代码资源分离功能,及可扩展的多场景管理器支持能力,这种简明的场景树管理设计取得了重大成功。
~易用性
为了使代码可以支持D3D和OpenGL引擎,OGRE编程中不推荐直接使用D3D或OpenGL的API,且绘制流水线与底层的API有一定区别,这就提高了入门难度,加大了学习曲线的陡峭程度。而OSG只是基于OpenGL单个底层API的,所以可以直接在OSG工程中加入OpenGL的API调用,且一般情况下只也是唯一方案,如要使用OSG所没包括的新的OpenGL扩展。从这点来看OSG比较适合要用到新的显卡技术的项目,而OGRE比较适合技术通用、成熟且要求使用更适合游戏的D3D引擎的项目。如前面提到的OGRE有一个强大的、功能齐全的资源管理器,可以大大减轻资源管理复杂度,提高资源加载、分配和利用效率。这有助于把美工、效果与代码分离,使编程时逻辑更清晰。这是程序设计的一个主流方向,如Nokia的Qt用户界面库就是一直朝这个方向发展的。
~相关支持
OGRE与OSG在对一些资源和功能的支持上也存在这差异,如OGRE没有提供像OSG那样广泛的Mesh文件格式支持。其实OGRE只支持自身特有的.mesh文件支持,而其它模型只能通过转换到这种格式才可以载入。同时OGRE也没有提供输入输出相关支持,需要通过独立模块OIS(Object
Oriented Input
System)来支持输入输出操作。总的来说,OGRE专注于3D绘制,而3D应用程序所需要的其它功能可以由插件或其它库完成。相对而言,OSG提供的支持会多些,如体绘制(osgVolume)、仿真模拟(osgSim)、声音支持(osgAL)等模块。
4 小结
本文简单介绍了一些OGRE与OSG的一些特性及之间的功能对比,在简化3D图形编程在设计理念下,两者又保持着自己独特的设计路线。OGRE的特色在于成熟的设计模式、出色的资源管理方式和良多的跨平台性(特别是支持D3D);OSG的特色在于丰富的相关开源项目和文档、很多现成的功能模块。
同是开源项目,OSG由一个超过200人的大规模开发队伍,而OGRE却拥有一个精小强悍的开发团队(现在共7人)。OGRE相对而言比较活跃,功能更新频繁,这对于技术变化快速的图形绘制领域是重要的。至今,已有多款商业游戏使用了OGRE图形绘制引擎,如国内的网络游戏“天龙八部”、近期流行游戏“火炬之光”(Torchlight
2009.10)、网游“Zero
Gear”等。OSG偏向于虚拟仿真领域,强调库的功能胜于程序设计理论。两者都拥有着强大的开源社区,并是开源项目,随时可以方便的查看源代码,这对于开发应用程序是很有帮助的。
5 参考文献
[1]. OpenSceneGraph Quick Start Guide,Paul Martz[美],王锐 钱学雷 译,2007
[2]. Pro OGRE 3D Programming,Gregory Juker,邸锐 李旭东 译,2006
[3]. OGRE Manual v1.7 ('Cthugha'),http://www.ogre3d.org/docs/manual/
[4]. OGRE Features,http://www.ogre3d.org/about/features
[5]. OSG Introduction,http://www.openscenegraph.org/projects/osg/wiki/About/Introduction
关于OGRE与OSG的简单比较
林乃养 lnychina{at}gmail.com
浙江大学CAD&CG实验室
2010年3月27日