第五章 OSRender场景渲染器总体设计与实现
如前面章节所述,一个室外场景渲染器的主要工作包括三部分:1.超大场景数据的读取与管理;2.场景地形网格的组织与简化算法;3.场景真实感渲染技术。基于对这三部分的研究,本设计实现了名为0SRender的室外场景渲染器。本章就0SRender的总体框架做简要说明,并介绍在实现中可采用的基于0penGL的渲染优化手段。
5.1渲染器总工作流程

(1)初始化阶段
载入地形Tiles的高度图数据,初始化Tiles缓冲池,载入纹理贴图、光照贴图,载入树的多边形模型、计算顶点法向量。
(2)实时渲染阶段
包括地形的渲染、天空的渲染、草树雾的渲染。地形的渲染是最主要的。
(3)对象清除,资源回收
清除分配的系统资源。
5.2渲染器的总体设计
本设计基于面向对象的设计理念,整个模块框架如图5.2所示:

以下是比较重要的类的说明:

关于重要算法的描述和伪代码已经在具体章节给出,这里不再赘述。
5.3场景渲染的最终效果图
程序用VC+OpenGL在windows平台上完成。我们使用大小为2049×2049的高程图作为实验数据,以Athlon2500+,DDR 1G,ATI 9550,128M显存作为硬件环境对渲染器进行了测试,在图形渲染效果良好的情况下,帧率达到40-50FPS,能满足游戏引擎中图形渲染的需要。下图是本设计关于室外场景的最终渲染效果:

5.4基于OpenGL的渲染优化手段
5.4.1利用GLSL对GPU进行编程
GLSL(GL Shading Language)是用来在顶点和像素着色器(shader)中编程的语言。使用它我们可以通过写短小的自定义程序,在图形卡的GPU(Graphic Processor Unit图形处理单元)上执行,代替固定渲染管线的一部分,所以也称为可编程管道渲染。现在生产的主流显卡都已经支持着色器编程,所以要实现高性能、高逼真的渲染,使用着色器语言是必不可少的。主流着色器语言有两类:DirectX支持的HLSL(High Level Shading Language),OpenGL支持的GLSL。
GLSL的着色器代码分成两个部分:Vertex Shader(顶点着色器)和Fragment Shader(像素着色器)。
顶点着色器主要的工作是利用视图和投影矩阵对点的位置进行变化,控制纹理坐标的产生和转换,顶点的光照或者象素光照的计算,颜色的计算。可以根据需要选择一些功能进行不同的编写。它可以得到当前OpenGL中的状态,用GLSL内置变量进行传递。比如gl_ProjectionMatrix(投影变换矩)、gl_ModelViewMatrix(视图变换矩阵)、g_position、gl_backcolor、gl_frontcolor、gl_normal等;而这些就是OpenGL应用程序中的顶点位置、颜色、法线等信息。
像素着色器是在对每个像素进行光栅化处理期间执行的程序。它实际上替换了固定功能管线的多纹理化阶段,并赋予我们直接操纵单独的像素和访问每个像素的纹理坐标的能力。这种对像素和纹理坐标的直接访问使我们可以高效达成各种特效,例如:多纹理化、每像素光照、景深、云状物模拟、焰火模拟等。
5.4.2使用显示列表加快渲染速度
OpenGL显示列表(Display List)是由一组预先存储起来的留待以后调用的OpenGL函数语句组成的,当调用显示列表时就依次执行表中所列出的函数语句。OpenGL对这些语句进行了预编译,因此速度比立即模式快很多。显示列表可以用在以下场合:
(1)矩阵操作
大部分矩阵操作需要OpenGL计算逆矩阵。矩阵及其逆矩阵都可以保存在显示列表中。
(2)光栅位图
程序定义的光栅数据不一定是适合硬件处理的理想格式。当编译组织一个显示列表时,OpenGL可以把数据转换成硬件能够接受的数据,这可以有效地提高画位图的速度。
(3)光、材质和光照模型
当用一个比较复杂的光照环境绘制场景时,因为材质计算可能比较慢。若把材质定义放在显示列表中,则每次改换材质时就不必重新计算了,因此能更快地绘制光照场景。
(4)纹理
因为硬件的纹理格式可能与OpenGL格式不一致,若把纹理定义放在显示列表中,则在编译显示列表时就能对格式进行转换,而不是在执行中进行,这样就能大大提高效率。
OpenGL提供glNewList 0与glEndList 0的形式创建显示列表。
5.4.3使用VBO扩展加载顶点常驻显存
VBO(Vertex Buffer Object)扩展是把数据保存在高速的显存中,而不是普通的系统RAM内存。它不仅仅降低了每帧的内存操作,而且减少了数据在显卡和内存之间的传输。这种技术应用在合适的时机将大大提高渲染效率。当然,这个扩展是依赖较新的硬件的,不是所有的图形卡都支持的,所以在使用它前需要检测显卡支不支持VBO扩展。在OpenGL中使用VBO可以通过以下几个步骤:
首先用glGenBuffersARB来产生一个可用VBO的ID,OpenGL通过这个ID关联你的数据。
然后通过glBufferDataARB把内存中的数据的指针和大小传递进去,glBufferDataARB将把你的数据拷贝到显卡内存中,这时我们可以把相应主机内存中的数据删除。
在访问数据的时候,用glBindBufferARB绑定你的数据,这样你就可以通过glDrawArrays等函数来把你的数据绘制出来。
5.5本章小结
本章主要介绍在课题研究过程中实现的一个室外场景渲染器的相关流程和框架,在更高层次上清晰地表达室外场景渲染的各个层面。此外,本章还涉及基于OpenGL的一些渲染优化手段。 |