一种3D游戏实时渲染大规模场景的方法及系统与流程

文档序号:12179054阅读:1290来源:国知局
一种3D游戏实时渲染大规模场景的方法及系统与流程

本发明涉及3D渲染技术和大规模场景领域,特别涉及一种3D游戏实时渲染大规模场景的方法及系统。



背景技术:

近年来,实时的游戏画面渲染有了很大的改进。最新的光影技术——动态光源和实时辐射的出现大大改观了游戏画面的光影效果;冲击测绘和三维模型的LOD技术提高了游戏画面的精细度,在Doom 3的引擎中,利用高精度角色模型(100,000+多边形)得到其惊喜的纹理贴图和法向贴图,在游戏渲染时把得到的纹理贴图放到低精度的角色模型(<5000多边形)渲染,这样在保持实时渲染的基础上大大改进了画面的渲染效果。

三维场景的实时渲染技术主要有两大类:基于几何的渲染技术和基于图像的渲染技术。其中基于几何的渲染技术的三维场景,由被定义了多重属性的空间多边形集合体构成,这些多边形几何体上都定义了颜色值、反射度、透明度和相关的光照参数等等。基于图像的渲染技术,其渲染场景是用一组光线映射函数(Plenoptic Function)来描述的。在现在的3D游戏引擎和商业3D图像软件中,一般都采用基于几何的渲染技术。游戏中常用的技术包括以下三个:

1)光影技术。目前,计算机图形学中的光照模型很多,根据光照模型的特点,大致可分为局部光照模型和全局光照模型两类。在三维图形渲染中,多边形顶点上的点的光照颜色值是通过光照模型计算得到,多边形内部点的光照颜色值是通过多边形各定点上的光照颜色值插值生成,即:我们所说的着色技术,各种着色算法不同得到的渲染效果的真实感差异很大。通过多边形顶点和多边形内部采用不同的算法计算光照颜色值,能在大大加速多边形几何体场景的渲染工作。

2)场景筛选。在做图形渲染之前,整个游戏场景中的模型一般都需要做必要的筛选,提出场景中看不到的多边形,避免不必要的额外渲染工作,这样能很大程度的提高整个游戏场景的实时渲染数度,提高游戏引擎的渲染帧率。

3)纹理贴图技术。在几何体的多边形上面附加图像信息(即:图像纹理)能让虚拟三维场景的视觉效果更加逼真。通常一张纹理图像要映射到多个多边形网络上,多层纹理技术能提高实时渲染速度和渲染画面的质量,但会占用更多的内存空间。纹理压缩技术能大幅度减小纹理空间的同时有能保留原有的图像信息,在现代3D渲染技术中,纹理压缩技术应用的非常多。压缩后的纹理占用更少的游戏CD空间,更重要的是,他占用更少的内存和3D显卡的内存空间。

随着3D大规模场景游戏技术的不断发展,对场景的大规模性、真实性等不断提出更新更高的要求。然而,对大规模的场景进行真实、实时渲染一直以来都是图形学界所面对的一个热点和难点问题。

目前,由于Linux操作系统平台的大力推广,基于Linux的各种应用软件也不断壮大,因此基于跨平台图形库的跨平台三维游戏开发也越来越受重视。OpenGL(open graphics library)是一种独立的平台无关的三维图形开发库,在各种语言下进行主框架开发并结合应用OpenGL函数都可以开发出三维游戏。



技术实现要素:

本发明要解决的技术问题是,以大规模场景对真实感和实时性的要求、鲁棒性和易于实现三个标准进行分析,提出了适用于游戏中实时渲染大规模场景的解决方案。

解决上述技术问题,本发明提供了一种3D游戏实时渲染大规模场景系统,包括:地形管理模块、场景模块、光影特效模块以及场景支持模块,

所述地形管理模块,用以根据距离人眼视点的距离实时对地形进行渲染;

所述场景模块,用以渲染大规模场景中的不同场景元素;

所述光影特效模块,用以增强所述大规模场景中的全局光照和软阴影;

所述场景支持模块,用以提供上述地形管理模块、场景模块以及光影特效模块的中运算环境和封装。

更进一步,所述地形管理模块具体基于四叉树的静态LOD地形算法:

按照四叉树数据结构构建四叉树地形,

遍历所述四叉树的节点,更新索引缓冲然后修补地形裂缝。

更进一步,所述光影特效模块中增强所述大规模场景中的全局光照的方法进一步包括:

基于Blinn-Phong光照模型,实现Direct GI直接全局光照,

基于CLPV算法(Cascaded Light Propagation Volumes,层次化光传播体),实现Indirect GI间接全局光照。

更进一步,所述光影特效模块中增强所述大规模场景中的软阴影基于下述的PCSS百分比靠近算法:

4.1)遮挡物查找,对一个接收点着色时,在深度图上确定搜索区域,查找区域内的点的深度值,并计算出比该接收点与光源的距离更小的深度值的均值;

4.2)半影区域大小的确定,所述半影区域的大小由光源大小、遮挡物和接收点的距离以及遮挡物与光源的距离确定:

4.3)滤波,根据所述步骤4.2)计算得到的半影区域大小作为滤波的大小,并使用PCF方法进行滤波。

更进一步,所述场景模块中的场景元素至少包括:{天空、植被、车辆、地形、赛道}。

更进一步,所述地形管理模块,还用以在加载地形时,分别计算出视点均匀分布在地形的64个部分的2个高度的LOD顶点索引,并将128个LOD顶点索引存储为lod文件;

以及,还用以在渲染地形时,根据视点的位置判断当前帧所用的lod文件,将文件解析为顶点索引缓冲。

基于上述本发明还提供了一种3D游戏实时渲染大规模场景实现方法,在打开大规模场景时,包括如下步骤:

根据距离人眼视点的距离实时对地形进行渲染;

渲染所述大规模场景中的不同场景元素,用以提高大规模场景的实时性;

并且,增强所述大规模场景中的全局光照和软阴影,用以增加所述大规模场景真实感。

更进一步,根据距离人眼视点的距离实时对地形进行渲染时,基于四叉树的静态LOD地形算法提高所述大规模场景的渲染速度。

更进一步,根据PCSS算法,增强所述大规模场景中的软阴影。

更进一步,上述大规模场景的地形大小为1024*1024,以满足帧速率至少为30fps

本发明的有益效果:

1)本发明的3D游戏实时渲染大规模场景系统,由于包括所述地形管理模块,用以根据距离人眼视点的距离实时对地形进行渲染;所述场景模块,用以渲染大规模场景中的不同场景元素;所述光影特效模块,用以增强所述大规模场景中的全局光照和软阴影;所述场景支持模块,用以提供上述地形管理模块、场景模块以及光影特效模块的中运算环境和封装。从而能够使得大规模场景能够满足:真实感和实时性、鲁棒性和易于实现的要求。从游戏分析、游戏设计着手,划分出渲染系统的模块;通过对每个模块的详细设计与分析,结合提出的解决方案,最终利用OpenGL开发实现了3D大规模场景游戏的实时渲染系统。

2)采用本发明的方法,对三维渲染中增强实时性和真实感的技术进行调研,以鲁棒性和易于实现作为标准分析出适用于渲染大规模游戏场景的算法,能够对相关开发者提供借鉴和参考。

3)目前越来越受重视的Linux操作系统下的游戏开发在国内占少数。相比于只适用于Windows平台的DirectX,OpenGL在跨平台应用开发中具有一定的优势。本发明使用OpenGL开发,填补了国内跨平台三维游戏开发的空白。

附图说明

图1是本发明3D游戏实时渲染大规模场景系统的结构示意图;

图2是本发明3D游戏实时渲染大规模场景实现方法流程示意图;

图3(a)、(b)是Blinn-Phong模型效果示意图;

图4是PCSS软阴影效果示意图。

图5(a)、(b)是PCSS软阴影效果示意图。

图6是实现静态LOD地形的流程图;

图7所示是程序中定义的四叉树结构体示意图;

图8所示是四叉树节点的huffman码示意图;

图9是LOD地形效果图;

图10所示是天空盒纹理示意图;

图11所示是植被纹理图;

图12是两种草和一种花的分布图;

图13是两种树的分布图。

具体实施方式

现在将参考一些示例实施例描述本公开的原理。可以理解,这些实施例仅出于说明并且帮助本领域的技术人员理解和实施例本公开的目的而描述,而非建议对本公开的范围的任何限制。在此描述的本公开的内容可以以下文描述的方式之外的各种方式实施。

如本文中所述,术语“包括”及其各种变体可以被理解为开放式术语,其意味着“包括但不限于”。术语“基于”可以被理解为“至少部分地基于”。术语“一个实施例”可以被理解为“至少一个实施例”。术语“另一实施例”可以被理解为“至少一个其它实施例”。

在本申请中的主要专业术语及其英文缩略词:

GI:GlobalIllumination,全局光照。

Direct GI:Direct Global Illumination,直接全局光照。

Indirect GI:Indirect Global Illumination,间接全局光照。

lod文件:本文所用的lod文件,其格式等同于文本文件,用于存储索引缓冲。

AO:Ambient Occlusion,环境遮挡。

GLSL:The OpenGL Shading Language。

Huffman编码:一种编码方式,是一种用于无损数据压缩的熵编码(权编码)算法。

可以理解,在本申请中涉及的算法概述如下:

●全局光照算法

目前存在很多全局光照算法,其目的都是模拟或估计物体表面之间的反射效果,这些算法以其不同的优缺点而适用于不同的应用[20]。本节将介绍用于工业界计算机游戏开发的主要的全局光照算法。

计算机游戏对全局光照算法的要求是优先考虑运行速度、其次考虑渲染效果[Jaroslav Kivnek,Marcos Fajardo,Per H.Christensen,et al.Global Illumination Across Industries.ACM SIGGRAPH 2010 Courses.2010.]。对于Direct GI,可使用OpenGL管线中使用的默认明暗处理模型Blinn-Phong。对于Indirect GI,基于点的全局光照(Point-Based Global Illumination)的间接光照,区域光源可产生较好的效果,但该方法的运行速度较慢,不适用于大规模场景[Jaroslav Kivnek,Marcos Fajardo,Per H.Christensen,et al.Global Illumination Across Industries.ACM SIGGRAPH 2010 Courses.2010.];预计算光照(Pre-computed Radiance Lighting)能够满足任何场景对运行速度和渲染效果的要求,但场景必须是静态的,不适用于交互应用;Peter-Pike Sloan提出的ProxyPG[Peter-Pike Sloan,PNaga K.Govindaraju,Derek Nowrouzezahrai,PJohn Snyder.Image-Based Proxy Accumulation for Real-Time Soft Global Illumination.Proceedings of the 15th Pacific Conference on Computer Graphics and Applications,2007,97-105.]能满足交互场景的实时渲染,但该方法需要限制场景的规模才能保证渲染速度,不适用于大规模场景;Crytek GmbH实验室提出的Cascaded Light Propagat ion Volumes(CLPV)[Anton Kaplanyan,Carsten Dachsbacher.Cascaded Light Propagation Volumes for Real-Time Indirect Illumination.Proceeding of the 2010 Symposium on Interactive 3D Graphics and Games,2010.]能够实现对漫反射表面的低频Indirect GI,其运行速度和光照效果都比较完美,该方法已经在CryENGINE 2中使用。

●软阴影算法

本节对于软阴影算法作一个简单的回顾。本节内容介绍的算法主要模拟在真实世界中的扩展光源的作用下生成的软阴影效果。扩展光源的类型从遥远的环境光到区域光源不等。由于人眼对于阴影的形状远没有对几何体本身的形状敏感,尤其是对于环境光源下的软阴影,人眼对其精确性的敏感度很低[梅春晖.基于预计算及采样的实时高真实感图像绘制技术研究[D].浙江大学2004]。根据这个特征,利用形状简单的近距离光源即可生成逼真的软阴影,以下介绍的算法主要使用这种光源。

A,准确的软阴影生成方法

目前,在包含合理光源的动态场景中,最有效的算法是视点采样映射(View-Sample Mapping)方法。复杂深度采样(Depth-Complexity Sampling)方法总体计算速度更慢,仅在光源较大时比较游泳,而视点采样映射在光源较大时计算量很大。遗憾的是,在这种场景下,不能只考虑从光源中心投下的阴影轮廓边缘。只考虑这个因素会使更多的边缘被转换成四边形图元,从而极大增加软阴影锥的计算开销。尽管如此,表述的原理可以使用改进的遮挡物数据结构去实现更有效的光线追踪。但是目前看来,这种方法更适用于离线渲染,在动态场景改变时会产生诸多问题。如果要求软阴影非常准确,可以使用光束追踪,但当图元比较复杂时该方法的计算开销将非常大。生成实时交互的准确软阴影还有待研究。

B,近似的软阴影生成方法

这种方法在目前是实时应用中最有趣的软阴影方法,使用合理的计算开销便可达到较好的软阴影效果。百分比靠近算法(Percentage-Closer Soft Shadows,PCSS)[Randima Fernando.Percentage-closer soft shadows.In ACM SIGGRAPH 2005 Sketches,July 2005]是目前交互应用中使用最广的方法,比如游戏。该方法能以可接受的速度在较小的光源下生成合理的阴影。PCSS的一个重要特点是可以应用于大规模场景并生成真实的太阳光效果。如果场景较小,可使用遮挡纹理(Occlusion Textures)[Elmar Eisemann and Xavier decoret.Plausible image based soft shadows using occlusion textures.In Proceedings of SIBGRAPI 2006,pages 155-162,October 2006b]。遮挡纹理的速度非常快(在Geforce 6 GPU实时运行可渲染500000个多边形),其优势是与光源的大小无关,从而能以较低的计算开销生成较好的软阴影,并为有较大光源的室内场景渲染提供了一个很好的方案。但是,对于大规模场景,Occlusion Textures的效果并不理想。

若场景要求更高的准确度和更多的鲁棒性,可使用反向投影,该方法在[Gael Guennebaud,Loic Barthe,and Mathias Paulin.Real-time soft shadow mapping by back-projection.In Proceedings of Eurographics Symposium on Rendering 2006,pages 227-234,June 2006]中提出。使用遮挡位掩码可生成及其准确的软阴影,同时使用微四边形[Michael Schwarz and marc Stamminger.Bitmask soft shadows.Computer Graphics Forum(Proceedings of Eurographics 2007),26(3):515-524,September 2007]可优化该阴影效果。遮挡轮廓[Gael Guennebaud,Loic Barthe,and Mathias paulin.High-quality adaptive soft shadow mapping.Computer Graphics Forum(Proceedings of Eurographics 2007),26(3):525-533,September 2007和简单的区域累积也能渲染出不错的效果;比该方法更快的方案是采取等级轮廓提取和基于包的处理[Baoguang Yang,Jieqing Feng,Gael Guennebaud,and Xinguo Liu.Packet-based hierarchal soft shadow mapping.Computer Graphics Forum(Proceedings of Eurographics Symposium on Rendering 2009),28(4):1121-1130,June2009]。通常来讲,实现较好软阴影和较高运行速度可能需要用粗糙地近似遮挡物,但粗糙地近似遮挡物需要避免类似明显的渐变的走样;特别地,使用该方法需要合理调整场景,否则其结果不会比简单的PCSS的视觉效果更好。

请参考图1所示是本发明3D游戏实时渲染大规模场景系统的结构示意图,一种3D游戏实时渲染大规模场景系统,包括:地形管理模块1、场景模块2、光影特效模块4以及场景支持模块3,

所述地形管理模块1,用以根据距离人眼视点的距离实时对地形进行渲染;

所述场景模块2,用以渲染大规模场景中的不同场景元素;

所述光影特效模块4,用以增强所述大规模场景中的全局光照和软阴影;

所述场景支持模块3,用以提供上述地形管理模块、场景模块以及光影特效模块的中运算环境和封装。

具体地,所述光影特效模块4用以全局光照实现,本申请中使用Blinn-Phong实现Direct GI、CLPV实现Indirect GI。

Blinn-Phong原理

Blinn-phong光照模型[blinn-phong]是基于Phong[phong]的修正模型,由Jim Blinn提出。Blinn-Phong模型与Phong模型的区别是,把dot(V,R)换成了dot(N,H),其中H为半角向量,位于法线N和光线L的角平分线方向。Blinn-Phong模型可表示为:

Ispecular=Ks×Is×pow(dot(N,H),n)

其中H=(L+V)/|L+V|,计算H比计算反射向量R更快速。

具体地,所述光影特效模块4还用以软阴影实现,

百分比靠近算法(PCSS)原理:

PCSS技术建立在标准的阴影映射的基础上:在视锥内给每一个像素着色时,PCSS返回一个浮点数表示该像素对应的几何点的阴影数量(代替了标准阴影映射的深度比较)。同时PCSS建立与PCF内核,当PCF内核增大时,阴影变得更加柔和。该算法的关键在于变化滤波内核的大小生成逼真的软阴影。如何调整滤波内核的大小使阴影达到理想的柔和程度是一个挑战。PCSS假设遮挡物、光源和接收物是平行的。如图3(a)、(b)所示是Blinn-Phong模型效果示意图。如图4所示是PCSS软阴影效果示意图。如图5(a)、(b)所示,是PCSS软阴影效果示意图。

步骤1:遮挡物查找(Blocker search)。对一个接收点(属于接收物)着色时,在深度图上确定搜索区域,查找区域内的点的深度值,并计算出比该接收点与光源的距离更小的深度值的均值。其中,搜索区域的大小根据光源的大小、接收物与光源的距离确定。此处得出的均值用于确定步骤2的半阴影区域大小。

步骤2:半影区域大小的确定(Penumbra estimation)。假设遮挡物、光源和接收物是平行的,半影区域的大小由光源大小、遮挡物和接收点的距离以及遮挡物与光源的距离确定:

wpenumbra=(dReceiver-dBlocker)×wLight/dBlocker

步骤3:滤波(Filtering)。我们使用步骤2计算的半影区域大小作为滤波的大小,使用PCF方法进行滤波。如图

具体地,所述地形管理模块1用以实现根据距离人眼视点的距离实时对地形进行渲染。主要基于四叉树的静态LOD地形原理:

一般的地形是这样实现的:整个地形是一个三角形网格,本文的地形大小是1024*1024,包括1024*1024个顶点、1024*1024*2个三角形;在开始渲染地形之前,写入地形的顶点缓冲和索引缓冲;每一帧渲染地形的时候,只根据索引缓冲便可渲染出地形。

LOD地形利用人眼对几何形状的敏感度简化了地形的渲染:在距离视点较近的地方,渲染较多的三角网格,地形细致真实;距离视点较远的地形,渲染较少的三角网格,地形比较粗糙。所以,LOD地形每一帧渲染的顶点个数小于一般地形每一帧渲染的顶点个数,其渲染速度比一般地形的渲染速度高。

基于四叉树的LOD地形则是以四叉树为数据结构来表示地形,运行时每一帧所用的三角网格在当前帧计算:

1.运行前的预处理:构建四叉树地形。

2.运行时的每一帧:

1)提取三角网格。本文在提取三角网格时,采用Brian(1987)的细分标准来决定每个四叉树节点的等级。这个步骤生成一个无限制的四叉树,同时该四叉树的叶子节点就是在这一帧渲染的节点。但是,这个步骤带来的问题是地形裂缝。

2)修补裂缝。在修补地形裂缝时,本文参考CryENGINE 3生成的LOD地形的图案,并设计出一个类似Huffman编码的方法生成了该图案。

上述步骤是动态LOD地形每一帧的运行流程。由于在运行时每一帧更新三角网格的计算量比较大,程序的帧速率下降到10fps,本文采用静态LOD地形。静态LOD地形的不同是,运行时每一帧所用的三角网格在预处理中计算并保存,运行时调用保存的lod文件。从lod文件中读取三角网格的速度远远大于计算三角网格的速度,程序的帧速率上升到150+fps:

1.运行前的预处理:执行动态LOD地形的2个步骤,分别计算出视点均匀分布在地形的64个部分的2个高度的LOD顶点索引,并将这128个LOD顶点索引存储为lod文件;

2.运行时的每一帧:根据视点的位置判断当前帧所用的lod文件,将文件解析为顶点索引缓冲。

图6是实现静态LOD地形的流程图,以下介绍关键步骤的实现过程,即四叉树数据结构的设计、建造四叉树地形、更新索引缓冲、修补裂缝:

●四叉树数据结构

地形的四叉树结构QuadTreeData的核心属性:

m_nCenter:int,中心顶点的索引。

m_nCorner[4]:int,左上、右上、左下、右下顶点的索引。

m_pChild[4]:QuadTreeData*,左上、右上、左下、右下四个孩子节点。

m_bRealLeaf:bool,真实叶子变量。

m_bVirtualLeaf:bool,虚拟叶子变量。

如图7所示是程序中定义的四叉树结构体示意图。

●构建四叉树地形

一个5*5的地形,头节点的m_nCenter是12,m_nCorner[4]依次是0、4、20、24,m_pChild[0]的m_nCenter是6,m_nCorner[4]依次是0、2、10、12,m_pChild[1]、m_pChild[2]、m_pChild[3]的属性值可以此类推。我们可以设定整个四叉树的最多层级,比如9,头结点的层级是0。若某个四叉树节点的m_nCorner[1]和m_nCorner[0]相差为1,或者该四叉树节点位于整个四叉树的第9层,则该四叉树节点为真实叶子,其m_bRealLeaf值为true,四个孩子节点的值均为空NULL,至此,整个地形的四叉树建造完成。

●更新索引缓冲

首先更新虚拟叶子节点:遍历四叉树的每个节点,并评价每个节点:若该节点为真实节点,则该节点不可再分,将virtualLeaf设置为true;若该节点为虚拟节点,若该节点不满足评价公式(不可再细分),则将该节点的virtualLeaf设置为true。否则将virtualLeaf设置为false(评价公式:g=d/e×r×C1×C2,当g<1,则该节点可再分,virtualLeaf设置为false。其中,d表示节点和摄像机的距离;e表示节点边长;r=e/diff,其中diff表示该节点四个角最大高度与最小高度的差值;C1、C2代表分辨率。)。

●修补地形裂缝

大致思路是:四叉树的每个节点都有自己的huffman编码,通过huffman编码可以遍历到自己的位置。

每个节点同等级的上、下、左、右兄弟节点的huffman编码可以根据自己处于父节点的位置(左上、右上、左下、右下)推导出来。在第一步更新了四叉树的虚拟叶子节点之后,遍历所有的虚拟叶子节,通过每个叶子节点的左上、右上、左下、右下兄弟节点的huffman编码找到每个叶子节点的兄弟节点,若兄弟节点的virtualLeaf值为false,则在兄弟节点与该节点共享的边上存在裂缝,进行修补:找出兄弟节点在该边因细分所添加的三角形网的顶点,将这些点的索引依次压入该节点该条边用于修补裂缝的点的链表。至此,修补裂缝结束。如图8所示是四叉树节点的huffman码示意图。图9是LOD地形效果图。

具体地,所述场景模块2,用以渲染大规模场景中的不同场景元素:

1)天空盒实现

天空盒的类图如下图所示,Plit表示点光源的信息;天空盒的几何信息存储在v[8]、vn[8]和vt[8]中,分别表示顶点位置坐标、顶点法线坐标、顶点纹理坐标,这些属性的值在初始化时Init()中计算。

天空盒的纹理如下图所示:天空盒六个面的纹理从左至右、从上至下依次为背面、底部、前面、左边、右边、顶部。纹理文件是texture\skybox\back_bottom_front-left_right_top.ppm,程序中在Viewer.h中定义为texSkybox。

天空盒的GLSL文件是Shader\shadingSkybox.frag和Shader\shadingSkybox.vert,程序中在Viewer.h中定义为shadingSkybox。如图10所示是天空盒纹理示意图。

●基本渲染流程

天空盒的渲染在Viewer.cpp文件中的drawSkybox()中实现:

每一帧调用V()、Size()获取天空盒的顶点位置、VN()获取顶点法线、VT()获取顶点纹理;

使用GLSL实现shadingSkybox.frag和shadingSkybox.vert中动态云和动态太阳的效果。

●动态云的实现

动态云的实现有两种方案:

模拟三维云朵。制作云朵模型,在程序中根据光照给模型着色,同时根据云朵的移动速度更新模型的位置。

移动天空纹理。在每一帧根据云朵的移动速度的逆方向更新顶部天空盒的纹理贴图坐标。

模拟三维云朵时,根据光照给云朵着色的部分渲染比较耗时,因为云朵各部分的折射、反射等计算;同时其效果也不太理想,目前图形界在云朵模拟方面尚未有效果比较理想的成熟的方案。所以本游戏采用第二种方案来实现动态云,在UpdateCloud()中实现,使用cloudSpeed更新vt中天空盒顶部的参数。

●动态太阳的实现

太阳属于点光源,在本程序中用属性sun表示。本程序中每一帧根据太阳的大小sun.size、太阳的位置sun.p来渲染一个发光球,发光球的亮度用sun.intensity表示。太阳的位置sun.p根据移动速度sunSpeed来更新。

移动太阳可带来天空效果的变化,即天空盒不同部位的明暗变化。此效果在shadingSkybox.frag中使用顶点法线和太阳位置与顶点坐标的向量的cosine值来实现:

2)植被系统实现

植被系统设计了一种花、两种草、两种树,其类图如下图所示,LeafVertex表示植被的顶点信息,在初始化植被顶点和顶点索引的时候使用;两种草、一种花、两种树的模型、两种树的叶子在程序中有不同的纹理,故分开渲染,其几何信息分别用t2f_v3f_grass1、t2f_v3f_grass2、t2f_v3f_flower、t2f_v3f_tree1、t2f_v3f_tree2、t2f_v3f_treeLeaf1、t2f_v3f_treeLeaf2中表示,索引信息分别用elements_grass1、elements_grass2、elements_flower、elements_tree1、elements_tree2、element_treeLeaf1、element_treeLeaf2表示。以上属性的值在初始化时Create()、CreateGrassFlower()、CreateTree()中计算。

植被中的树模型分别是model\tree1.obj、model\tree2.obj。植被纹理如下图所示,其文件位置在texture目录下;程序中,上述纹理在Viewer.h中定义为texFlower、texGrass1、texGrass2、texTree1、texTree2、texTreeLeaf1、texTreeLeaf2。

植被系统的的GLSL文件是Shader\shadingPlant.frag和Shader\shadingPlant.vert,程序中在Viewer.h中定义为shadingPlant。

●基本渲染流程

植被系统的渲染在Viewer.cpp文件中的drawPlant()中实现:

调用T2F_V3F_Flower()和Elements_Flower()获取花的顶点坐标和顶点索引;

将Viewer.h中的texFlower作为纹理、使用GLSL实现shadingPlant.vert中花草的风动效果。

●植被的初始化

两种草、一种花和两种树的树叶的初始化类似DirectX中的公告板原理,两种树的模型的初始化使用模型加载。初始化之后所有类型的植被被表示为顶点索引缓冲和顶点缓冲,如图11所示是植被纹理图。下面介绍初始化的过程。

图12是两种草和一种花的分布图,对应程序中的resource\drawPlant.ppm文件。该图的大小是1024*1024,等同于地形的大小。其中红色代表花的分布,绿色代表第一种草,蓝色代表第二种草。花草的几何信息的初始化在CreateFlowerGrass()实现:加载分布图文件、根据分布图中像素的颜色和位置标记t2f_v3f_flower、t2f_v3f_grass1、t2f_v3f_grass2的顶点位置,在FlushVertexFlowerGrass()中计算以上属性及其对应索引的值。

图13是两种树的分布图,对应程序中的resource\treeRange.ppm文件。该图的大小也是1024*1024,等同于地形的大小。其中绿色代表第一种树,蓝色代表第二种树。树的几何信息的初始化在CreateTree()实现:加载分布图文件、加载树的模型、根据分布图中像素的颜色和位置标记两种树的模型和t2f_v3f_treeLeaf1、t2f_v3f_treeLeaf2的顶点位置,在FlushVertexTreeLeaf()中计算以上属性及其对应索引的值。

●风动效果的实现

植被的风动效果原理非常简单,就是使顶点随时间呈现余弦状波动效果。此效果在shadingPlant.vert中实现,核心代码如下:

gl_Position=gI_ModelViewProjectionMatrix×gl_Vertex

gl_Position+=windDirxcos(time)

其中,windDir表示风向,time表示全局时间。

3)车辆渲染实现

车辆不同部位的材质有所不同,主要分为车体、车窗和轮胎,所以这三个部分的顶点需要分别渲染,所以模型文件也需要分别加载。车辆类的类图如下所示:body、window、metalWheel、rubberWheel分别表示车体、车窗、金属部分的车轮、橡胶部分的车轮,其模型都属于Wavefront.OBJ格式。特别地,玩家驾驶车辆会使得车轮相对与车身产生旋转,所以,程序中使用变换矩阵transWheel来表示车轮相对与车身的旋转效果。

车辆模型分为车体、车窗、金属部分的车轮和橡胶部分的车轮,模型文件分别是model\carBody.obj、model\carWindow.obj、model\carMetalWheel.obj、model\carRubberWheel.obj;对应的纹理文件是texture\car\carBodyF.ppm、texture\car\carBodyB.ppm、texture\car\carBodyL.ppm、texture\car\carBodyR.ppm、texture\car\carBodyU.ppm、texture\car\carWindow.ppm、texture\car\carMetalWheel.ppm、texture\car\carRubberWheel.ppm;程序中,上述纹理分别在Viewer.h中定义:texCarBodyF,texCarBodyB,texCarBodyU,texCarBodyL,texCarBodyR,texCarMetalWheel,texCarRubberWheel;

车辆渲染的GLSL文件是Shader\shadingCar.frag和Shader\shadingCar.vert,程序中在Viewer.h中定义为shadingCar。

●基本渲染流程

车辆的渲染在Viewer.cpp文件中的drawCar()中实现:

调用T2F_N3F_V3F_Body()和Elements_Body()获取车体渲染所用的缓冲数据,即纹理坐标、法线坐标、顶点坐标、顶点索引;金属部分车轮和橡胶部分车轮的缓冲数据的调用类似于车体,即调用T2F_N3F_V3F_MetalWheel()和Elements_MetalWheel()、T2F_N3F_V3F_RubberWheel()

和Elements_RubberWheel();特别地,车窗属于半透明材质,没有纹理,所以其渲染所用的缓冲数据只包括法线坐标、顶点坐标和顶点索引,调用N3F_V3F_Window()和Elements_Window()。

将Viewer.h中的texCarBodyF,texCarBodyB,texCarBodyU,texCarBodyL,texCarBodyR,texCarMetalWheel,texCarRubberWheel作为纹理、使用GLSL实现shadingCar.frag中车体的环境映射效果、车窗的环境映射效果(视点在车外)、车窗的环境折射效果(视点在车内)、车窗的半透明效果、轮胎的漫反射效果。

●环境贴图实时更新的实现

当赛车在场景内漫游时,车体和车窗应该反射出周围的环境;当视点在车内的时候,从半透明车窗内看到折射后的环境。程序中使用环境贴图来实现上述效果,而环境的动态体现在环境贴图的实时更新。

实时更新环境贴图的思路是:每一帧渲染车辆之前,将摄像机位于车辆的位置,以向上、向下、向左、向右、向前、向后为视点将场景渲染六遍,获得环境贴图的六个纹理,使用这六个纹理更新当前帧的环境贴图。

在程序中,环境贴图的更新在Viewer.h中的updateEnv()中实现:使用FrameBufferObject[ref]envFBO来渲染六个纹理texEnvUp,texEnvBottom,texEnvLeft,texEnvRight,texEnvBack,texEnvFront;使用六个纹理更新环境贴图cubeMap。

●环境映射、环境折射的实现

在GLSL中,环境映射和环境折射的原理一致:获取环境贴图在某个方向的像素值。环境映射和环境折射的不同体现在获取纹理像素值的向量不同:环境映射的向量是某一个几何点与视点组成的向量的反射向量;环境折射的向量是某一个几何点与视点组成的向量的折射向量。计算出获取纹理像素值的向量之后,可以调用GLSL的函数textureCube来获取在该向量方向的纹理。

在shadingCar.frag中,传入更新的cubeMap,环境映射和环境折射的核心代码如下:

环境映射

shadingCar.vert:

vec3InVec=normalize(pos-EyePos);//顶点到眼睛的入射向量

R=reflect(InVec,norm);//norm:顶点法线

shadingCar.frag:

gl_FragColor=textureCube(EnvMap,R);

环境折射

shadingCar.vert:

vec3InVec=normalize(pos-EyePos);//顶点到眼睛的入射向量

T=refract(InVec,norm,ior);//ior:折射率;norm:顶点法线

shadingCar.frag:

gl_FragColor=textureCube(EnvMap,T);

此处描述的折射计算只能处理一次折射的效果,对于两次折射的计算,可参考的方法。

请参考图2是本发明3D游戏实时渲染大规模场景实现方法流程示意图,一种3D游戏实时渲染大规模场景实现方法,在打开大规模场景时包括如下步骤:

步骤S100根据距离人眼视点的距离实时对地形进行渲染;在步骤S100中根据距离人眼视点的距离实时对地形进行渲染时,基于四叉树的静态LOD地形算法提高所述大规模场景的渲染速度。步骤S101渲染所述大规模场景中的不同场景元素,用以提高大规模场景的实时性;步骤S102增强所述大规模场景中的全局光照和软阴影,用以增加所述大规模场景真实感。步骤S102中根据PCSS算法,增强所述大规模场景中的软阴影。上述大规模场景的地形大小为1024*1024,以满足帧速率至少为30fps。

虽然本公开以具体结构特征和/或方法动作来描述,但是可以理解在所附权利要求书中限定的本公开并不必然限于上述具体特征或动作。而是,上述具体特征和动作仅公开为实施权利要求的示例形式。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1