游戏引擎剖析.doc

上传人:本田雅阁 文档编号:2786067 上传时间:2019-05-16 格式:DOC 页数:18 大小:74.97KB
返回 下载 相关 举报
游戏引擎剖析.doc_第1页
第1页 / 共18页
游戏引擎剖析.doc_第2页
第2页 / 共18页
游戏引擎剖析.doc_第3页
第3页 / 共18页
游戏引擎剖析.doc_第4页
第4页 / 共18页
游戏引擎剖析.doc_第5页
第5页 / 共18页
点击查看更多>>
资源描述

《游戏引擎剖析.doc》由会员分享,可在线阅读,更多相关《游戏引擎剖析.doc(18页珍藏版)》请在三一文库上搜索。

1、游戏引擎剖析第1部分:游戏引擎介绍,渲染和构造3D世界介绍自Doom游戏时代以来我们已经走了很远。DOOM不只是一款伟大的游戏,它同时也开创了一种新的游戏编程模式:游戏引擎。这种模块化,可伸缩和扩展的设计观念可以让游戏玩家和程序设计者深入到游戏核心,用新的模型,场景和声音创造新的游戏,或向已有的游戏素材中添加新的东西。大量的新游戏根据已经存在的游戏引擎开发出来,而大多数都以ID公司的Quake引擎为基础,这些游戏包括Counter Strike,Team Fortress,Tac Ops,Strike Force,以及Quake Soccer。Tac Ops和Strike Force都使用了U

2、nreal Tournament引擎。事实上,游戏引擎已经成为游戏玩家之间交流的标准用语,但是究竟引擎止于何处,而游戏又从哪里开始呢?像素的渲染,声音的播放,怪物的思考以及游戏事件的触发,游戏中所有这一切的幕后又是什么呢?如果你曾经思考过这些问题,而且想要知道更多驱动游戏进行的东西,那么这篇文章正好可以告诉你这些。本文分多个部分深入剖析了游戏引擎的内核,特别是Quake引擎,因为我最近工作的公司Raven Software已经在Quake引擎的基础上开发出了多款游戏,其中包括著名的Soldier of Fortune。开始让我们首先来看看一个游戏引擎和游戏本身之间的主要区别。许多人们会混淆游戏

3、引擎和整个游戏。这有点像把一个汽车发动机和整个汽车混淆起来一样。你能够从汽车里面取出发动机,建造另外一个外壳,再使用发动机一次。游戏也像那。游戏引擎被定义为所有的非游戏特有的技术。游戏部份是被称为资产的所有内容(模型,动画,声音,人工智能和物理学)和为了使游戏运行或者控制如何运行而特别需要的程序代码,比如说AI-人工智能。对于曾经看过Quake游戏结构的人来说,游戏引擎就是Quake。exe,而游戏部分则是QAGame。dll和CGame。dll。如果你不知道这是什么意思,也没有什么关系;在有人向我解释它以前,我也不知道是什么意思。但是你将会完全明白它的意思。这篇游戏引擎指导分为十一个部份。是

4、的,从数量上来说,总共是十一个部份!每个部分大概3000字左右。现在就从第一部分开始我们的探索吧,深入我们所玩游戏的内核,在这里我们将了解一些基本的东西,为后面的章节作铺垫。渲染器让我们从渲染器来开始游戏引擎设计的探讨吧,我们将从游戏开发者(本文作者的背景)的角度来探讨这些问题。事实上,在本文的各个段落,我们将常常从游戏开发者的角度探讨,也让您像我们一样思考问题!什么是渲染器,为什么它又这么重要呢?好吧,如果没有它,你将什么也看不到。它让游戏场景可视化,让玩家/观众可以看见场景,从而让玩家能够根据屏幕上所看到的东西作出适当的决断。尽管我们下面的探讨可能让新手感到有些恐惧,先别去理会它。渲染器做

5、些什么?为什么它是必须的?我们将会解释这些重要问题。当构造一个游戏引擎的时候,你通常想做的第一件事情就是建造渲染器。因为如果看不见任何东西那么你又如何知道你的程序代码在工作呢?超过50%的CPU处理时间花费在渲染器上面;通常也是在这个部分,游戏开发者将会受到最苛刻的评判。如果我们在这个部分表现很差,事情将会变得非常糟糕,我们的程序技术,我们的游戏和我们的公司将在10天之内变成业界的笑话。它也是我们最依赖于外部厂商和力量的地方,在这里他们将处理最大限度的潜在操作目标。如此说来,建造一个渲染器确实不象听起来那么吸引人(事实如此),但如果没有一个好的渲染器,游戏或许永远不会跻身于排行榜前10名。如今

6、,在屏幕上生成像素,涉及到3D加速卡,API,三维空间数学,对3D硬件如何工作的理解等等。对于主机(游戏机)游戏来说,也需要相同类型的知识,但是至少对于主机,你不必去尝试击中一个移动中的目标。因为一台主机的硬件配置是固定的时间快照,和PC(个人计算机)不同,在一台主机的生命期中,它的硬件配置不会改变。在一般意义上,渲染器的工作就是要创造出游戏的视觉闪光点,实际上达到这个目标需要大量的技巧。3D图形本质上是用最少的努力创造出最大效果的一门艺术,因为额外的3D处理在处理器时间和和内存带宽方面都是极为昂贵的。它也是一种预算,要弄清楚你想在什么地方花费处理器时间,而你宁愿在什么地方节省一些从而达到最好

7、的整体效果。接下来我们将会介绍一些这方面的工具,以及怎样更好的用它们让游戏引擎工作。建造3D世界最近,当我和一位从事计算机图形方面工作长达数年之久的人会谈时,她向我吐露道,当她第一次看到实时操纵计算机3D图象时,她不知道这是怎么实现的,也不知道计算机如何能够存储3D图象。今天这对于在大街上的普通人来说或许是真实的,即使他们时常玩PC游戏,游戏机游戏,或街机游戏。下面我们将从游戏设计者的角度讨论创造3D世界的一些细节,你也应该看一看Dave Salvator所写的3D管线导论,以便对3D图象生成的主要过程有一个整体的了解。3D物体(对象)被储存成3D世界中的一系列点(被称为顶点),彼此之间有相互

8、关系,所以计算机知道如何在世界中的这些点之间画线或者是填充表面。一个立方体由8个点组成,每个角一个点。立方体有6个表面,分别代表它的每一个面。这就是3D对象储存的基础。对于一些比较复杂的3D物体,比如说一个Quake的关卡,将有数以千计(有时数以十万计)的顶点,和数以千计的多边形表面。参见上图的线框表示(注:原文在这里有一幅图)。本质上与上面的立方体例子类似,它仅仅是由许许多多的小多边形组成的一些复杂场景。模型和世界如何储存是渲染器的一部份功能,而不属于应用程序/游戏部份。游戏逻辑不需要知道对象在内存中如何表示,也不需要知道渲染器将怎样把他们显示出来。游戏只是需要知道渲染器将使用正确的视野去表

9、示对象,并将在正确的动画帧中把正确的模型显示出来。在一个好的引擎中,渲染器应该是可以完全被一个新的渲染器替换掉,并且不需要去改动游戏的一行代码。许多跨平台引擎,而且许多自行开发的游戏机引擎就是这样的,如Unreal引擎,-举例来说,这个游戏GameCube版本的渲染器就可以被你任意的替换掉。让我们再看看内部的表示方法-除了使用坐标系统,还有其他方法可以在计算机内存里表示空间的点。在数学上,你可以使用一个方程式来描述直线或曲线,并得到多边形,而几乎所有的3D显示卡都使用多边形来作为它们的最终渲染图元。一个图元就是你在任何显示卡上面所能使用的最低级的绘制(渲染)单位,几乎所有的硬件都是使用三个顶点

10、的多边形(三角形)。新一代的nVidia和ATI显卡可以允许你以数学方式渲染(被称为高次表面),但因为这不是所有图形卡的标准,你还不能靠它作为渲染策略。从计算的角度来看,这通常有些昂贵,但它时常是新的实验技术的基础,例如,地表的渲染,或者对物件锐利的边缘进行柔化。我们将会在下面的曲面片小节中更进一步介绍这些高次表面。剔除概观问题来了。我现在有一个由几十万个顶点/多边形描述的世界。我以第一人称视角位于我们这个3D世界的一边。在视野中可以看见世界的一些多边形,而另外一些则不可见,因为一些物体,比如一面看得见的墙壁,遮挡住了它们。即使是最好的游戏编码人员,在目前的3D显卡上,在一个视野中也不能处理3

11、00,000个三角形且仍然维持60fps(一个主要目标)。显卡不能处理它,因此我们必须写一些代码,在把它们交给显卡处理之前除去那些看不见的多边形。这个过程被称为剔除。有许多不同的剔除方法。在深入了解这些之前,让我们探讨一下为什么图形显示卡不能处理超高数量的多边形。我是说,最新的图形卡每秒钟不能处理几百万个多边形吗?它不应该能够处理吗?首先,你必须理解市场销售宣称的多边形生成率和真实世界的多边形生成率。行销上宣称的多边形生成率是图形显示卡理论上能够达到的多边形生成率。如果全部多边形都在屏幕上,相同的纹理,相同的尺寸大小,正在往显示卡上传送多边形的应用程序除了传送多边形以外什么也不做,这时显卡能处

12、理多少多边形数量,就是图形芯片厂商呈现给你的数字。然而,在真实的游戏情形中,应用程序时常在后台做着许多其他的事情-多边形的3D变换,光照计算,拷贝较多的纹理到显卡内存,等等。不仅纹理要送到显示卡,而且还有每个多边形的细节。一些比较新的显卡允许你实际上在显卡内存本身里面储存模型/世界几何细节,但这可能是昂贵的,将会耗光纹理正常可以使用的空间,所以你最好能确定每一帧都在使用这些模型的顶点,否则你只是在浪费显示卡上的存储空间。我们就说到这里了。重要的是,在实际使用显卡时,并不必然就能达到你在显卡包装盒上所看到的那些指标,如果你有一个比较慢速的CPU,或没有足够的内存时,这种差异就尤为真实。基本的剔除

13、方法最简单的剔除方式就是把世界分成区域,每个区域有一个其他可见区域的列表。那样,你只需要显示针对任何给定点的可见部分。如何生成可见视野区域的列表是技巧所在。再者,有许多方法可以用来生成可见区域列表,如BSP树,窥孔等等。可以肯定,当谈论DOOM或QUAKE时,你已经听到过使用BSP这个术语了。它表示二叉空间分割。BSP是一种将世界分成小区域的的方法,通过组织世界的多边形,容易确定哪些区域是可见的而哪些是不可见的从而方便了那些不想做太多绘制工作的基于软件的渲染器。它同时也以一种非常有效的方式让你知道你位于世界中的什么地方。在基于窥孔的引擎(最早由3D Realms已经取消的Prey项目引入游戏世

14、界)里,每个区域(或房间)都建造有自己的模型,通过每个区域的门(或窥孔)能够看见另外的区段。渲染器把每个区域作为独立的场景单独绘制。这就是它的大致原理。足以说这是任何一个渲染器的必需部份,而且非常重要。尽管一些这样的技术归类在遮挡剔除之下,但是他们全部都有同样的目的:尽早消除不必要的工作。对于一个FPS游戏(第一人称射击游戏)来说,视野中时常有许多三角形,而且游戏玩家承担视野的控制,丢弃或者剔除不可见的三角形就是绝对必要的了。对空间模拟来说也是这样的,你可以看见很远很远的地方剔除超过视觉范围外面的东西就非常重要。对于视野受到限制的游戏来说比如RTS(即时战略类游戏)-通常比较容易实现。通常渲染

15、器的这个部份还是由软件来完成,而不是由显卡完成,由显卡来做这部分工作只是一个时间问题。基本的图形管线流程一个简单的例子,从游戏到多边形绘制的图形管线过程大致是这样:游戏决定在游戏中有哪些对象,它们的模型,使用的纹理,他们可能在什么动画帧,以及它们在游戏世界里的位置。游戏也决定照相机的位置和方向。游戏把这些信息传递给渲染器。以模型为例,渲染器首先要查看模型的大小,照相机的位置,然后决定模型在屏幕上是否全部可见,或者在观察者(照相机视野)的左边,在观察者的后面,或距离很远而不可见。它甚至会使用一些世界测定方式来计算出模型是否是可见的。(参见下面这条)世界可视化系统决定照相机在世界中的位置,并根据照

16、相机视野决定世界的哪些区域/多边形是可见的。有许多方法可以完成这个任务,包括把世界分割成许多区域的暴力方法,每个区域直接为我能从区域D看见区域AB&C,到更精致的BSP(二叉空间分割)世界。所有通过这些剔除测试的多边形被传递给多边形渲染器进行绘制。对于每一个被传递给渲染器的多边形,渲染器依照局部数学(也就是模型动画)和世界数学(相对于照相机的位置?)对多边形进行变换,并检查决定多边形是不是背对相机(也就是远离照相机)。背面的多边形被丢弃。非背面的多边形由渲染器根据发现的附近灯光照亮。然后渲染器要看多边形使用的纹理,并且确定API/图形卡正在使用那种纹理作为它的渲染基础。在这里,多边形被送到渲染

17、API,然后再送给显卡。很明显这有些过分简单化了,但你大概理解了。下面的图表摘自Dave Salvators 3D管线一文,可以给你多一些具体细节:3D管线-高层的概观1.应用程序/场景场景/几何数据库遍历对象的运动,观察相机的运动和瞄准对象模型的动画运动3D世界内容的描述对象的可见性检查,包括可能的遮挡剔除细节层次的选择(LOD)2.几何变换(旋转,平移,缩放)从模型空间到世界空间的变换(Direct3D)从世界空间到观察空间变换观察投影细节接受/拒绝剔除背面剔除(也可以在后面的屏幕空间中做)光照透视分割-变换到裁剪空间裁剪变换到屏幕空间3.三角形生成背面剔除(或者在光照计算之前的观察空间中

18、完成)斜率/角度计算扫瞄线变换4.渲染/光栅化着色纹理雾Alpha透明测试深度缓冲抗锯齿(可选择的)显示通常你会把所有的多边形放到一些列表内,然后根据纹理对这个列表排序(这样你只需要对显卡传送一次纹理,而不是每个多边形都传送一次),等等。在过去,会把多边形按照它们到相机的距离进行排序,首先绘制那些距离相机最远的多边形,但现在由于Z缓冲的出现,这种方法就不是那么重要了。当然那些透明的多边形要除外,它们要在所有的非半透明多边形绘制之后才能够绘制,这样一来,所有在它们后面的多边形就能正确地在场景中显现出来。当然,象那样,实际上你必须得从后到前地绘制那些多边形。但时常在任何给定的FPS游戏场景中,通常

19、没有太多透明的多边形。它可能看起来像有,但实际上与那些不透明的多边形相比,其比率是相当低的。一旦应用程序将场景传递到API,API就能利用硬件加速的变换和光照处理(T&L),这在如今的3D显卡中是很平常的事情。这里不讨论涉及到的矩阵数学(参见Dave的3D管线导论),几何变换允许3D显卡按照你的尝试,根据相机在任何时间的位置和方向,在世界的正确角度和位置绘制多边形。对于每个点或顶点都有大量的计算,包括裁剪运算,决定任何给定的多边形实际上是否可见,在屏幕上完全不可见或部分可见。光照运算,计算纹理色彩明亮程度,这取决于世界的灯光从什么角度如何投射到顶点上。过去,处理器处理这些计算,但现在,当代图形

20、硬件就能为你做这些事情,这意谓着你的处理器可以去做其他的事情了。很明显这是件好事情(tm),由于不能指望市面上所有的3D显卡板上都有T&L,所以无论如何你自己将必须写所有的这些例程(再一次从游戏开发者角度来说)。你将在本文各处的不同段落看到好事情(tm)这个词汇。我认为,这些特征为使游戏看起来更好作出了非常有用的贡献。毫不令人吃惊,你也将会看见它的对立面;你猜到了,那就是坏事情(tm)。我正在尝试争取这些词汇的版权,你要使用他们就得支付一笔小小的费用哟。曲面片(高次表面)除了三角形,曲面片的使用现在正变得更普遍。因为他们能用数学表达式来描述几何(通常涉及某种曲线的几何形体),而不仅仅只是列出大

21、量的多边形以及在游戏世界中的位置,所以曲面片(高次表面的另一个名称)非常好。这样,你实际上就能够动态地根据方程式来建立(和变形)多边形网格,并决定你实际想要从曲面片上看到的多边形数量。因此,举例来说,你可以描述一个管道,然后在世界中就可以有这种管道的许多样例。在一些房间中,你已经显示了10,000个多边形,你可以说,因为我们已经显示了大量的多边形,而且任何更多的多边形将会使帧速率下降,所以这个管道应该只有100个多边形。但在另外一个房间中,视野中只有5,000个可见的多边形,你可以说,因为我们还没有达到预算可以显示的多边形数量,所以,现在这个管道能有500个多边形。非常美妙的东西-但你必须首先

22、知道所有这些,并建立网格,这不是无足轻重的。通过AGP传送同一个对象的曲面方程确实要比传送其大量顶点节省成本。SOF2就使用了这个方法的一种变体来建立它的地表系统。事实上现在的ATI显卡具有TruForm,它能带一个以三角形为基础的模型,并将该模型转换为基于高次表面的模型,使其平滑-接着再用十倍三角形数量把模型转换回基于大量三角形的模型(被称为retesselation)。然后模型送往管线做进一步的处理。实际上ATI仅仅在T&L引擎之前增加了一个阶段来处理这个过程。这里的缺点是,要控制哪些模型需要被平滑处理而哪些又不需要。你常常想要一些边缘比较尖锐,比如鼻子,但它却被不恰当的平滑过了。这仍然是

23、一种很好的技术,而且我能预见它在将来会被更多的应用。这就是第一部份-我们将会在第二部分继续介绍光照和纹理,下面的章节会更加深入。世界的灯光在变换过程中,通常是在称为观察空间的坐标空间中,我们遇到了最重要的运算之一:光照计算。它是一种这样的事情,当它工作时,你不关注它,但当它不工作时,你就非常关注它了。有很多不同的光照方法,从简单的计算多边形对于灯光的朝向,并根据灯光到多边形的方向和距离加上灯光颜色的百分比值,一直到产生边缘平滑的灯光贴图叠加基本纹理。而且一些API实际上提供预先建造的光照方法。举例来说,OpenGL提供了每多边形,每顶点,和每像素的光照计算。在顶点光照中,你要决定一个顶点被多少

24、个多边形共享,并计算出共享该顶点的所有多边形法向量的均值(称为法向量),并将该法向量赋顶点。一个给定多边形的每个顶点会有不同的法向量,所以你需要渐变或插值多边形顶点的光照颜色以便得到平滑的光照效果。你没有必要用这种光照方式查看每个单独的多边形。这种方式的优点是时常可以使用硬件转换与光照(T&L)来帮助快速完成。不足之处是它不能产生阴影。举例来说,即使灯光是在模型的右侧,左手臂应该在被身体投影的阴影中,而实际上模型的双臂却以同样的方式被照明了。这些简单的方法使用着色来达到它们的目标。当用平面光照绘制一个多边形时,你让渲染(绘制)引擎把整个多边形都着上一种指定的颜色。这叫做平面着色光照。(该方法中

25、,多边形均对应一个光强度,表面上所有点都用相同的强度值显示,渲染绘制时得到一种平面效果,多边形的边缘不能精确的显示出来)。对于顶点着色(Gouraud着色),你让渲染引擎给每个顶点赋予特定的颜色。在绘制多边形上各点投影所对应的像素时,根据它们与各顶点的距离,对这些顶点的颜色进行插值计算。(实际上Quake III模型使用的就是这种方法,效果好的令人惊奇)。还有就是Phong着色。如同Gouraud着色,通过纹理工作,但不对每个顶点颜色进行插值决定像素颜色值,它对每个顶点的法向量进行插值,会为每个顶点投影的像素做相同的工作。对于Gouraud着色,你需要知道哪些光投射在每个顶点上。对于Phong

26、着色,你对每个像素也要知道这么多。一点也不令人惊讶,Phong着色可以得到更加平滑的效果,因为每个像素都需要进行光照计算,其绘制非常耗费时间。平面光照处理方法很快速,但比较粗糙。Phong着色比Gouraud着色计算更昂贵,但效果最好,可以达到镜面高光效果(高亮)。这些都需要你在游戏开发中折衷权衡。不同的灯光接着是生成照明映射,你用第二个纹理映射(照明映射)与已有的纹理混合来产生照明效果。这样工作得很好,但这本质上是在渲染之前预先生成的一种罐装效果。如果你使用动态照明(即,灯光移动,或者没有程序的干预而打开和关闭),你得必须在每一帧重新生成照明映射,按照动态灯光的运动方式修改这些照明映射。灯光

27、映射能够快速的渲染,但对存储这些灯光纹理所需的内存消耗非常昂贵。你可以使用一些压缩技巧使它们占用较少的的内存空间,或减少其尺寸大小,甚至使它们是单色的(这样做就不会有彩色灯光了),等等。如果你确实在场景中有多个动态灯光,重新生成照明映射将以昂贵的CPU周期而告终。许多游戏通常使用某种混合照明方式。以Quake III为例,场景使用照明映射,动画模型使用顶点照明。预先处理的灯光不会对动画模型产生正确的效果-整个多边形模型得到灯光的全部光照值-而动态照明将被用来产生正确的效果。使用混合照明方式是多数的人们没有注意到的一个折衷,它通常让效果看起来正确。这就是游戏的全部做一切必要的工作让效果看起来正确

28、,但不必真的是正确的。当然,所有这些在新的Doom引擎里面都不复存在了,但要看到所有的效果,至少需要1GHZ CPU和GeForce 2显卡。是进步了,但一切都是有代价的。一旦场景经过转换和照明,我们就进行裁剪运算。不进入血淋淋的细节而,剪断运算决定哪些三角形完全在场景(被称为观察平截头体)之内或部份地在场景之内。完全在场景之内的三角形被称为细节接受,它们被处理。对于只是部分在场景之内的三角形,位于平截头体外面的部分将被裁剪掉,余下位于平截头体内部的多边形部分将需要重新闭合,以便其完全位于可见场景之内。(更多的细节请参考我们的3D流水线指导一文)。场景经过裁剪以后,流水线中的下一个阶段就是三角

29、形生成阶段(也叫做扫描线转换),场景被映射到2D屏幕坐标。到这里,就是渲染(绘制)运算了。纹理与MIP映射纹理在使3D场景看起来真实方面异常重要,它们是你应用到场景区域或对象的一些分解成多边形的小图片。多重纹理耗费大量的内存,有不同的技术来帮助管理它们的尺寸大小。纹理压缩是在保持图片信息的情况下,让纹理数据更小的一种方法。纹理压缩占用较少的游戏CD空间,更重要的是,占用较少内存和3D显卡存储空间。另外,在你第一次要求显卡显示纹理的时候,压缩的(较小的)版本经过AGP接口从PC主存送到3D显卡,会更快一些。纹理压缩是件好事情。在下面我们将会更多的讨论纹理压缩。MIP映射(多纹理映射)游戏引擎用来

30、减少纹理内存和带宽需求的另外一个技术就是MIP映射。MIP映射技术通过预先处理纹理,产生它的多个拷贝纹理,每个相继的拷贝是上一个拷贝的一半大小。为什么要这样做?要回答这个问题,你需要了解3D显卡是如何显示纹理的。最坏情况,你选择一个纹理,贴到一个多边形上,然后输出到屏幕。我们说这是一对一的关系,最初纹理映射图的一个纹素(纹理元素)对应到纹理映射对象多边形的一个像素。如果你显示的多边形被缩小一半,纹理的纹素就每间隔一个被显示。这样通常没有什么问题-但在某些情况下会导致一些视觉上的怪异现象。让我们看看砖块墙壁。假设最初的纹理是一面砖墙,有许多砖块,砖块之间的泥浆宽度只有一个像素。如果你把多边形缩小

31、一半,纹素只是每间隔一个被应用,这时候,所有的泥浆会突然消失,因为它们被缩掉了。你只会看到一些奇怪的图像。使用MIP映射,你可以在显示卡应用纹理之前,自己缩放图像,因为可以预先处理纹理,你做得更好一些,让泥浆不被缩掉。当3D显卡用纹理绘制多边形时,它检测到缩放因子,说,你知道,我要使用小一些的纹理,而不是缩小最大的纹理,这样看起来会更好一些。在这里,MIP映射为了一切,一切也为了MIP映射。多重纹理与凹凸映射单一纹理映射给整个3D真实感图形带来很大的不同,但使用多重纹理甚至可以达到一些更加令人难忘的效果。过去这一直需要多遍渲染(绘制),严重影响了像素填充率。但许多具有多流水线的3D加速卡,如A

32、TIs Radeon和nVidias GeForce 2及更高级的显卡,多重纹理可以在一遍渲染(绘制)过程中完成。产生多重纹理效果时,你先用一个纹理绘制多边形,然后再用另外一个纹理透明地绘制在多边形上面。这让你可以使纹理看上去在移动,或脉动,甚至产生阴影效果(我们在照明一节中描述过)。绘制第一个纹理映射,然后在上面绘制带透明的全黑纹理,引起一种是所有的织法黑色的但是有一个透明分层堆积过它的顶端,这就是-即时阴影。该技术被称为照明映射(有时也称为暗映射),直至新的Doom,一直是Id引擎里关卡照明的传统方法。凹凸贴图是最近涌现出来的一种古老技术。几年以前Matrox第一个在流行的3D游戏中发起使

33、用各种不同形式的凹凸贴图。就是生成纹理来表现灯光在表面的投射,表现表面的凹凸或表面的裂缝。凹凸贴图并不随着灯光一起移动-它被设计用来表现一个表面上的细小瑕疵,而不是大的凹凸。比如说,在飞行模拟器中,你可以使用凹凸贴图来产生像是随机的地表细节,而不是重复地使用相同的纹理,看上去一点趣味也没有。凹凸贴图产生相当明显的表面细节,尽管是很高明的戏法,但严格意义上讲,凹凸贴图并不随着你的观察角度而变化。比较新的ATI和nVidia显卡片能执行每像素运算,这种缺省观察角度的不足就真的不再是有力而快速的法则了。无论是哪一种方法,到目前为止,没有游戏开发者太多的使用;更多的游戏能够且应该使用凹凸贴图。高速缓存

34、抖动=糟糕的事物纹理高速缓存的管理游戏引擎的速度至关重要。和任何高速缓存一样,缓存命中很好,而不命中将很糟糕。如果遇到纹理在图形显示卡内存被频繁地换入换出的情况,这就是纹理高速缓存抖动。发生这种情况时,通常API将会废弃每个纹理,结果是所有的纹理在下一帧将被重新加载,这非常耗时和浪费。对游戏玩家来说,当API重新加载纹理高速缓存时,会导致帧速率迟钝。在纹理高速缓存管理中,有各种不同的技术将纹理高速缓存抖动减到最少这是确保任何3D游戏引擎速度的一个决定性因素。纹理管理是件好事情这意味着只要求显卡使用纹理一次,而不是重复使用。这听起来有点自相矛盾,但效果是它意谓着对显卡说,看,所有这些多边形全部使

35、用这一个纹理,我们能够仅仅加载这个纹理一次而不是许多次吗?这阻止API(或图形驱动软件)上传多次向显卡加载纹理。象OpenGL这样的API实际上通常处理纹理高速缓存管理,意谓着,根据一些规则,比如纹理存取的频率,API决定哪些纹理储存在显卡上,哪些纹理存储在主存。真正的问题来了:a)你时常无法知道API正在使用的准确规则。b)你时常要求在一帧中绘制更多的纹理,以致超出了显卡内存空间所能容纳的纹理。另外一种纹理高速缓存管理技术是我们早先讨论的纹理压缩。很象声音波形文件被压缩成MP3文件,尽管无法达到那样的压缩比率,但纹理可以被压缩。从声音波形文件到MP3的压缩可以达到11:1的压缩比率,而绝大多

36、数硬件支持的纹理压缩运算法则只有4:1的压缩比率,尽管如此,这样能产生很大的差别。除此之外,在渲染(绘制)过程中,只有在需要时,硬件才动态地对纹理进行解压缩。这一点非常棒,我们仅仅擦除即将可能用到的表面。如上所述,另外一种技术确保渲染器要求显卡对每个纹理只绘制一次。确定你想要渲染(绘制)的使用相同纹理的所有多边形同时送到显卡,而不是一个模型在这里,另一个模型在那里,然后又回到最初的纹理论。仅仅绘制一次,你也就通过AGP接口传送一次。Quake III在其阴影系统就是这么做的。处理多边形时,把它们加入到一个内部的阴影列表,一旦所有的多边形处理完毕,渲染器遍历纹理列表,就将纹理及所有使用这些纹理的

37、多边形同时传送出去。上述过程在使用显卡的硬件T&L(如果支持的话)时,并不怎么有效。你面临的结局是,满屏幕都是使用相同纹理的大量的多边形小群组,所有多边形都使用不同的变换矩阵。这意谓着更多的时间花在建立显卡的硬件T&L引擎,更多的时间被浪费了。无论如何,因为他们有助于对整个模型使用统一的纹理,所以它对实际屏幕上的模型可以有效地工作。但是因为许多多边形倾向使用相同的墙壁纹理,所以对于世界场景的渲染,它常常就是地狱。通常它没有这么严重,因为大体而言,世界的纹理不会有那么大,这样一来API的纹理缓存系统将会替你处理这些,并把纹理保留在显卡以备再次使用。在游戏机上,通常没有纹理高速缓存系统(除非你写一

38、个)。在PS2上面,你最好是远离一次纹理的方法。在Xbox上面,这是不重要的,因为它本身没有图形内存(它是UMA体系结构),且所有的纹理无论如何始终保留在主存之中。事实上,在今天的现代PC FPS游戏中,试图通过AGP接口传送大量纹理是第二个最通常的瓶颈。最大的瓶颈是实际几何处理,它要使东西出现在它应该出现的地方。在如今的3D FPS游戏中,最耗费时间的工作,显然是那些计算模型中每个顶点正确的世界位置的数学运算。如果你不把场景的纹理保持在预算之内,仅居其次的就是通过AGP接口传送大量的纹理了。然而,你确实有能力影响这些。通过降低顶层的MIP级别(还记得系统在哪里不断地为你细分纹理吗?),你就能

39、够把系统正在尝试送到显卡的纹理大小减少一半。你的视觉质量会有所下降-尤其是在引人注目的电影片断中-但是你的帧速率上升了。这种方式对网络游戏尤其有帮助。实际上,Soldier of Fortune II和Jedi Knight II:Outcast这两款游戏在设计时针对的显卡还不是市场上的大众主流显卡。为了以最大大小观看他们的纹理,你的3D显卡至少需要有128MB的内存。这两种产品在思想上都是给未来设计的。第3部份:内存使用,特效和API关于内存使用的思考让我们想一想,在今天实际上是如何使用3D显卡内存的以及在将来又会如何使用。如今绝大多数3D显卡处理32位像素颜色,8位红色,8位蓝色,8位绿色

40、,和8位透明度。这些组合的红,蓝和绿256个色度,可以组成16。7百万种颜色-那是你我可以在一个监视器上看见的所有颜色。那么,游戏设计大师John Carmack为什么要求64位颜色分辨率呢?如果我们看不出区别,又有什么意义呢?意义是:比如说,有十几个灯光照射模型上的点,颜色颜色各不相同。我们取模型的最初颜色,然后计算一个灯光的照射,模型颜色值将改变。然后我们计算另外的一个灯光,模型颜色值进一步改变。这里的问题是,因为颜色值只有8位,在计算了4个灯光之后,8位的颜色值将不足以给我们最后的颜色较好的分辨率和表现。分辨率的不足是由量化误差导致的,本质原因是由于位数不足引起的舍入误差。你能很快地用尽

41、位数,而且同样地,所有的颜色被清掉。每颜色16或32位,你有一个更高分辨率,因此你能够反复着色以适当地表现最后的颜色。这样的颜色深度很快就能消耗大量的存储空间。我们也应提到整个显卡内存与纹理内存。这里所要说的是,每个3D显卡实际只有有限的内存,而这些内存要存储前端和后端缓冲区,Z缓冲区,还有所有的令人惊奇的纹理。最初的Voodoo1显卡只有2MB显存,后来Riva TNT提高到16MB显存。然后GeForce和ATI Rage有32MB显存,现在一些GeForce 2到4的显卡和Radeons带有64MB到128MB的显存。这为什么重要?好吧,让我们看一些数字比如你想让你的游戏看起来最好,所以

42、你想要让它以32位屏幕,1280x1024分辨率和32位Z-缓冲跑起来。好,屏幕上每个像素4个字节,外加每个像素4字节的Z-缓冲,因为都是每像素32位。我们有1280x1024个像素也就是1,310,720个像素。基于前端缓冲区和Z-缓冲区的字节数,这个数字乘以8,是10,485,760字节。包括一个后端缓冲区,这样是1280x1024x12,也就是15,728,640字节,或15MB。在一个16MB显存的显卡上,就只给我们剩下1MB来存储所有的纹理。现在如果最初的纹理是真32位或4字节宽,那么我们每帧能在显卡上存储1MB/4字节每像素=262,144个像素。这大约是4个256x256的纹理页

43、面。很清楚,上述例子表明,旧的16MB显卡没有现代游戏表现其绚丽画面所需要的足够内存。很明显,在它绘制画面的时候,我们每帧都必须重新把纹理装载到显卡。实际上,设计AGP总线的目的就是完成这个任务,不过,AGP还是要比3D掀卡的帧缓冲区慢,所以你会受到性能上的一些损失。很明显,如果纹理由32位降低到16位,你就能够通过AGP以较低的分辨率传送两倍数量的纹理。如果你的游戏以每个像素比较低的色彩分辨率跑,那么就可以有更多的显示内存用来保存常用的纹理(称为高速缓存纹理)。但实际上你永远不可能预知使用者将如何设置他们的系统。如果他们有一个在高分辨率和颜色深度跑的显卡,那么他们将会更可能那样设定他们的显卡

44、。雾我们现在开始讲雾,它是某种视觉上的效果。如今绝大多数的引擎都能处理雾,因为雾非常方便地让远处的世界淡出视野,所以当模型和场景地理越过观察体后平面进入视觉范围内时,你就不会看见它们突然从远处跳出来了。也有一种称为体雾的技术。这种雾不是随物体离照相机的距离而定,它实际上是一个你能看见的真实对象,并且可以穿越它,从另外一侧出去-当你在穿越对象的时候,视觉上雾的可见程度随着变化。想象一下穿过云团-这是体雾的一个完美例子。体雾的一些好的实现例子是Quake III一些关卡中的红色雾,或新的Rogue Squadron II之Lucas Arts的GameCube版本。其中有一些是我曾经见过的最好的云

45、-大约与你能看见的一样真实。在我们讨论雾化的时候,可能是简短介绍一下Alpha测试和纹理Alpha混合的好时机。当渲染器往屏幕上画一个特定像素时,假定它已经通过Z-缓冲测试(在下面定义),我们可能最后做一些Alpha测试。我们可能发现为了显示像素后面的某些东西,像素需要透明绘制。这意味着我们必须取得像素的已有值,和我们新的像素值进行混和,并把混合结果的像素值放回原处。这称为读-修改-写操作,远比正常的像素写操作费时。你可以用不同类型的混合,这些不同的效果被称为混合模式。直接Alpha混合只是把背景像素的一些百分比值加到新像素的相反百分比值上面。还有加法混合,将旧像素的一些百分比,和特定数量(而

46、不是百分比)的新像素相加。这样效果会更加鲜明。(Kyles Lightsaber在Jedi Knight II中的效果)。每当厂商提供新的显卡时,我们可以得到硬件支持的更新更复杂的混合模式,从而制作出更多更眩目的效果。GF3+4和最近的Radeon显卡提供的像素操作,已经到了极限。模板阴影与深度测试用模板产生阴影效果,事情就变得复杂而昂贵了。这里不讨论太多细节(可以写成一篇单独的文章了),其思想是,从光源视角绘制模型视图,然后用这个把多边形纹理形状产生或投射到受影响的物体表面。实际上你是在视野中投射将会落在其他多边形上面的光体。最后你得到看似真实的光照,甚至带有视角在里面。因为要动态创建纹理,

47、并对同一场景进行多遍绘制,所以这很昂贵。你能用众多不同方法产生阴影,情形时常是这样一来,渲染质量与产生效果所需要的渲染工作成比例。有所谓的硬阴影或软阴影之分,而后者较好,因为它们更加准确地模仿阴影通常在真实世界的行为。通常有一些被游戏开发者偏爱的足够好的方法。如要更多的了解阴影,请参考Dave Salvator的3D流水线一文。深度测试现在我们开始讨论深度测试,深度测试丢弃隐藏的像素,过度绘制开始起作用。过度绘制非常简单在一帧中,你数次绘制一个像素位置。它以3D场景中Z(深度)方向上存在的元素数量为基础,也被称为深度复杂度。如果你常常太多的过度绘制,-举例来说,符咒的眩目视觉特效,就象Here

48、tic II,能让你的帧速率变得很糟糕。当屏幕上的一些人们彼此施放符咒时,Heretic II设计的一些最初效果造成的情形是,他们在一帧中对屏幕上每个相同的像素画了40次!不用说,这必须调整,尤其是软件渲染器,除了将游戏降低到象是滑雪表演外,它根本不能处理这样的负荷。深度测试是一种用来决定在相同的像素位置上哪些对象在其它对象前面的技术,这样我们就能够避免绘制那些隐藏的对象。看着场景并想想你所看不见的。换句话说,是什么在其他场景对象前面,或者隐藏了其他场景对象?是深度测试作出的这个决定。我将进一步解释深度深度如何帮助提高帧速率。想像一个很琐细的场景,大量的多边形(或像素)位于彼此的后面,在渲染器

49、获得他们之间没有一个快速的方法丢弃他们。对非Alpha混合的多边形分类排序(在Z-方向上),首先渲染离你最近的那些多边形,优先使用距离最近的像素填充屏幕。所以当你要渲染它们后面的像素(由Z或者深度测试决定)时,这些像素很快被丢弃,从而避免了混合步骤并节省了时间。如果你从后到前绘制,所有隐藏的对象将被完全绘制,然后又被其他对象完全重写覆盖。场景越复杂,这种情况就越糟糕,所以深度测试是个好东西。抗锯齿让我们快速的看一下抗锯齿。当渲染单个多边形时,3D显卡仔细检查已经渲染的,并对新的多边形的边缘进行柔化,这样你就不会得到明显可见的锯齿形的像素边缘。两种技术方法之一通常被用来处理。第一种方法是单个多边形层次,需要你从视野后面到前面渲染多边形,这样每个多边形都能和它后面的进行适当的混

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1