游戏引擎剖析--概述

发表于:2007-05-05来源:作者:点击数: 标签:经常如果引擎剖析概述
如果经常关注 游戏 或者关注硬件方面的消息,经常会接触到“游戏引擎”这个名词。正如它的名字一样,它所指的是游戏的动力核心,或者或是一种游戏 开发 平台,比如最早的Doom引擎或者Quake引擎,它们自己是一款完整、独立的游戏,但是还通过游戏的扩展接口来

   如果经常关注游戏或者关注硬件方面的消息,经常会接触到“游戏引擎”这个名词。正如它的名字一样,它所指的是游戏的动力核心,或者或是一种游戏开发平台,比如最早的Doom引擎或者Quake引擎,它们自己是一款完整、独立的游戏,但是还通过游戏的扩展接口来帮助游戏玩家或者游戏开发者来改进游戏或者开发新的游戏,对于游戏开发者来说,可以在这个核心的基础上,创建新的模型、场景、声音甚至是全新的材质。我们所熟悉的游戏CounterStrike、Team Fortress、TacOps、Strike Force和Quake Soclearcase/" target="_blank" >ccer等游戏都是由专业游戏设计师或者游戏玩家在Quake、Unreal等现有引擎上开发的(TacOps和 Strike Force都使用了著名的 Unreal锦标赛的引擎),特别是Quake引擎,可以说是目前最流行的第一人称射击游戏引擎之一。

 

不过这些引擎是如何组织这些像素、如何播放声音、如何让你的敌人具有高超的AI以及如何触发游戏中的事件呢?如果你希望了解这些问题的答案,那么阅读本文可以找到答案。当然这个答案仅仅是大致的、框架上级别的,至于具体的实现当然需要专业的编程知识。我们主要根据Quake引擎来进行介绍,毕竟这款引擎的应用范围相当的广泛,比如Raven Software就在这个引擎的基础上开发了非常具有争议性的Soldier of Fortune(命运战士或者财富战士)。

游戏引擎和游戏

游戏引擎和游戏之间的关系就象一部汽车和汽车引擎之间的关系。不同型号的汽车可以采用相同的引擎,不同的游戏也可以采用相同的游戏,而且汽车的外型、材料、颜色都可以不同就象不同游戏有不同的人物模型和场景一样。整个游戏都是以游戏引擎为基础的,来控制其中各个部分的内容,比如模型、动画、声音、AI等等。

在Quake游戏中其引擎就是Quake.exe、QAGame.dll和CGame.dll,如果你不知道它们代表什么意思,不要紧,因为我们在听到专业人事解释之前也不知道。不过看完这篇文章之后应该对于这些有了一定的了解,当然这一篇文章肯定不能解决这个问题,所以我们打算写一系列的文章来解释这个问题。

渲染

首先我们从游戏开发者的角度来讨论一下游戏引擎中的渲染,让你在阅读这个系列的文章的时候对于这个问题有个大致的认识:

所以渲染究竟是什么以及为什么重要?如果在游戏中没有渲染,那么可能在显示器上看不到任何的东西,对于游戏玩家或者观察者来说渲染过程决定了显示器最后显示的图像,如果进一步讨论这个问题,可能会让一些刚刚接触这个问题的读者觉得难以理解,因为本文仅仅是概述,我们也在讨论的时候仅仅是点到即止。

构建一个游戏引擎之后,首先需要确定的就是渲染方法。不过在看不到任何图形的前提下,怎么知道你的引擎代码可以正常的工作呢?渲染过程一般要花费处理器50%的处理时间,游戏开发者会对于这个方面进行非常严格的控制,因为再好的引擎如果因为渲染算法出现错误的结果,那么需要渲染的场景或者人物就会出现非常可笑的错误,这在业界应该是非常低级的错误(当然也是比较常见的错误,只是开发者基本上在开发的过程中就基本上消除了这些错误),一款渲染结果会出现错误的有些肯定无法得到广大的玩家的承认,甚至会让一个公司就此血本无归。

我们最后在显示器看到的像素正确与否受到了多个方面因素的影响,其中包括3D加速卡、API、三维算法。不同的3D加速卡的核心是不同的,所以其内部的算法处理过程应该是不同的,一般的它们都符合一个共同的标准比如提供标准的接口来同软件进行通讯,如果做好同这些硬件之间的兼容问题是渲染过程需要主要注意问题,API也就是应用程序接口,比如我们经常提到的directX、OpenGL或者Glide都是常用的API,硬件就是通过API同一定的驱动程序配合然后支持Windows的运行等等;算法也是非常的重要,如果仅仅是按部就班的进行渲染,那么将会占用大量的处理器资源和内存带宽,任何高效的利用这个方面的资源是设计渲染算法一个非常重要的因素。

创建3D世界

最近我同一些从事计算机图形工作多年的业内人事进行过这个方面的交谈,让我对于创建一个3D计算机图形的过程有了进一步的了解。即使你平时经常的玩PC游戏、游戏主机或者街机,也不一定对于这个过程有深入的了解,因为他们看到的仅仅是最后的结果。在下面我们也将会对于创建3D世界的部分细节进行讨论:

记录一个3D对象起始就是记录一些关键点的位置(也就是我们常说的顶点Vertex),根据这些顶点计算机就可以绘制出来多个线条,然后就形成了很多的面--简化一下,可以考虑一般的包装盒,它是一个六面体,有8个点,6个面组成。可见基于顶点的数据是可以构建模型的,简单的或者复杂的。对于游戏中的场景和人物只是由更加复杂的顶点和多边形组成的而已,比如Quake中的人物模型都是由几千个顶点和几千个多边形构成。上图所示的就是构成一个3D对象的线框图,相对于构成一个盒子来说,它只是复杂了而已,基本的思路是一样的。

模型和场景如何储存仅仅是渲染器的部分功能,而渲染器也仅仅是应用程序或者游戏的部分功能。在这个过程中游戏核心并不需要知道对象如何存储在内存或者渲染过程是怎样的或者渲染器如何进行渲染。核心仅仅需要把要做的任务分配给各个渲染器就可以了,当然对于结果控制还是需要核心的检验的。

一款好的游戏引擎,它渲染器应该是可以被完全替换的。很多跨平台的游戏引擎,比如Unreal引擎可以在不同的游戏平台的运行,只要用不同的平台上的渲染器替换就可以了。其实这里渲染器的作用就是使用一定的坐标系统来定义各个点的空间位置,通过定义这些空间位置来构成组件3D对象的基本单位三角形(triangle)。当然现在的Nvidia和ATi的高端显卡还允许你利用所谓的高序表面(higher-order surface)来构成3D模型,虽然这样的方法的效率会更高但是这毕竟不是业界的标准方法,所以游戏开发商可能会对于这个方法提供支持,但是肯定还会提供基本渲染方法的支持,以保持游戏的兼容性

选择(Culling)方法

这个问题其实我们已经讨论过多次了,简单的说就是构建一个3D场景,最后我们还是通过2D的显示器来观察,这样我们只能看到位于最外层的物体。但是对于大部分显卡来说它并不管你最后会不会看见对于3D场景中的所有顶点、面都进行计算和渲染--即使我们最后看到的只是一堵墙,如果墙后面还有很多房子,计算机同样还会对于它们进行计算和渲染--显然一般是最后才判断哪些对象是可见的哪些不是可见,显然这样造成了大量的资源的浪费。为了提高系统资源利用率,把判断对象的是否可见安排在最后渲染之前就可以了,一般的我们把这个过程叫做选择(Culling),同之前的HSR(隐面消除)是一个意思。

 

如上图所示的复杂场景中,很多对象是我们看不到的,比如下面的楼层、围墙后面的对象,传统的渲染方法对于整个场景都会忠实的进行渲染。现在通过Culling功能可以不完全计算这些部分,提高显卡工作效率。

Culling的方法有很多种,在介绍这些方法之前我们首先需要对于显卡的填充率指标有所了解,现在最新的显示核心的像素填充率指标相当的高了,不过需要知道的这个数字仅仅是理论最高填充率,在实际环境中并达不到这个数字。

如果最后屏幕上显示的都是同样的材质、同样尺寸的多边形的话,显卡基本上能够达到它的理论值,但是在实际应用中,显卡并不仅仅是进行像素填充,还要进行3D变形、光照、调用材质等工作,因此达不到这个理论值也是正常的。

最简单的culling方法就是把需要处理的场景分成不同的区域,每个区域都有一个相对于其它区域的可见对象的列表。当然生成这个列表的计算方法有很多,也有多种列表格式。

其中BSP(Binary Space Partitioning,二进制空间分区)树是非常常用的一个方法,在Doom和Quake就应用到了这种方法。这种方法把需要处理的场景分成很多小的分区,然后就可以根据各个分区的关系来判断哪个是可见的哪个是不可见的。

如上图所示,A区是任何分区都遮挡不住的,所以在树型分支表中它的位于最上层
B和C区的可见程度仅仅会被A区遮挡,所以它们排列在第二层,而D、E区的可见程
度要受到其它三个分区的影响,所以位于最地层

Portal是基于专用的引擎之上的方法(在游戏届相当的知名,是3D Realms流产的项目Prey的“残留物”),在构建每个区域的时候就考虑到其是否能够被看到,然后渲染器对于每个场景进行独立的渲染。同现在的Nvdiia采用的“occlusion culling”有一个共同点就是在进行工作之前把所有的不必要的工作都删除。

基本的图像管线流程

下面介绍的处理流程比较接近于实际情况了:

 

3D Pipeline - High-Level Overview

1. Application/Scene

  • Scene/Geometry database traversal
  • Movement of objects, and aiming and movement of view camera
  • Animated movement of object models
  • Description of the contents of the 3D world
  • Object Visibility Check including possible Occlusion Culling
  • Select Level of Detail (LOD)

2. Geometry

  • Transforms (rotation, translation, scaling)
  • Transform from Model Space to World Space (Direct3D)
  • Transform from World Space to View Space
  • View Projection
  • Trivial Accept/Reject Culling
  • Back-Face Culling (can also be done later in Screen Space)
    Lighting
  • Perspective Divide - Transform to Clip Space
  • Clipping
  • Transform to Screen Space

3. Triangle Setup

  • Back-face Culling (or can be done in view space before lighting)
  • Slope/Delta Calculations
  • Scan-Line Conversion

4. Rendering / Rasterization

  • Shading
  • Texturing
  • Fog
  • Alpha Translucency Tests
  • Depth Buffering
  • Antialiasing (optional)
  • Display

通常把多边形按照所使用的材质进行排序然后把结果放入列表,然后根据材质对于这些列表进行排列。对于使用同一种材质的多边形还要根据它到摄像机的距离进行排序,最远的首先会被渲染,不过现在使用Z缓存之后这一步并不是很重要了。对于那些透明的多边形,需要在不透明的多边形渲染之后再渲染,因为它们是透明的其最终结果要根据这些透明多边形后面的多边形来确定--这是一个相当耗费资源的过程。不过好在FPS游戏场景中的透明多边形所占据的比例一般很少。

一旦应用程序(也就是游戏)把这些需要处理的场景传送给API(应用程序接口),API将会利用硬件T&L功能来处理器--现在主流的显卡都具有这个功能。这其中需要进行顶点计算、光照运算--这些计算在过去都是有CPU来完成的,现在具有硬件T&L功能的显卡都具有这个功能,这样可以让CPU做更加有价值的工作,比如提高游戏的AI等等。

Patches (Higher-Order Surfaces)

三角形渲染方法是计算机图形业界比较传统的渲染方法,显卡厂商为了进一步提高显卡的效能开始采用了 patches(面片)。 Patches (也就是 higher-order surfaces)它通过数学公司描述几何体,而不在是记录每个顶点的位置。根据这个公式可以按照对象的表面生成一个网格状的框架。这种方法相同的节约资源,因为需要传送的数据相对于需要传送各个顶点的数据少多了。 SOF2(命运战士2)就是采用了这种方法构建的地形系统。

ATI的TruForm功能就利用这个功能,但是它还是基于三角形渲染系统,中间利用 higher-order surface让需要渲染的对象更加平滑,最后再转换为更多数量的三角形模型,这种方法在渲染很多物体的时候都可以让物体更加逼真,比如渲染生物对象,像是上面的海豚、FPS游戏中的怪兽或者人,都可以让它们更加逼真,但是也会让一些有棱角的物体变得圆滑而失真。

原文转自:http://www.ltesting.net