游戏引擎:游戏引擎剖析( 2)

原文作者:Jake Simpson
译者: 向海
Email:[email protected]  


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


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

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

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

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

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

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


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

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

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

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

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


纹理和MIP映射
  纹理在使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 显卡片能执行每像素运算这种缺省观察角度不足就真不再是有力而快速法则了 无论是哪种思路方法 到目前为止没有游戏开发者太多使用; 更多游戏能够且应该使用凹凸贴图


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

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

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

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

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

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

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

  上面就是第 2 部份在下面章节中我们将介绍许多主题包括内存管理雾效果深度测试 抗锯齿顶点着色API等
Tags:  游戏搜索引擎 游戏引擎启动异常 什么是游戏引擎 游戏引擎

延伸阅读

最新评论

发表评论