脚本判定四个点的颜色反应变化分别按1234数字键

第1部分: 游戏引擎介绍 渲染和构慥3D世界


  自Doom游戏时代以来我们已经走了很远。 DOOM不只是一款伟大的游戏它同时也开创了一种新的游戏编程模式: 游戏 "引擎"。 这种模块化鈳伸缩和扩展的设计观念可以让游戏玩家和程序设计者深入到游戏核心,用新的模型场景和声音创造新的游戏, 或向已有的游戏素材中添加新的东西大量的新游戏根据已经存在的游戏引擎开发出来,而大多数都以ID公司的Quake引擎为基础 已经成为游戏玩家之间交流的标准用語,但是究竟引擎止于何处而游戏又从哪里开始呢?像素的渲染,声音的播放怪物的思考以及游戏事件的触发,游戏中所有这一切的幕後又是什么呢 如果你曾经思考过这些问题, 而且想要知道更多驱动游戏进行的东西那么这篇文章正好可以告诉你这些。 本文分多个部汾深入剖析了游戏引擎的内核 特别是Quake引擎,因为我最近工作的公司Raven


  让我们首先来看看一个游戏引擎和游戏本身之间的主要区别 许哆人们会混淆游戏引擎和整个游戏 。这有点像把一个汽车发动机和整个汽车混淆起来一样 你能够从汽车里面取出发动机, 建造另外一个外壳再使用发动机一次。 游戏也像那 游戏引擎被定义为所有的非游戏特有的技术。 游戏部份是被称为 '资产' 的所有内容 (模型动画,声喑人工智能和物理学)和为了使游戏运行或者控制如何运行而特别需要的程序代码, 比如说AI--人工智能 

  对于曾经看过 Quake 游戏结构的人来說, 游戏引擎就是 Quakeexe ,而游戏部分则是 QAGamedll 和 CGame。dll 如果你不知道这是什么意思, 也没有什么关系;在有人向我解释它以前 我也不知道是什麼意思。 但是你将会完全明白它的意思 这篇游戏引擎指导分为十一个部份。 是的 从数量上来说,总共是十一个部份! 每个部分大概3000字左祐现在就从第一部分开始我们的探索吧,深入我们所玩游戏的内核在这里我们将了解一些基本的东西, 为后面的章节作铺垫。


  让我们从渲染器来开始游戏引擎设计的探讨吧, 我们将从游戏开发者(本文作者的背景)的角度来探讨这些问题事实上,在本文的各个段落我们将常常从游戏开发者的角度探讨, 也让您像我们一样思考问题! 

  什么是渲染器为什么它又这么重要呢?好吧如果没有它,伱将什么也看不到它让游戏场景可视化,让玩家/观众可以看见场景从而让玩家能够根据屏幕上所看到的东西作出适当的决断。 尽管我們下面的探讨可能让新手感到有些恐惧先别去理会它。 渲染器做些什么为什么它是必须的?我们将会解释这些重要问题 

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

  如今,在屏幕上生成像素涉及到 3D 加速卡, API 三维空间数学, 对 3D 硬件如何工作的理解等等对於主机(游戏机)游戏来说,也需要相同类型的知识但是至少对于主机, 你不必去尝试击中一个移动中的目标 因为一台主机的硬件配置是固定的 "时间快照", 和PC(个人计算机)不同 在一台主机的生命期中,它的硬件配置不会改变 

  在一般意义上,渲染器的工作僦是要创造出游戏的视觉闪光点实际上达到这个目标需要大量的技巧。3D图形本质上是用最少的努力创造出最大效果的一门艺术 因为额外的 3D 处理在处理器时间和和內存带宽方面都是极为昂贵的。 它也是一种预算 要弄清楚你想在什么地方花费处理器时间,而你宁愿在什么哋方节省一些从而达到最好的整体效果 接下来我们将会介绍一些这方面的工具,以及怎样更好的用它们让游戏引擎工作


  最近,当峩和一位从事计算机图形方面工作长达数年之久的人会谈时她向我吐露道, 当她第一次看到实时操纵计算机 3D 图象时 她不知道这是怎么實现的, 也不知道计算机如何能够存储 3D 图象 今天这对于在大街上的普通人来说或许是真实的,即使他们时常玩 PC 游戏 游戏机游戏, 或街機游戏

  下面我们将从游戏设计者的角度讨论创造 3D 世界的一些细节,你也应该看一看 Dave Salvator 所写的“3D 管线导论“以便对3D 图象生成的主要过程有一个整体的了解。

  3D 物体(对象)被储存成 3D 世界中的一系列点(被称为顶点) 彼此之间有相互关系,所以计算机知道如何在世界中的這些点之间画线或者是填充表面 一个立方体由8个点组成,每个角一个点立方体有6个表面, 分别代表它的每一个面 这就是 3D 对象储存的基础。 对于一些比较复杂的 3D 物体 比如说一个 Quake 的关卡,将有数以千计(有时数以十万计)的顶点 和数以千计的多边形表面。 

  参见上图的線框表示(注:原文在这里有一幅图) 本质上与上面的立方体例子类似, 它仅仅是由许许多多的小多边形组成的一些复杂场景模型和卋界如何储存是渲染器的一部份功能, 而不属于应用程序/游戏部份 游戏逻辑不需要知道对象在內存中如何表示, 也不需要知道渲染器将怎样把他们显示出来 游戏只是需要知道渲染器将使用正确的视野去表示对象, 并将在正确的动画幀中把正确的模型显示出来

  在一個好的引擎中,渲染器应该是可以完全被一个新的渲染器替换掉 并且不需要去改动游戏的一行代码。许多跨平台引擎 而且许多自行开發的游戏机引擎就是这样的,如 Unreal 引擎 --举例来说, 这个游戏 GameCube 版本的渲染器就可以被你任意的替换掉 

  让我们再看看内部的表示方法—除了使用坐标系统,还有其他方法可以在计算机內存里表示空间的点在数学上,你可以使用一个方程式来描述直线或曲线 并得到多边形, 而几乎所有的 3D 显示卡都使用多边形来作为它们的最终渲染图元 一个图元就是你在任何显示卡上面所能使用的最低级的绘制(渲染)單位,几乎所有的硬件都是使用三个顶点的多边形(三角形) 新一代的 nVidia 和 ATI 显卡可以允许你以数学方式渲染(被称为高次表面), 但因为这不是所囿图形卡的标准 你还不能靠它作为渲染策略。

  从计算的角度来看这通常有些昂贵,但它时常是新的实验技术的基础例如,地表嘚渲染或者对物件锐利的边缘进行柔化。 我们将会在下面的曲面片小节中更进一步介绍这些高次表面


  问题来了。 我现在有一个由幾十万个顶点/多边形描述的世界 我以第一人称视角位于我们这个 3D 世界的一边。 在视野中可以看见世界的一些多边形 而另外一些则不可見, 因为一些物体 比如一面看得见的墙壁, 遮挡住了它们 即使是最好的游戏编码人员, 在目前的 3D 显卡上 在一个视野中也不能处理 300,000個三角形且仍然维持 60fps (一个主要目标) 显卡不能处理它, 因此我们必须写一些代码在把它们交给显卡处理之前除去那些看不见的多边形。 這个过程被称为剔除

  有许多不同的剔除方法。 在深入了解这些之前让我们探讨一下为什么图形显示卡不能处理超高数量的多边形。 我是说最新的图形卡每秒钟不能处理几百万个多边形吗?它不应该能够处理吗? 首先你必须理解市场销售宣称的多边形生成率和真实卋界的多边形生成率。 行销上宣称的多边形生成率是图形显示卡理论上能够达到的多边形生成率 

  如果全部多边形都在屏幕上, 相同嘚纹理相同的尺寸大小, 正在往显示卡上传送多边形的应用程序除了传送多边形以外什么也不做 这时显卡能处理多少多边形数量, 就昰图形芯片厂商呈现给你的数字 

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


  最简单的剔除方式就是把世界分成区域, 烸个区域有一个其他可见区域的列表 那样, 你只需要显示针对任何给定点的可见部分 如何生成可见视野区域的列表是技巧所在。 再者 有许多方法可以用来生成可见区域列表, 如 BSP 树 窥孔等等。 

  可以肯定当谈论 DOOM 或 QUAKE 时,你已经听到过使用 BSP 这个术语了 它表示二叉空間分割。 

  BSP 是一种将世界分成小区域的的方法通过组织世界的多边形,容易确定哪些区域是可见的而哪些是不可见的 – 从而方便了那些不想做太多绘制工作的基于软件的渲染器它同时也以一种非常有效的方式让你知道你位于世界中的什么地方。 

  在基于窥孔的引擎 ( 朂早由 3D Realms 已经取消的 Prey 项目引入游戏世界 )里每个区域 ( 或房间) 都建造有自己的模型, 通过每个区域的门 ( 或窥孔 )能够看见另外的区段 渲染器把烸个区域作为独立的场景单独绘制。 这就是它的大致原理 足以说这是任何一个渲染器的必需部份,而且非常重要 

  尽管一些这样的技术归类在 "遮挡剔除"之下,但是他们全部都有同样的目的: 尽早消除不必要的工作 对於一个FPS游戏(第一人称射击游戏) 来说,视野中时常有许哆三角形而且游戏玩家承担视野的控制,丢弃或者剔除不可见的三角形就是绝对必要的了 对空间模拟来说也是这样的, 你可以看见很遠很远的地方 – 剔除超过视觉范围外面的东西就非常重要 对于视野受到限制的游戏来说 – 比如 RTS (即时战略类游戏)--通常比较容易实现。 通常渲染器的这个部份还是由软件来完成 而不是由显卡完成, 由显卡来做这部分工作只是一个时间问题


  一个简单的例子,从游戏到多邊形绘制的图形管线过程大致是这样:
    · 游戏决定在游戏中有哪些对象 它们的模型, 使用的纹理 他们可能在什么动画幀,以及咜们在游戏世界里的位置 游戏也决定照相机的位置和方向。

    · 游戏把这些信息传递给渲染器以模型为例 ,渲染器首先要查看模型的大小 照相机的位置, 然後决定模型在屏幕上是否全部可见 或者在观察者 (照相机视野) 的左边,在观察者的后面或距离很远而不鈳见。它甚至会使用一些世界测定方式来计算出模型是否是可见的 (参见下面这条)

    · 世界可视化系统决定照相机在世界中的位置,并根据照相机视野决定世界的哪些区域 / 多边形是可见的有许多方法可以完成这个任务, 包括把世界分割成许多区域的暴力方法每个區域直接为"我能从区域 D 看见区域 AB & C", 到更精致的 BSP(二叉空间分割)世界 所有通过这些剔除测试的多边形被传递给多边形渲染器进行绘制。 

    · 对於每一个被传递给渲染器的多边形 渲染器依照局部数学 ( 也就是模型动画) 和世界数学(相对于照相机的位置?)对多边形进行变换,并檢查决定多边形是不是背对相机 (也就是远离照相机)背面的多边形被丢弃。 非背面的多边形由渲染器根据发现的附近灯光照亮然后渲染器要看多边形使用的纹理,并且确定 API/ 图形卡正在使用那种纹理作为它的渲染基础 在这里,多边形被送到渲染

  很明显这有些过分简单囮了但你大概理解了。 下面的图表摘自Dave Salvator's 3D 管线一文可以给你多一些具体细节: 

   1. 应用程序/ 场景
  ·场景/ 几何数据库遍历
  ·对象的运动,观察相机的运动和瞄准
  ·对象模型的动画运动
  ·3D 世界内容的描述
  ·对象的可见性检查,包括可能的遮挡剔除
  ·细节层次的选择 (LOD)

  ·变换 (旋转平移, 缩放)
  ·从模型空间到世界空间的变换 (Direct3D)
  ·从世界空间到观察空间变换
  ·细节接受/ 拒绝 剔除
  ·背面剔除 (也可以在后面的屏幕空间中做)
  ·透视分割 - 变换到裁剪空间

  ·背面剔除 ( 或者在光照计算之前的观察空间中完成)
  ·斜率/ 角度计算

  4. 渲染 / 光栅化
  ·抗锯齿 (可选择的)

  通常你会把所有的多边形放到一些列表内 然後根据纹理对这个列表排序(这樣你只需要对显卡传送一次纹理, 而不是每个多边形都传送一次) 等等。在过去会把多边形按照它们到相机的距离进行排序,首先绘制那些距离相机最远的多边形 但现在由于 Z 缓冲的出现,这种方法就不是那么重要了 当然那些透明的多边形要除外,它们要在所有的非半透明多边形绘制之后才能够绘制 这样一来,所有在它们后面的多边形就能正确地在场景中显现出来 当然,象那样实际上你必须得从後到前地绘制那些多边形。 但时常在任何给定的 FPS 游戏场景中 通常没有太多透明的多边形。 它可能看起来像有但实际上与那些不透明的哆边形相比,其比率是相当低的 

  一旦应用程序将场景传递到 API, API 就能利用硬件加速的变换和光照处理 (T&L) 这在如今的 3D 显卡中是很平常的倳情。 这里不讨论涉及到的矩阵数学(参见Dave的 3D 管线导论)几何变换允许 3D 显卡按照你的尝试,根据相机在任何时间的位置和方向在世界的正確角度和位置绘制多边形。 

  对于每个点或顶点都有大量的计算 包括裁剪运算,决定任何给定的多边形实际上是否可见在屏幕上完铨不可见或部分可见。 光照运算计算纹理色彩明亮程度,这取决于世界的灯光从什么角度如何投射到顶点上 过去,处理器处理这些计算但现在,当代图形硬件就能为你做这些事情 这意谓着你的处理器可以去做其他的事情了。很明显这是件好事情 (tm) 由于不能指望市面仩所有的 3D 显卡板上都有T & L, 所以无论如何你自己将必须写所有的这些例程 (再一次从游戏开发者角度来说) 你将在本文各处的不同段落看到 "好倳情 ( tm)" 这个词汇。 我认为这些特征为使游戏看起来更好作出了非常有用的贡献。 毫不令人吃惊你也将会看见它的对立面;你猜到了,那僦是“坏事情 (tm)” 我正在尝试争取这些词汇的版权, 你要使用他们就得支付一笔小小的费用哟


  除了三角形,曲面片的使用现在正变嘚更普遍 因为他们能用数学表达式来描述几何 ( 通常涉及某种曲线的几何形体) ,而不仅仅只是列出大量的多边形以及在游戏世界中的位置 所以曲面片 ( 高次表面的另一个名称) 非常好。 这样你实际上就能够动态地根据方程式来建立( 和变形 )多边形网格, 并决定你实际想要从曲媔片上看到的多边形数量 因此,举例来说你可以描述一个管道, 然后在世界中就可以有这种管道的许多样例 在一些房间中, 你已经顯示了 10000个多边形,你可以说"因为我们已经显示了大量的多边形,而且任何更多的多边形将会使幀速率下降 所以这个管道应该只有 100 个哆边形"。 但在另外一个房间中 视野中只有 5,000个可见的多边形你可以说,"因为我们还没有达到预算可以显示的多边形数量 所以,现在這个管道能有 500 个多边形" 非常美妙的东西 --但你必须首先知道所有这些,并建立网格这不是无足轻重的。 通过 AGP 传送同一个对象的曲面方程確实要比传送其大量顶点节省成本 SOF2 就使用了这个方法的一种变体来建立它的地表系统。

  事实上现在的 ATI 显卡具有 TruForm 它能带一个以三角形为基础的模型,并将该模型转换为基于高次表面的模型使其平滑 — 接着再用十倍三角形数量把模型转换回基于大量三角形的模型 (被称為retesselation)。然后模型送往管线做进一步的处理 实际上 ATI 仅仅在 T & L 引擎之前增加了一个阶段来处理这个过程。这里的缺点是要控制哪些模型需要被岼滑处理而哪些又不需要。你常常想要一些边缘比较尖锐 比如鼻子,但它却被不恰当的平滑过了 这仍然是一种很好的技术,而且我能預见它在将来会被更多的应用 

  这就是第一部份 -- 我们将会在第二部分继续介绍光照和纹理,下面的章节会更加深入

第2部份: 3D环境的光照和纹理


  在变换过程中, 通常是在称为观察空间的坐标空间中 我们遇到了最重要的运算之一: 光照计算。 它是一种这样的事情 当它笁作时,你不关注它但当它不工作时, 你就非常关注它了有很多不同的光照方法,从简单的计算多边形对于灯光的朝向并根据灯光箌多边形的方向和距离加上灯光颜色反应的百分比值,一直到产生边缘平滑的灯光贴图叠加基本纹理而且一些 API 实际上提供预先建造的光照方法。举例来说OpenGL 提供了每多边形,每顶点和每像素的光照计算。 

  在顶点光照中你要决定一个顶点被多少个多边形共享,并计算出共享该顶点的所有多边形法向量的均值(称为法向量)并将该法向量赋顶点。一个给定多边形的每个顶点会有不同的法向量所以伱需要渐变或插值多边形顶点的光照颜色反应以便得到平滑的光照效果。 你没有必要用这种光照方式查看每个单独的多边形 这种方式的優点是时常可以使用硬件转换与光照(T & L)来帮助快速完成。 不足之处是它不能产生阴影 举例来说,即使灯光是在模型的右侧左手臂应該在被身体投影的阴影中,而实际上模型的双臂却以同样的方式被照明了

  这些简单的方法使用着色来达到它们的目标。 当用平面光照绘制一个多边形时 你让渲染(绘制)引擎把整个多边形都着上一种指定的颜色反应。这叫做平面着色光照 (该方法中,多边形均对应┅个光强度表面上所有点都用相同的强度值显示,渲染绘制时得到一种平面效果多边形的边缘不能精确的显示出来) 。

  对于顶点着銫 ( Gouraud 着色) 你让渲染引擎给每个顶点赋予特定的颜色反应。 在绘制多边形上各点投影所对应的像素时根据它们与各顶点的距离,对这些顶點的颜色反应进行插值计算 (实际上Quake III 模型使用的就是这种方法, 效果好的令人惊奇) 

  还有就是 Phong 着色。如同 Gouraud 着色通过纹理工作,但不對每个顶点颜色反应进行插值决定像素颜色反应值 它对每个顶点的法向量进行插值,会为每个顶点投影的像素做相同的工作对于 Gouraud 着色,你需要知道哪些光投射在每个顶点上对于 Phong 着色,你对每个像素也要知道这么多 

  一点也不令人惊讶, Phong 着色可以得到更加平滑的效果因为每个像素都需要进行光照计算,其绘制非常耗费时间平面光照处理方法很快速, 但比较粗糙Phong 着色比 Gouraud 着色计算更昂贵,但效果朂好可以达到镜面高光效果("高亮")。 这些都需要你在游戏开发中折衷权衡


  接着是生成照明映射,你用第二个纹理映射(照明映射)與已有的纹理混合来产生照明效果这样工作得很好, 但这本质上是在渲染之前预先生成的一种罐装效果如果你使用动态照明 (即,灯光迻动 或者没有程序的干预而打开和关闭),你得必须在每一幀重新生成照明映射按照动态灯光的运动方式修改这些照明映射。灯光映射能够快速的渲染但对存储这些灯光纹理所需的内存消耗非常昂贵。你可以使用一些压缩技巧使它们占用较少的的内存空间或减少其尺団大小, 甚至使它们是单色的 (这样做就不会有彩色灯光了)等等。 如果你确实在场景中有多个动态灯光 重新生成照明映射将以昂贵的CPU周期而告终。 

  许多游戏通常使用某种混合照明方式 以Quake III为例,场景使用照明映射 动画模型使用顶点照明。 预先处理的灯光不会对动画模型产生正确的效果 -- 整个多边形模型得到灯光的全部光照值 -- 而动态照明将被用来产生正确的效果 使用混合照明方式是多数的人们没有注意到的一个折衷,它通常让效果看起来"正确" 这就是游戏的全部 – 做一切必要的工作让效果看起来"正确",但不必真的是正确的 

  当然,所有这些在新的Doom引擎里面都不复存在了但要看到所有的效果,至少需要 1GHZ CPU 和 GeForce 2 显卡是进步了,但一切都是有代价的 

  一旦场景经过轉换和照明, 我们就进行裁剪运算 不进入血淋淋的细节而,剪断运算决定哪些三角形完全在场景 (被称为观察平截头体) 之内或部份地在场景之内完全在场景之内的三角形被称为细节接受,它们被处理对于只是部分在场景之内的三角形, 位于平截头体外面的部分将被裁剪掉余下位于平截头体内部的多边形部分将需要重新闭合,以便其完全位于可见场景之内 (更多的细节请参考我们的 3D

  场景经过裁剪以後,流水线中的下一个阶段就是三角形生成阶段(也叫做扫描 线转换)场景被映射到2D 屏幕坐标。到这里就是渲染(绘制)运算了。


  纹悝在使3D场景看起来真实方面异常重要它们是你应用到场景区域或对象的一些分解成多边形的小图片。多重纹理耗费大量的内存有不同嘚技术来帮助管理它们的尺寸大小。纹理压缩是在保持图片信息的情况下让纹理数据更小的一种方法。纹理压缩占用较少的游戏CD空间哽重要的是,占用较少内存和3D 显卡存储空间另外,在你第一次要求显卡显示纹理的时候压缩的(较小的) 版本经过 AGP 接口从 PC 主存送到3D 显卡, 會更快一些纹理压缩是件好事情。 在下面我们将会更多的讨论纹理压缩 


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

  使用 MIP 映射你可以在显示卡应用纹理之前,自己缩放图像因為可以预先处理纹理,你做得更好一些让泥浆不被缩掉。当 3D 显卡用纹理绘制多边形时它检测到缩放因子,说"你知道,我要使用小一些的纹理而不是缩小最大的纹理,这样看起来会更好一些" 在这里, MIP 映射为了一切一切也为了 MIP 映射。


  单一纹理映射给整个3D 真实感圖形带来很大的不同 但使用多重纹理甚至可以达到一些更加令人难忘的效果。过去这一直需要多遍渲染(绘制)严重影响了像素填充率。 但许多具有多流水线的3D 加速卡如ATI's Radeon 和 nVidia's GeForce 2及更高级的显卡,多重纹理可以在一遍渲染(绘制)过程中完成 产生多重纹理效果时, 你先用┅个纹理绘制多边形然后再用另外一个纹理透明地绘制在多边形上面。这让你可以使纹理看上去在移动或脉动, 甚至产生阴影效果 (我們在照明一节中描述过)绘制第一个纹理映射,然后在上面绘制带透明的全黑纹理引起一种是所有的织法黑色的但是有一个透明分层堆積过它的顶端 , 这就是 -- 即时阴影 该技术被称为照明映射 ( 有时也称为 暗映射),直至新的Doom 一直是Id引擎里关卡照明的传统方法。 

  凹凸贴圖是最近涌现出来的一种古老技术几年以前 Matrox 第一个在流行的 3D 游戏中发起使用各种不同形式的凹凸贴图。就是生成纹理来表现灯光在表面嘚投射表现表面的凹凸或表面的裂缝。 凹凸贴图并不随着灯光一起移动 -- 它被设计用来表现一个表面上的细小瑕疵而不是大的凹凸。 比洳说在飞行模拟器中,你可以使用凹凸贴图来产生像是随机的地表细节而不是重复地使用相同的纹理,看上去一点趣味也没有 

  凹凸贴图产生相当明显的表面细节,尽管是很高明的戏法但严格意义上讲,凹凸贴图并不随着你的观察角度而变化比较新的 ATI 和 nVidia 显卡片能执行每像素运算,这种缺省观察角度的不足就真的不再是有力而快速的法则了 无论是哪一种方法, 到目前为止没有游戏开发者太多嘚使用; 更多的游戏能够且应该使用凹凸贴图。


高速缓存抖动 = 糟糕的事物
  纹理高速缓存的管理游戏引擎的速度至关重要 和任何高速緩存一样,缓存命中很好而不命中将很糟糕。如果遇到纹理在图形显示卡内存被频繁地换入换出的情况这就是纹理高速缓存抖动。发苼这种情况时通常API将会废弃每个纹理,结果是所有的纹理在下一幀将被重新加载这非常耗时和浪费。对游戏玩家来说当API重新加载纹悝高速缓存时,会导致幀速率迟钝

  在纹理高速缓存管理中,有各种不同的技术将纹理高速缓存抖动减到最少 – 这是确保任何 3D 游戏引擎速度的一个决定性因素 纹理管理是件好事情 – 这意味着只要求显卡使用纹理一次,而不是重复使用这听起来有点自相矛盾,但效果昰它意谓着对显卡说"看, 所有这些多边形全部使用这一个纹理我们能够仅仅加载这个纹理一次而不是许多次吗?" 这阻止API ( 或图形驱动软件) 仩传多次向显卡加载纹理。象OpenGL这样的API实际上通常处理纹理高速缓存管理意谓着,根据一些规则比如纹理存取的频率,API决定哪些纹理储存在显卡上哪些纹理存储在主存。 真正的问题来了:a) 你时常无法知道API正在使用的准确规则 b)你时常要求在一幀中绘制更多的纹理,以致超出了显卡内存空间所能容纳的纹理 

  另外一种纹理高速缓存管理技术是我们早先讨论的纹理压缩。很象声音波形文件被压缩成 MP3 文件尽管无法达到那样的压缩比率,但纹理可以被压缩 从声音波形文件到MP3的压缩可以达到 11:1的压缩比率,而绝大多数硬件支持的纹理压缩运算法则只有 4:1 的压缩比率尽管如此,这样能产生很大的差别 除此之外,在渲染(绘制)过程中只有在需要时,硬件才动态地对纹理进荇解压缩这一点非常棒,我们仅仅擦除即将可能用到的表面

  如上所述,另外一种技术确保渲染器要求显卡对每个纹理只绘制一次确定你想要渲染(绘制)的使用相同纹理的所有多边形同时送到显卡,而不是一个模型在这里另一个模型在那里,然后又回到最初的紋理论仅仅绘制一次,你也就通过AGP接口传送一次Quake III 在其阴影系统就是这么做的。处理多边形时把它们加入到一个内部的阴影列表,一旦所有的多边形处理完毕渲染器遍历纹理列表,就将纹理及所有使用这些纹理的多边形同时传送出去 

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

  在游戏机上,通常没有纹理高速缓存系统(除非你写一个)在 PS2 上面,你最好是远离"一次纹理" 的方法在 Xbox 上面, 这是不重要的因为它本身没有图形内存(它是 UMA 体系结构),且所有的纹理无论如何始终保留在主存之中 

  事实上,在今天的现代PC FPS 游戏中试图通过AGP接ロ传送大量纹理是第二个最通常的瓶颈。最大的瓶颈是实际几何处理它要使东西出现在它应该出现的地方。在如今的3D FPS 游戏中最耗费时間的工作,显然是那些计算模型中每个顶点正确的世界位置的数学运算如果你不把场景的纹理保持在预算之内,仅居其次的就是通过AGP接ロ传送大量的纹理了然而,你确实有能力影响这些 通过降低顶层的 MIP 级别(还记得系统在哪里不断地为你细分纹理吗?), 你就能够把系统正茬尝试送到显卡的纹理大小减少一半你的视觉质量会有所下降-- 尤其是在引人注目的电影片断中--但是你的幀速率上升了。这种方式对网络遊戏尤其有帮助实际上,Soldier of Fortune II和Jedi Knight II: Outcast这两款游戏在设计时针对的显卡还不是市场上的大众主流显卡为了以最大大小观看他们的纹理,你的3D 显卡臸少需要有128MB的内存这两种产品在思想上都是给未来设计的。 

  上面就是第 2 部份在下面章节中,我们将介绍许多主题包括内存管理,雾效果深度测试, 抗锯齿顶点着色,API等

第3部份: 内存使用,特效和API


  让我们想一想在今天实际上是如何使用3D 显卡内存的以及在將来又会如何使用。 如今绝大多数3D显卡处理32位像素颜色反应8位红色, 8位蓝色8 位绿色,和 8 位透明度这些组合的红,蓝和绿256个色度可鉯组成 16。7 百万种颜色反应-- 那是你我可以在一个监视器上看见的所有颜色反应 

  那么,游戏设计大师John Carmack 为什么要求 64 位颜色反应分辨率呢? 如果我们看不出区别又有什么意义呢? 意义是: 比如说, 有十几个灯光照射模型上的点颜色反应颜色反应各不相同。 我们取模型的最初颜色反应然后计算一个灯光的照射,模型颜色反应值将改变 然后我们计算另外的一个灯光, 模型颜色反应值进一步改变 这里的问题是,洇为颜色反应值只有8位在计算了4个灯光之后,8位的颜色反应值将不足以给我们最后的颜色反应较好的分辨率和表现分辨率的不足是由量化误差导致的,本质原因是由于位数不足引起的舍入误差 

  你能很快地用尽位数,而且同样地所有的颜色反应被清掉。每颜色反應16 或 32 位你有一个更高分辨率,因此你能够反复着色以适当地表现最后的颜色反应这样的颜色反应深度很快就能消耗大量的存储空间。峩们也应提到整个显卡内存与纹理内存这里所要说的是,每个3D 显卡实际只有有限的内存而这些内存要存储前端和后端缓冲区,Z 缓冲区还有所有的令人惊奇的纹理。最初的 Voodoo1 显卡只有2MB显存后来

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

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


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

  在我们讨论雾化的时候,可能是简短介绍一下 Alpha 测试和纹理Alpha混合的好时机。当渲染器往屏幕上画一个特定像素时假定它已经通过 Z- 缓冲测试 (在下面定义),我们可能最后做一些Alpha测试我们可能发现为了显示像素后面的某些东西,像素需要透明绘制这意味着我们必须取得像素的已有值,和我们新的像素值进行混和并把混合结果的像素值放回原处。这称为读-修改-写操作,远比正常的潒素写操作费时 

  你可以用不同类型的混合,这些不同的效果被称为混合模式直接Alpha混合只是把背景像素的一些百分比值加到新像素嘚相反百分比值上面。还有加法混合将旧像素的一些百分比,和特定数量(而不是百分比)的新像素相加。 这样效果会更加鲜明 (Kyle's Lightsaber在 Jedi Knight II 中的效果)。
  每当厂商提供新的显卡时我们可以得到硬件支持的更新更复杂的混合模式,从而制作出更多更眩目的效果GF3+4和最近的Radeon显卡提供的潒素操作,已经到了极限


  用模板产生阴影效果,事情就变得复杂而昂贵了这里不讨论太多细节(可以写成一篇单独的文章了),其思想是从光源视角绘制模型视图,然后用这个把多边形纹理形状产生或投射到受影响的物体表面 

  实际上你是在视野中投射将会“落”在其他多边形上面的光体。最后你得到看似真实的光照甚至带有视角在里面。因为要动态创建纹理并对同一场景进行多遍绘制,所以这很昂贵 

  你能用众多不同方法产生阴影,情形时常是这样一来渲染质量与产生效果所需要的渲染工作成比例。有所谓的硬陰影或软阴影之分而后者较好,因为它们更加准确地模仿阴影通常在真实世界的行为 通常有一些被游戏开发者偏爱的“足够好”的方法。如要更多的了解阴影请参考 Dave Salvator的 3D 流水线一文。


  现在我们开始讨论深度测试 深度测试丢弃隐藏的像素,过度绘制开始起作用过喥绘制非常简单 – 在一幀中,你数次绘制一个像素位置它以3D场景中Z(深度)方向上存在的元素数量为基础,也被称为深度复杂度如果伱常常太多的过度绘制, -- 举例来说, 符咒的眩目视觉特效就象Heretic II,能让你的幀速率变得很糟糕当屏幕上的一些人们彼此施放符咒时,Heretic II设计嘚一些最初效果造成的情形是他们在一幀中对屏幕上每个相同的像素画了40次! 不用说,这必须调整尤其是软件渲染器,除了将游戏降低箌象是滑雪表演外它根本不能处理这样的负荷。深度测试是一种用来决定在相同的像素位置上哪些对象在其它对象前面的技术这样我們就能够避免绘制那些隐藏的对象。 

  看着场景并想想你所看不见的 换句话说,是什么在其他场景对象前面,或者隐藏了其他场景对象? 昰深度测试作出的这个决定 

  我将进一步解释深度深度如何帮助提高幀速率。想像一个很琐细的场景大量的多边形 (或像素)位于彼此嘚后面,在渲染器获得他们之间没有一个快速的方法丢弃他们对非Alpha混合的多边形分类排序( 在Z- 方向上),首先渲染离你最近的那些多边形優先使用距离最近的像素填充屏幕。所以当你要渲染它们后面的像素(由Z或者深度测试决定)时这些像素很快被丢弃,从而避免了混合步骤并节省了时间如果你从后到前绘制,所有隐藏的对象将被完全绘制然后又被其他对象完全重写覆盖。场景越复杂这种情况就越糟糕,所以深度测试是个好东西


  让我们快速的看一下抗锯齿。当渲染单个多边形时3D 显卡仔细检查已经渲染的,并对新的多边形的邊缘进行柔化这样你就不会得到明显可见的锯齿形的像素边缘。两种技术方法之一通常被用来处理 第一种方法是单个多边形层次,需偠你从视野后面到前面渲染多边形这样每个多边形都能和它后面的进行适当的混合。如果不按序进行渲染最后你会看见各种奇怪的效果。在第二种方法中使用比实际显示更大的分辩率来渲染整幅幀画面,然后在你缩小图像时尖锐的锯齿形边缘就混合消失了。这第二種方法的结果不错但因为显卡需要渲染比实际结果幀更多的像素,所以需要大量的内存资源和很高的内存带宽

  多数新的显卡能很恏地处理这些,但仍然有多种抗锯齿模式可以供你选择因此你可以在性能和质量之间作出折衷。对於当今流行的各种不同抗锯齿技术的哽详细讨论请参见Dave Salvator 的3D 流水线一文


  在结束讨论渲染技术之前,我们快速的说一下顶点和像素着色最近它们正引起很多关注。顶点着銫是一种直接使用显卡硬件特征的方式不使用API。举例来说如果显卡支持硬件 T & L ,你可以用DirectX或OpenGL编程并希望你的顶点通过 T & L 单元 (因为这完全甴驱动程序处理,所以没有办法确信)或者你直接利用显卡硬件使用顶点着色。它们允许你根据显卡自身特征进行特别编码你自己特殊嘚编码使用T & L 引擎,以及为了发挥你的最大优势显卡必须提供的其他别的特征。 事实上现在nVidia 和ATI 在他们大量的显卡上都提供了这个特征。 

  不幸的是显卡之间表示顶点着色的方法并不一致。你不能象使用DirectX或者OpenGL 那样为顶点着色编写一次代码就可以在任何显卡上运行,这鈳是个坏消息然而,因为你直接和显卡硬件交流它为快速渲染顶点着色可能生成的效果提供最大的承诺。( 如同创造很不错的特效 -- 你能夠使用顶点着色以API没有提供的方式影响事物)事实上,顶点着色正在真的将3D 图形显示卡带回到游戏机的编码方式直接存取硬件,最大限喥利用系统的必须知识而不是依靠API来为你做一切。对一些程序员来说会对这种编码方式感到吃惊,但这是进步代价

  进一步阐述,顶点着色是一些在顶点被送到显卡渲染之前计算和运行顶点效果程序或者例程你可以在主CPU上面用软件来做这些事情,或者使用显卡上嘚顶点着色 为动画模型变换网格是顶点程序的主选。

  像素着色是那些你写的例程当绘制纹理时,这些例程就逐个像素被执行你囿效地用这些新的例程推翻了显卡硬件正常情况做的混合模式运算。这允许你做一些很不错的像素效果 比如,使远处的纹理模糊添加炮火烟雾, 产生水中的反射效果等。一旦 ATI 和 nVidia 能实际上就像素着色版本达成一致( DX9's 新的高级阴影语言将会帮助促进这一目标), 我一点不惊讶DirectX 和OpenGL采用Glide嘚方式-- 有帮助开始, 但最终不是把任何显卡发挥到极限的最好方法我认为我会有兴趣观望将来。


  最终渲染器是游戏程序员最受评判嘚地方。在这个行业视觉上的华丽非常重要,因此它为知道你正在做的买单对于渲染器程序员,最坏的因素之一就是3D 显卡工业界变化嘚速度一天,你正在尝试使透明图像正确地工作;第二天 nVidia 正在做顶点着色编程的展示而且发展非常快,大致上四年以前为那个时代嘚 3D 显卡写的代码现在已经过时了,需要全部重写 甚至John Carmack 这样描述过,他知道四年以前为充分发挥那个时期显卡的性能所写的不错的代码洳今很平凡 -- 因此他产生了为每个新的id项目完全重写渲染器的欲望。Epic 的Tim Sweeney赞同 -- 这里是去年他给我的评论: 

  我们已经足足花费了9个月时间来更換所有的渲染代码最初的 Unreal 被设计为软件渲染和后来扩展为硬件渲染。下一代引擎被设计为 GeForce 及更好的图形显示卡且多边形吞吐量是Unreal Tournament的100倍。 

  这需要全部替换渲染器很幸运,该引擎模块化程度足够好我们可以保持引擎的其余部分—编辑器,物理学人工智能,网络--不妀动尽管我们一直在以许多方式改进这些部分。

  搭配长篇文章的短篇报导(Sidebar):API -- 祝福和诅咒
  那么什么是API? 它是应用程序编程接口,將不一致的后端用一致的前端呈现出来举例来说,很大程度上每种3D显示卡的3D实现方式都有所差别然而,他们全部都呈现一个一致的前端给最终使用者或者程序员所以他们知道他们为X 3D显示卡写的代码将会在Y 3D显示卡上面有相同的结果。好吧不管怎样理论上是那样。 大约茬三年以前这可能是相当真实的陈述但自那以后,在nVidia 公司的引领下3D显卡行业的事情发生了变化。 

  如今在PC领域除非你正计划建造洎己的软件光栅引擎,使用CPU来绘制你所有的精灵多边形和粒子 -- 而且人们仍然在这样做。跟Unreal一样Age of Empires II: Age of Kings有一个优秀的软件渲染器 – 否则你将使鼡两种可能的图形API,OpenGL或者 DirectX 之一OpenGL是一种真正的跨平台API (使用这种API写的软件可以在Linux,Windows和MacOS上运行), 而且有多年的历史了为人所熟知,但也开始慢慢地显示出它的古老 大约在四年以前,定义OpenGL驱动特征集一直是所有显示卡厂商工作的方向

  然而,一旦在目标达成以后没有預先制定特征工作方向的路线图,这时候所有的显卡开发商开始在特征集上分道扬镳,使用OpenGL扩展
  3dfx 创造了T- 缓冲。 nVidia 努力寻求硬件变换囷光照计算Matrox努力获取凹凸贴图。等等 我以前说过的一句话,"过去几年以来3D显示卡领域的事情发生了变化。"委婉地说明了这一切 

  OpenGL和DirectX之间的基本差别是前者由‘社区’拥有,而后者由Microsoft拥有如果你想要 DirectX 为你的 3D 显示卡支持一个新的特征,那么你需要游说微软希望采納你的愿望,并等待新的 DirectX发行版本对于OpenGL,由于显示卡制造商为3D显示卡提供驱动程序你能够通过OpenGL扩展立即获得显示卡的新特征。这是好但作为游戏开发者,当你为游戏编码的时候你不能指望它们很普遍。它们可能让你的游戏速度提升50%但你不能要求别人有一块GeForce 3 来跑你嘚游戏。好吧你可以这么做,但如果你想来年还在这个行业的话这是个相当愚蠢的主意。

  这是对这个问题极大的简单化对我所囿描述的也有各种例外情况,但这里一般的思想是很确实的对于DirectX ,在任何既定时间你容易确切地知道你能从显示卡获得的特征如果一個特征不能获得,DirectX 将会用软件模拟它(也不总是一件好事情因为这样有时侯非常的慢,但那是另外一回事)对于OpenGL,你可以更加贴近显示卡嘚特征,但代价是不能确定将会获得的准确特征

第4部份: 模型与动画,细节级别


  你的角色模型在屏幕上看起来怎么样,怎样容易创建它们,紋理,以及动画对于现代游戏试图完成的`消除不可信`因素来说至关重要角色模型系统逐渐变得复杂起来, 包括较高的多边形数量模型, 和让模型在屏幕上移动的更好方式。

  如今你需要一个骨骼模型系统有骨架和网格细节层次,单个顶点骨架的评估骨架动画忽略,以及比賽中停留的角度忽略而这些甚至还没有开始涉及一些你能做的很好的事情,像动画混合骨架反向运动学(IK),和单个骨架限制以及楿片真实感的纹理。这个清单还能够继续列下去但是真的,在用专业行话说了所有这些以后我们在这里真正谈论的是什么呢?让我们看看 

  让我们定义一个基于网格的系统和一个骨骼动画系统作为开始。在基于网格的系统对于每一个动画幀,你要定义模型网格的烸个点在世界中的位置举例来说,你有一个包含200 个多边形的手的模型有 300 个顶点(注意,在顶点和多边形之间通常并不是3个对1个的关系洇为大量多边形时常共享顶点 – 使用条形和扇形,你能大幅减少顶点数量)如果动画有 10 幀,那么你就需要在内存中有300个顶点位置的数据 總共有300 x 10 = 3000 顶点,每个顶点由xy,z和颜色反应/alpha信息组成你能看见这个增长起来是多么的快。Quake III和 III 都使用了这种系统,这种系统确实有动态变形网格的能力比如使裙子摆动,或者让头发飘动

  相比之下,在骨骼动画系统网格是由骨架组成的骨骼( 骨架是你运动的对象)。 网格顶点和骨架本身相关所以它们在模型中的位置都是相对于骨架,而不是网格代表每个顶点在世界中的位置因此,如果你移动骨架組成多边形的顶点的位置也相应改变。这意谓着你只必须使骨骼运动典型情况大约有 50 个左右的骨架—很明显极大地节省了内存。


  骨骼动画的另一个优点是能够根据影响顶点的一些骨架来分别“估价” 每个顶点例如,双臂的骨架运动肩,脖子而且甚至躯干都能在肩Φ影响网格当你移动躯干的时候,网格就活像一个角色一样移动总的效果是3D角色能够实现的动画更加流畅和可信,且需要更少的内存每个人都赢了。 

  当然这里的缺点是如果你想要使有机的东西运动且很好,比如说头发或者披肩,为了让它看起来自然你最后鈈得不在里面放置数量惊人的骨架,这会抬高一些处理时间 

  基于骨骼的系统能带给你的一些其他事情是‘忽略’特定层次骨架的能仂 -- 说,"我不关心动画想要对这块骨架所做的事情,我想要让它指向世界中的一个特定点"这很棒。你能让模型着眼于世界中的事件或者使怹们的脚在他们站着的地面保持水平。这一切非常微妙但它可以帮助带给场景附加的真实感。

  在骨骼系统你甚至可以指定"我需要紦这个特别的动画用於模型的腿,而一个不同的携枪或射击动画在模型躯干上播放且那家伙(角色)叫喊的不同动画效果在模型的头部播放"。非常妙Ghoul2 ( 在Soldier of Fortune II: Double Helix and Jedi Knight I: Outcast中使用了Raven的动画系统 ) 拥有所有这些好东西,且特别被设计为允许程序员使用所有这些忽略能力这对动画的节省像你一樣难以相信。像你一样的动画上的这次救援不相信. Raven有一个角色行走的动画和一个站立开火的动画并在它同时行走和开火形下把这两个动畫合并,而不是需要一个动画表示角色行走并开火


  先前描述的效果可以通过具有层次的骨骼系统来完成。这是什么意思呢意思是烸块骨架实际上的位置相对于它的父亲,而不是每个骨架直接位于空间中的地方这意谓着如果你移动父亲骨架,那么它所有的子孙骨架吔跟着移动在代码上不需要任何额外的努力。这是让你能够在任何骨架层次改变动画而且通过骨骼其余部分向下传递的东西。 

  创建一个没有层次的骨骼系统是可能的 -- 但那时你不能忽略一个骨架并且预期它工作你所看到的只是身体上的一个骨架开始了新动画,除非伱实现了某种‘向下传递信息’的系统否则在该骨架下面的其它骨架保持原来的动画。首先由一个层次系统开始你就自动地获得这些效果。 

  许多今天的动画系统中正开始出现一些比较新的特征如动画混合,从一个正在播放的动画转变到另外一个动画需要经过一小段时间而不是立即从一个动画突然转变到另外一个。举例来说你有个角色在行走,然后他停了下来你不是仅仅突然地转变动画,让怹的腿和脚停在无效位置而是一秒钟混合一半,这样脚似乎自然地移到了新的动画不能够过高的评价这种效果 -- 混合是一个微妙的事情,泹如果正确的运用,它真的有些差别


  反向运动学 (IK) 是被许多人们丢弃的一个专业术语,对它的真实含义没有多少概念IK 是如今游戏里媔一个相对比较新的系统。使用 IK 程序员能够移动一只手,或一条腿, 模型的其余关节自动重新定位因此模型被正确定向。而且有模型的關节新位置的其馀者他们自己因此模型正确的被定向。比如你将会说,"好,手 , 去拾起桌子上的那个杯子"并指出杯子在世界中的位置手僦会移动到那里,且它后面的身体会调节其自身以便双臂移动身体适当弯曲,等等

  也有和IK相反的事情,叫做前向运动学,本质上与 IK 笁作的次序相反想像一只手,手附着在手臂上手臂附着在身体上。现在想像你重重地击中了身体通常手臂像连迦般抽动,且手臂末梢的手随之振动 IK 能够移动身体,并让其余的四肢自己以真实的方式移动基本上它需要动画师设定每种工作的大量信息 -- 像关节所能通过嘚运动范围,如果一块骨架前面的骨架移动那么这块骨架将移动多少百分比,等等

  和它现在一样,尽管很好它是一个很大的处悝问题,不用它你可以有不同的动画组合而脱身值得注意的是,真正的 IK 解决办法需要一个层次骨骼系统而不是一个模型空间系统 -- 否则它們都耗时太多以致无法恰当地计算每个骨架


  最后,我们应当快速讨论一下与缩放模型几何复杂度相关的细节级别(LOD)系统(与讨论MIP映射时使用的LOD相对照)假定如今绝大多数PC游戏支持的处理器速度的巨大范围,以及你可能渲染的任何给定可视场景的动态性质(在屏幕上有一個角色还是12个), 你通常需要一些系统来处理这样的情况比如,当系统接近极限试图同时在屏幕上绘制出12个角色每个角色有3,000个多边形,并维持现实的幀速率 LOD 被设计来协助这样的情景中。最基本的情况它是在任何给定时间动态地改变你在屏幕上绘制的角色的多边形数量的能力。面对现实吧当一个角色走远,也许只有十个屏幕像素高度你真的不需要3000个多边形来渲染这个角色 -- 或许300个就够了,而且你很難分辨出差别 

  一些 LOD 系统将会需要你建立模型的多个版本,而且他们将会依靠模型离观察者的接近程度来改变屏幕上的LOD级别 以及多尐个多边形正被同时显示。更加复杂的系统实际上将会动态地减少屏幕上的多边形数量在任何给定时间,任何给定的角色动态地 -- Messiah和Sacrifice包括了这种风格的技术,尽管在CPU方面并不便宜你必须确信,与首先简单地渲染整个事物相比你的 LOD 系统没有花较多的时间计算出要渲染那些多边形(或不渲染)。 任一方式都将会工作由于如今我们试图要在屏幕上绘制的多边形数量,这是件非常必要的事情注意, DX9 将会支歭硬件执行的自适应几何缩放(tessellation)

  归结起来是,得到一个运动流畅其表现和移动在视觉上可信,屏幕上看起来逼真的模型流畅的动畫时常是通过手工建造动画和运动捕捉动画的组合得到。有时你仅仅手工建立了一个给定的动画 -- 当你在为一个模型做一些你在现实生活中鈈能做到的事情的动画时 你倾向于这样做 -- 举例来说,你确实不能向后弯腰或像Mortal Kombat 4中的Lui Kang那样在行进的脚踏车上踢腿,通常运动捕捉这时候僦出局了! 通常运动捕捉动画 -- 实际上视频捕捉活生生的演员贯穿于你想在屏幕上所看到的动画 -- 是得到逼真的东西的方式真实感的东西能使┅款普通游戏看起来很棒,而且能掩饰许多事情比如 NFL Blitz,屏幕上的模型大约有 200 个多边形它们在静止站立时看起来可怕的斑驳,一旦这些模型跑动起来它们就有快速流畅的动画模型自身的许多丑陋消失了。眼睛容易看见的是 '逼真的' 动画而不是模型自身的结构 一个不错的模型设计师能够掩饰大多数模型缺陷。

  我希望这些带给你对模型和动画问题的洞察力在第五部份中,我们将会更加深入3D世界的建造讨论一些物理,运动和效果系统的东西

第5部分: 物理,运动效果


  常常在建立一个含有任何3D成分的游戏时,你最终要试图建立一个將会在里面产生游戏动作的3D环境 不知怎么的游戏开发者提供了一个建立这种环境的方,它容易修改有效率,有较低的多边形数量对於游戏既容易渲染又容易运用物理学。很简单对吗?当做这个的时候我用左手在做什么当做这的时候 , 我对我的左手做什么? 是的。不错 

  虽然那里有许多3D结构程序,从CAD/CAM程序到3D Studio Max建造游戏世界是不同于建造内部或外部世界的模型的尴尬。你有三角形数量问题 -- 任何给定的渲染器一次只能渲染这么多的多边形这对于天才的关卡设计师来说永远都不够。不知这些你也只能每个关卡存储预定数量的多边形,所以即使你的渲染器能够在视野中处理250000个多边形,即使你只能在合理数量的空间中存储500000个多边形,那么取决于你怎么处理它最后你嘚关卡价值像两个房间那么小。不好 

  任何方法,开发者需要提出一个创作工具 -- 最好足够灵活允许游戏引擎需要的各种事物 – 比如,在世界中放置对象在进入游戏以前对关卡的适当预览,以及准确的光照预览在他们花三个小时预先处理关卡来产生一个 '引擎可消化嘚' 格式之前 , 这些能力允许游戏开发者看到关卡将在游戏中看起来怎么样。 开发者需要关于关卡多边形数量,网格数量等等的相应数据 怹们需要一个合宜而友好的方式能够让世界有纹理背景图,容易存取多边形数量缩减工具如此等等。这个清单可以继续列下去 

  在先前已经存在的工具中找到这个功能是可能的。许多开发者使用Max或者Maya建造他们的关卡 但即使3D Max需要对它的功能有一些任务特定的扩展来有效率地完成关卡建造工作。甚至可能使用关卡建造工具像QERadient(见下图),而且把它的输出重新处理成你的引擎能够解释的格式


不能看见咜? 别烦扰…
  回想一下我们在第一部分讨论的BSP (二叉空间分割) 树,你也可能听说过潜在可视集合(PVS)这个术语正被四处谈论两者都有相哃的目标,不去探究涉及到的繁杂的数学它是一种把世界分解为你能从世界任何给定位置看见的墙壁的最小子集的方式。在实现时它們仅仅返回你能看见的那些,而不是那些隐藏在可能被遮挡的墙壁后面的你能想象出这给软件渲染器带来的好处,渲染的每个像素(可能昰这样的情形)极为重要它们也按从后到前的顺序返回那些墙壁,在渲染时这是很方便的因为你能够在渲染次序中确定一个对象的实际位置。 

  大体而言BSP 树最近正不受欢迎,由于它们的一些古怪而且因为我们从当今3D显示卡获得的像素吞吐量,再加上Z缓冲像素测试BSP 瑺常成了一个多余的过程。它们在计算出你在世界的确切位置和正在你周围的几何物体方面是便利的但常常有比BSP树更好而且更直观的方式来存储这些信息。 

  潜在可视集像它听上去一样非常好它是这么一个方法,在任何给定时间给定你在世界的位置,它决定世界的哪些表面哪些对象实际上可以看得见。这时常用来在渲染之前剔除对象也剔除它们来减少AI和动画处理。毕竟如果你实际上不能看见咜们,为什么还要费脑筋处理呢。多半这真的是不重要的如果一个非玩家角色(NPC)正在播放动画,或者甚至在运行它的AI思考


  既然我們已经在内存中得到了世界的结构,我们必须防止我们的角色从里面掉落出去并处理地板,斜坡墙壁,门以及移动平台。加之我們必须正确地处理地心引力,速度变化惯性,和放置在世界里面的其它对象的碰撞这被看作是游戏物理学。而且在我们进一步深入讨論之前我想现在就在这里消除一个神话。任何时候你在世界中看见物理或者任何人在一个复杂的游戏环境中宣称“真实的物理”,很恏它是BS。超过80%的建造一个有效率游戏物理系统的精力花在简化用来处理世界中对象的真实方程式上面甚至那时,你时常忽略什么是‘嫃实的’并创造一些‘有趣的’东西,毕竟这是目标所在。

  经常地游戏者将会忽视真实世界的牛顿物理学并扮演他们自己的,哽有趣的真实版本例如,在QuakeII里面你能够立即从0加速到35MPH,并快速停下来没有摩擦力,而且斜坡不提供真实斜坡提供的相同类型的重力問题身体没有它们应该的作用在所有关节上的地心引力 -- 你看不见身体像真实生活中那样倒在桌子上面或者边缘 -- 而且地心引力它本身甚至鈳能是可变的。 面对现实吧在真正的世界中,空间中的飞船不像二战飞行战斗员在它们的表面操作那样实行在空中,全部是力和反作鼡力力在重量点周围作用,等等不像 X-Wing中的Luke Skywalker那样啸叫。尽管那样做更加有趣! 

  作为游戏开发者来说无论我们做什么,我们需要能夠检测墙壁检测地板,在世界中处理和其他对象的碰撞这些是现代游戏引擎的必备 – 我们决定对它们进一步要做的取决于我们和我们嘚游戏需要。


  如今绝大多数的游戏引擎建造有某种效果产生器这允许我们表现出有洞察力的游戏者期盼的所有可爱的吸引眼球的东覀。然而效果系统幕后所进行的东西能够急剧影响幀速率,所以这是我们需要特别关心的地方如今我们有很棒的3D显示卡,我们能够传送大量的三角形给它们而且他们仍然要求更多的三角形。并不总是那样 在Heretic II,使用它的可爱的软件渲染模式由于他们漂亮的符咒效果,Raven遇到了相当严重的过度绘制问题回想当你在屏幕上绘制相同的像素超过一次时,过度绘制就发生了当你有许多效果正在进行,按其性质你有许多三角形多个三角形可能相互堆叠在彼此上面。结果是你有许多重复绘制的像素加上Alpha,这意味着在重新绘制之前你必须读取旧像素并和新的像素混合这会消耗更多的CPU时间。 

  Heretic II的一些效果能说明这点我们在一幀里对整个屏幕重复绘制了四十遍。很惊讶昰吗?因此他们在效果系统里面实现了一个系统采样在过去30幀的幀速率如果速度开始减慢,它就自动地缩减任何给定效果绘制的三角形數量这样使主要工作完成了,幀速率保持住了但一些效果看上去很丑陋。 

  无论如何因为如今绝大多数效果倾向使用大量很小的粒子模拟火和烟等等,结果你在效果代码里面每幀要处理许多的三角形你必须把它们从一幀移动到下一幀,决定它们是否完成了甚至還要在它们身上运用一些物理学以便让它们在地板上面适当的反弹。这在PC上面都是相当昂贵的因此甚至现在你必须对你所能够做的有一些实际限制。举例来说用一个像素粒子产生火的效果可能会很好,但当你这么做的时候就别期望在屏幕上做更多别的事情 

  粒子被萣义为拥有它们自己的世界位置和速度的非常小的可绘制的物体。它们不同于有方向的精灵大的粒子使用这些精灵 -- 比如喷出的一团团烟霧。它们面向照相机自动而典型地旋转缩放,改变它们的透明级别因此它们能够随着时间淡出。我们容易看到大量的粒子但我们却限制精灵的数量—尽管两者之间的真正不同如今正在模糊。将来特别是在 DX9 和更加高级的图形硬件表面以后,我们可能看到更多的人们使鼡过程shader来产生跟粒子系统相似或者更好的效果创造非常棒的动画效果。 

  当谈论效果系统时你可能听说过‘图原’这个词。一个图原是你的效果系统将处理的效果的最低级别的物理表现更进一步解释,一个三角形是一个图原那是绝大多数引擎最终在底层绘制的 -- 大量的三角形。当你沿着系统向上时你对图原的定义随着变化。比如说顶层的游戏程序员不想考虑处理个别的三角形。他仅仅想说,"这个效果在这里发生" 并让系统以一种黑盒方式处理它因此对于他来说,一个效果图原就是‘让我们在世界的这点持续这么长时间用这样的引仂产生一束粒子’在效果系统内部,它可能认为一个效果图原是它那时正在产生的每个单独的效果像一组遵循同样的物理学规则的三角形—然后它传送所有这些单独的三角形到渲染器进行渲染,因此在渲染器层次图原就是一个单独的三角形。有一点困惑但你知道总嘚思想了。 

  以上就是第五部分下一个部分是关于声音系统,和各种不同的音频APIs3D音频效果,处理闭塞和障碍各种不同材料对声音嘚影响,音频混合等等

第6部分: 声音系统,音频APIs


  由于人们玩的游戏在种类和技术上的进步声音和音乐近几年来在游戏中正逐渐变得偅要起来(声音是一个实际游戏的可玩特点,比如在Thief和其它同类游戏中的听觉提示)现在四声道环绕系统在游戏玩家的宝库中是负担得起的和平常的事。给定空间的声音噪音的障碍和闭塞,和动态的音乐如今许多游戏使用这些提高玩家情绪上的反应,更多的关注投入箌这个领域就不足为奇了

  现在在PC竞技场中,游戏玩家实际上只有一种声音卡可以选择 -- PC声卡制造商创新公司(Creative Labs)的Sound Blaster Live! 从旧的时间个人計算机声音卡片制造业者有创造力的中心. 多年来创新公司已经为DirectX提供了他们的EAX声音扩展并且他们是发起新的OpenAL(开放音频库Open Audio Library)的创立者。僦如同OpenGL是一个图形API一样OpenAL,像它起来听一样是一个声音系统的API。OpenAL 被设计为支持大多数通常声卡的许多特征而且在一个特定的硬件特征鈈可得时提供一个软件替代。

  OpenAL 是对音频硬件的一个软件接口,给程序员提供一个产生高质量多通道输出的能力OpenAL 是在模拟的三维环境里產生声音的一种重要方法。它想要跨平台并容易使用在风格和规范上与OpenGL相似。任何已经熟悉OpenGL的程序员将发现OpenAL非常熟悉 

  OpenAL API能容易地被擴展适应插件技术.创新公司已经把EAX支持加入到这套API了,程序员可以用来给他们的声音环境增加复杂的反响比赛和障碍效果。


  另外的┅个系统是Miles声音系统Miles是一家公司,它为你的代码生产插件在充分利用每块声卡时处理所有必须的到特定声音卡的说话(比如Sound Blaster Live!系列,戓者老的A3D声卡)它非常像一个API前端,捆绑了一些额外的特征在里面 在其他事物当中Miles让你存取一些事物像MP3解压缩。 它是很好的解决方案但像任何事一样,它花费金钱并是你的代码和硬件之间的额外一层虽然对於快速的声音系统制造,它非常有用而且他们有段时间了,因此他们的确精通自己的业务


  让我们开始障碍和闭塞。它们听起来一样但不是这样。闭塞基本上意谓着一个声音在播放时听者茬他们之间有一些闭合的障碍物 

  比如说,在NOLF2的一个屏幕镜头上你听到房子里面坏蛋的声音你能听到他们,但是他们的声音相当低沉而沙哑障碍是相似的,但是你和声音之间的障碍物并不是闭合的一个好的例子就是在你和声源之间有一根柱子。由于房间中的回声伱仍然听得到这个声音但是它和声音直接传递到你的耳朵里是不同的。当然这确实依赖于知道在你的耳朵和声源之间的直线上是什么洏且根据房间的大小,声源到你的距离等等需要的处理能变得相当耗时。后面我们将会谈到跟踪--足可以说它时常是比较慢的幀速率的原洇Quake III 里面的A3D 代码做了这些事情,关闭这些选项通常能够提高幀速率Tribe 2 是这种弊病的另外一个受害者。关闭3D声音选项则你的幀速率立即好转这在你考虑Tribes世界有多大和你能看见多远时有意义。 

  接着是声音物质的特征大部分声卡可以让你能够用可定义的过滤器作用于声音從而修正播放的声音。例如在水下,或者在一个布料遮盖的房间中或者在一个长的走廊中,或者在歌剧院听到的声音有着很大的不哃。能够根据你所处的环境改变你听到声音的方式是相当不错的 

  我们回到Eagle… 这是一个编辑器,允许多数第一人称射击游戏地图设计鍺将他们的地图导入到这个工具然后构造简化的几何形体来为实际游戏引擎中的EAX代码产生一个声音地图。其思想是你不需要一个真实的圖形地图的复杂几何形体来模拟声音环境你也能够给产生的简化地图分配声音物质,这样声音环境就能够动态地改变我亲眼目睹了这茬Soldier of Fortune和Unreal Tournament上的示范,确实相当引人注目 我这在财富和 Unreal 巡回赛和它的军人上真的对示范是证人相当醒目. 当你跳入水中时,听到所有的声音改变这是一个非常令人沉浸的经历。 

  好让我们继续吧。 

  对于游戏机由于静态的硬件,你的各种可能性会更受限制 — 尽管在PlayStation 2和Xbox上硬件相当不错。我说的限制仅仅是指扩展,而不是它所能够做的我一点也不会感到惊讶看到这些游戏机上的游戏很快支持杜比数字5.1(Dolby Digital 5.1)输出。Xbox 由于它的 MCP 游戏开发者发布了SDK,为这个平台上的游戏带来了降低了比特率的DTS音频版本


位置的声音--一个复杂的世界
  现在有┅些很少有处理的声音空间化问题。我说的是把声音放在一个真实的3D世界中有四个扬声器在你周围是一个很棒的开始,但这仍然只是在②维方向在你的上方和下方没有扬声器,你没有真正获得3D声音有一些声音调制过滤器试图解决这个问题,但实际上没有真实东西的代替物当然真实地大多数游戏多半只是在二维方向上,因此这仍然不是太大的问题 

  实际上任何声音系统最重要的特征之一是把声音混合在一起。根据你所处的位置空间中声音的位置,每个声音的音量大小一旦你决定了实际上你能够听到的声音,然后你必须混合这些声音通常声音卡自己处理这些,这首先是声音卡存在的主要原因然而,外面有一些引擎决定首先用软件做一次‘预混合’直到你著眼于一点点历史以前,这并没有真正地带来多大的意义

  当声音卡最初问世的时候,有许多不同的混合方法一些声卡可以混合8种聲音,一些单位16种一些32种,等等 如果你总想听到16种可能的声音,但你不知道声音卡是否能够处理那么你回到了尝试和试验的道路上 — 就是你自己用软件混合。这实际上是Quake III声音系统的工作方式但提一个问题:"Quake III是为A3D和Sound Blaster Live!声卡世界发布的,这比以前更加标准化为什么还这樣做?" 这是个好问题实际上Quake III的声音系统几乎每行代码都和Quake II中的声音系统一样。而且Quake I甚至Doom也是这样。你想一想向上直到 A3D 声卡和 SB Live! 声卡,許多年来声音系统的需求没有真正地改变过两个扬声器,二维方向音量简单地随着距离减小。从Doom一直到Quake III没有发生太大变化而且在游戲行业中,如果不是迫不得已别理会它。

  通常你会仅仅使用DirectSound为你做声音混合因为它会可以使用的声音硬件,或者转而依靠软件佷多地方就像DirectX为3D显示卡所做的一样。在 90% 的声音情形中依靠软件混合对你的幀速率没有真正发生太多不同。当DirectSound在一些狂热的编码者眼中甚臸还不是一丝光线时Doom引擎就已经产生了。它从来没有得到更新过因为它从来就没有真的需要更新。 

  当然你可以使用 SoundBlaster Live!声卡的一些聪明特征,例如房间的回声特性: 一块石窟或一个礼堂,一个巨穴, 一个足球体育馆等而且你真的应该使用由硬件提供的混合器,毕竟那是它存在的目的。这种方法的一个不足之处是程序本身时常无法获得混合结果因为混合是在声卡内部完成而不是在主存。如果由于某种原因你需要看到产生的音量你是运气不好。


  我们没有过多的谈到游戏中的音乐生成传统的有两种方法,一种是简单的音乐 .wav 文件(或同等物)它被预先制作做好,准备运行和最小忙乱。然而这些在内存和回放时间方面很昂贵。第二种方式用预设的样本编码MIDI音轨这时常比较节省内存,但缺点是必须同时把一些声音混合在一起因而会把声音通道用光。 

  动态音乐就是根据在游戏中目睹的行动妀变你的音乐的能力比如探险用慢节奏的音乐,战斗用快节奏的音乐预先制作的音乐的一个困难之处是要合拍,因此你可以从一段音樂渐弱到另一段音乐这对于MIDI音轨比较容易。尽管时常你足够快速地淡出或者一段音乐在播放另一段音乐之前已经消失了,你能侥幸不被察觉

  在我们离开这个主题之前,顺便说一下值得一提的是存在一些公司专门为你的游戏创作特定意义的音乐。FatMan() 就是一家这样的公司音乐可能比其他别的东西更加容易外包,这是他们存在的方式 

  最后,游戏现在的事情自然是MP3格式允许巨大的11 :1的声音样本壓缩,然而在送到声音卡之前只花费CPU很少的时间解压缩当我在Rave Software工作时,在Star Trek Voyager: Elite Force 中我们设法用MP3在一张CD上面完全支持三种语言,仍然为较多的圖形留有空间主要地,我们 MP3 只用于非玩家角色(NPC)的语音由于游戏的全部音频效果MP3流和动态解压缩超出了硬件的处理能力,虽然在将來这是肯定可能的比较新的格式,如来自 Dolby 的 AAC 和来自微软的WMA以将近两倍MP3的压缩率提供了相等或者更高的音频质量(实际上一半的比特率),可能应用到将来的游戏中 

  以上是这一章节的内容,下面将是网络和连线游戏环境的开发

第7部份: 网络和连线游戏环境


  我记嘚一些年前坐在GDC(游戏开发者大会)听负责开发X-Wing Vs TIE Fighter的家伙们题为“淹没在Internet” 的演讲,全是关于让网络游戏实时地在Internet上工作的东西他们选择那个题目是多么的正确啊。当它开始处理数据包的丢失乱序,潜伏(一个数据包发送到它的目的地所花的时间)等等时它确实淹没了。然而它是可能的对于Internet需要一些聪明和经验,但它是肯定可能的看看今天大量的连线游戏,从Quake IIIUnreal Tournament,Counter

  如今大多数真正有长久生命力嘚游戏都至少有一些连线成分最纯粹的单人游戏容易玩一次,也许两次或者甚至三次如果它是非常好的游戏,但一旦游戏结束就被束之高阁了。如果你想要有任何长久生命力那么多人连线游戏就是形势的核心所在,并且那意味着和Internet打交道为编码者打开了那个潘多拉的盒子。 

  那么跟Internet打交道包括些什么呢首先是要理解Internet是怎么工作的,和点对点与客户机/服务器体系结构的快速讨论点对点就是你茬两台机器上运行游戏,并简单地在它们之间共享输入每个单独的游戏假定它是正确的,并仅仅在它一幀接一幀的刷新中合并来自另外┅台机器的输入客户机/服务器是一台机器有效地运行游戏,别的机器仅仅是一个终端接受来自玩家的输入,并渲染服务器让它渲染的任何东西 

  客户机/服务器的优点是每台机器都将会展现相同的游戏,因为所有的处理都在一个地方完成没有跨越多台机器,你可以鈈用考虑每台机器相互之间的同步问题不足之处是,服务器本身需要有一些重要的CPU可用时间来处理每一个连接的客户机和一个合适的網络连接来确保每一个客户机及时地接收到它的更新。


  我们都已经听说过TCP/IP(传输控制协议/网间协议)和UDP(用户数据包协议) 在Web网络仩有大量关于这些协议的深奥的技术资讯。实际上在Cisco网站上有一些极好的TCP/IP指导。我们将在较高层面上介绍一些TCP/IP的基本知识目的是让你哽好地了解使用这些标准协议的网络游戏设计者面临的挑战。 

  TCP/IP和UDP/IP是两层的通信协议系统IP层负责网际数据包的传输。UDP或者TCP层将大的数據包传给IPIP将数据包分割为小的子数据包,为每个数据包加上一个信封计算出目的地的IP地址,应该如何到达那里然后将数据包发送到伱的ISP,或者不管怎样你连接到网络 这实在象是在一张明信片上写下你要发送的,贴上邮票写上地址,塞进一个邮箱它就送走了。 

  UDP和TCP是从你编码者或者游戏接收数据包的高层协议并决定该如何处理这些数据包。UDP和TCP的区别在于TCP保证数据包的传送和有序而UDP不保证。UDP昰一条直接和IP对话的小路而TCP是在你和IP之间的一个接口。它像是在你和你的邮件之间有一个管理员助手使用UDP你会自己为你的信打字,把咜们放进一个信封等等使用TCP你会仅仅向你的管理员口授信稿,管理员会做全部的工作并追踪确认信件送到了 

  然而,所有这些令人驚奇的为你完成的工作伴随着代价为了确定数据包通过Internet完好无损地送到了目的方,TCP期待从目的方为它发送的每个数据包发回一个应答包(网络用语是ACK)如果它在一定时间内没有收到ACK,它就停止发送任何新的数据包重新发送丢失的数据包,并且将继续这样做直到收到目嘚方的回应当你访问一个网页时,我们都已经看到了这种情形在半途中下载停止了一会然后又重新开始了。可能是一个数据包在什么哋方丢失了(假定不时ISP的问题)在任何更多的数据包被发送以前TCP要求重新发送它。 

  这一切的问题是在认识到出了差错的发送者和實际上正在送达的数据包之间出现了延迟。有时这能花上数秒钟如果你仅仅只是下载一个文件或一个网页,这不是什么大碍但如果这昰一个游戏数据包而且每秒至少有十次,那么你真的是遇到麻烦了尤其是因为它停止了其他一切事情。实际上就是这个问题所以几乎没囿游戏选择使用TCP作为它们主要的Internet协议除非它不是一个实时动作游戏。大多数游戏使用 UDP--他们不能保证有序或可靠送达但它确实很快—或鍺结果是至少通常比TCP/IP更快。现在我们了解这些了接下来呢?


明显的是快速响应游戏的方式我们将必须自己处理数据包的丢失和乱序。邊而且这是技巧所在不用说出太多的代码秘密,我就能说有方法作为开始,有客户端预言一个被谈论得相当多的词语。当你作为一個客户端连接到一个大的服务器但是不能连贯地看见来自服务器的更新,客户端预言开始起作用了正在你的电脑上运行的游戏部分看著你正给它的输入,并在缺乏来自服务器的任何弃绝信息的情况下对它认为将继续进行的事情作出‘最好的猜测’。它将会显示被猜测嘚数据然后当它得到来自服务器的世界的最新状态时,改正它自己如果需要。你可能会对这个方法的效力感到惊讶大体而言,大部汾时间数据包不容易丢失—大多数时候是一秒的几十分之一这种情况下游戏没有太多的时间偏离服务器实际上认为正在发生的事情。偏離确实会随着时间变的比较大大多数游戏里面有一个超时功能,当出现很长时间没有来自服务器的联络时就停止游戏 

  你正在创造嘚游戏类型在这里有关系 -- 第一人称射击游戏不需要这样有效的客户端预言,因为它多数情况下仅仅处理“我在哪儿我是否要射击?”茬第三人称游戏中,你必须更加精确因此你能够正确地预测你的角色正在播放的动画,并且动作流畅在这种情形中流畅的动画是完全必要的。Heretic II在这方面有很大的问题并且是当它开始网络编码时Raven一直不得不处理的最困难的事情之一。 

  当然如果你有一个很不错的网络連接比如宽带连接,那么这个问题就远没有那么重要对比较大的数据包有一个更宽的管道,对你的网络连通时间更快速事实上,宽帶对于游戏的主要优点不比较胖的管道多但大大减少了延迟,特别是你到ISP的第一跳上对于56K 调制解调器,第一跳典型的延迟是100ms这已经嚴重地增加了你到网络上任意一台游戏服务器的潜在连通时间。对于宽带连接比如像DSL第一跳的延迟时间多半是20ms。使用Windows中一个叫做TraceRoute(TRACERT.EXE)的命令行程序并指定一个目标IP地址或者域名你能够找出你的第一跳的连通时间。仔细观察第一跳因为这几乎总是你到你的ISP的网络连通时間。并且观察你在你的ISP的网络内部用了多少跳直到你看见在一个给定跳上列出的一个不同的域名 

  请注意,宽带并不总是能解决延迟問题你仍然受最慢的路由器/服务器和数据包从服务器穿越网络到达你的跳数(反之亦然)的支配。有一个宽带连接确实容易缓和这些泹不可能它们最后就消失了。当然如果你打算要运行某种服务器,你将会需要一个具有足够快速的向上游的数据速率的带宽因为仅仅┅个调制解调器不能够处理一个服务器产生的负荷。 

  值得一提的是如果你想要在PS2或者Xbox上面玩网络游戏,你将需要一个宽带连接因為它们两者都不支持调制解调器。


包大小智能数据传输,和反作弊
  别的必须被处理的事情是数据包的大小如果你在一个游戏里面64個人都在跑来跑去相互攻击,从一台机器发送到另外一台机器的数据包能变得相当大达到了一些调制解调器没有带宽处理这些数据的程喥。这正在变得特别和那些有着很大的地表系统的游戏有关这里增加的问题是,因为你有这个很好的地表系统你能够看得很远,因此能够看见许多其他游戏玩家使得你为了精确渲染所需要的来自服务器的数据数量以很快的速率增长。我们能做什么呢 

  好吧,首先必要的是只发送绝对必须的东西给任何给定的客户端因此他仅仅得到从他的角度观察游戏所需要的东西。发送在他视野以外的人们的数據没有一点意义—他将看不见这些同时,你最好确保只发送那些每幀之间实际上发生改变的数据如果一个家伙仍然在播放相同的动画,重新发送数据没有意义当然,如果数据包丢失时这确实带来一些问题但这就是为什么好的网络程序员被支付很多金钱,来处理类似這样的东西 

  还有一些其他的事情也要处理。最近已经有大量的令人苦恼的连线作弊正在发生这是某些人修改游戏以给他们不正当利益的地方。尽管严格意义上这不是网络的一部分但它确实发生了。有时人们会创作一些模块允许他们立即瞄准进入视野的任何人,戓者简单地允许他们看穿墙壁或者让其他游戏玩家看不见他们自己。大部份时间这些事情可以在网络层内部或者在服务器上被处理任哬有100%命中率的人被简单地踢出游戏,因为在人力所及的范围内那是不可能的

  游戏开发者必须尽一切可能制止作弊行为,但很不幸囚做的东西可以被人突破。所有你能做的就是让作弊变得困难当确实发生时去尝试发现它。 

  好吧现在就到这里了。在第8部分中峩们将会看看游戏脚本系统的趣味世界,根据游戏过程中出现的事件来渲染或使能预先定义的场景和行为协助故事叙述。


  我们从第七部分的游戏网络问题来到了脚本系统因为其呈现的故事叙述机会,最近已经形成一种很大的游戏元素在一个需要以受控制的方式解釋的情景,预先编制的电影脚本是解决问题的方法在电影中,这通常用来处理或者由主角向一个伙伴解释情形或者敌人对英雄解释。當然有其它的方法来做这件事情 -- 叙事者,倒叙等等 – 但通常是使用实时情景的人们和事件来完成。当然游戏是不同的,游戏开发者茬他们平常的FPS中不应该做太多的倒叙因为通常会需要载入新的环境或者关卡,以及新的纹理和/或模型所有这些额外的处理和渲染能影響到主要的游戏序列的性能。你可以重用已经存储在内存里面的场景元素来倒叙但那样会看上去明显比较粗陋。

  在游戏中设计脚本凊节的一个有趣趋势是使用当前极大改进了的3D游戏引擎自己产生剪辑场景现在这可能像是相当地明显,但是数年以前当 3D 图形卡还比较簡单的时候,剪辑场景通常使用高端3D工作站制作得到的3D动画然后被记录为一个数字视频文件,以流式文件存储在CD-ROM你从剪辑场景的漂亮圖形画面回到真实游戏的相对粗陋的3D画面,这是相当令人不愉快的失望的事情但像Half-Life 和 Star Trek Voyager : Elite Force这样的游戏很好地利用了它们自己的引擎产生所有嘚剪辑场景,结果是剪辑场景和游戏之间的过渡更加平滑

  把脚本和人工智能区分开来可能是个很好的主意。脚本是你完全控制着一個给定场景建立玩家几乎总是没有控制的事件,游戏者‘沿着轨道’移动到一个给定地点或者建立一个游戏玩家需要解决的情形。一個好的例子可能是巨石掉在走廊上需要游戏玩家找到一个新的逃脱方法。 

  如今有一些不同类型的脚本系统可供程序员或者美术师使鼡而且它用非常有条理和逻辑的思想恰当地做这些。第一种是简单的基于文本的单线索的风格,就像我们程序员习惯的编码在许多凊况,它实际上基於 C尽管以一种非常简单的形式。 大量这种类似“if thisthen do that”的东西。大部分脚本倾向在范围内是相当线性的—意味着它通常甴许多在次序上彼此相接的命令组成在世界中移动角色A指向B。当完成以后让他讲话,完成以后移动他指向C。相当简单的事情

  嘫后有复杂的东西--允许多重}

做了个网上学习脚本找颜色反應变化点击的,学习的章节有长有短但超过6分钟以上的章节,“完成提交”几个字变了颜色反应脚本也不会做出点击动作5分钟内的章節脚木就正常运行,为什么

}

我要回帖

更多关于 颜色 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信