原文作者:Jake Simpson
譯者: 向海
Email:GameWorldChina@myway.com  
FROM:CSDN

第1部分: 游戲引擎介紹, 渲染和構(gòu)造3D世界


介紹
  自Doom游戲時代以來我們已經(jīng)走了很遠(yuǎn)。 DOOM不只是一款偉大的游戲,它同時也開創(chuàng)了一種新的游戲編程模式: 游戲 "引擎"。 這種模塊化,可伸縮和擴(kuò)展的設(shè)計觀念可以讓游戲玩家和程序設(shè)計者深入到游戲核心,用新的模型,場景和聲音創(chuàng)造新的游戲, 或向已有的游戲素材中添加新的東西。大量的新游戲根據(jù)已經(jīng)存在的游戲引擎開發(fā)出來,而大多數(shù)都以ID公司的Quake引擎為基礎(chǔ), 這些游戲包括Counter  Strike, Team Fortress, Tac Ops, Strike Force, 以及Quake Soccer。Tac Ops 和Strike Force 都使用了Unreal Tournament 引擎。事實(shí)上, "游戲引擎" 已經(jīng)成為游戲玩家之間交流的標(biāo)準(zhǔn)用語,但是究竟引擎止于何處,而游戲又從哪里開始呢?像素的渲染,聲音的播放,怪物的思考以及游戲事件的觸發(fā),游戲中所有這一切的幕后又是什么呢? 如果你曾經(jīng)思考過這些問題, 而且想要知道更多驅(qū)動游戲進(jìn)行的東西,那么這篇文章正好可以告訴你這些。 本文分多個部分深入剖析了游戲引擎的內(nèi)核, 特別是Quake引擎,因?yàn)槲易罱ぷ鞯墓綬aven Software已經(jīng)在Quake引擎的基礎(chǔ)上開發(fā)出了多款游戲,其中包括著名的Soldier of Fortune 。  


開始
  讓我們首先來看看一個游戲引擎和游戲本身之間的主要區(qū)別。 許多人們會混淆游戲引擎和整個游戲 。這有點(diǎn)像把一個汽車發(fā)動機(jī)和整個汽車混淆起來一樣 。 你能夠從汽車?yán)锩嫒〕霭l(fā)動機(jī), 建造另外一個外殼,再使用發(fā)動機(jī)一次。 游戲也像那。 游戲引擎被定義為所有的非游戲特有的技術(shù)。 游戲部份是被稱為 '資產(chǎn)' 的所有內(nèi)容 (模型,動畫,聲音,人工智能和物理學(xué))和為了使游戲運(yùn)行或者控制如何運(yùn)行而特別需要的程序代碼, 比如說AI--人工智能。  

  對于曾經(jīng)看過 Quake 游戲結(jié)構(gòu)的人來說, 游戲引擎就是 Quake。exe ,而游戲部分則是 QAGame。dll 和 CGame。dll 。 如果你不知道這是什么意思, 也沒有什么關(guān)系;在有人向我解釋它以前, 我也不知道是什么意思。 但是你將會完全明白它的意思。 這篇游戲引擎指導(dǎo)分為十一個部份。 是的, 從數(shù)量上來說,總共是十一個部份! 每個部分大概3000字左右。現(xiàn)在就從第一部分開始我們的探索吧,深入我們所玩游戲的內(nèi)核,在這里我們將了解一些基本的東西, 為后面的章節(jié)作鋪墊。。。


渲染器
  讓我們從渲染器來開始游戲引擎設(shè)計的探討吧, 我們將從游戲開發(fā)者(本文作者的背景)的角度來探討這些問題。事實(shí)上,在本文的各個段落,我們將常常從游戲開發(fā)者的角度探討, 也讓您像我們一樣思考問題!  

  什么是渲染器,為什么它又這么重要呢?好吧,如果沒有它,你將什么也看不到。它讓游戲場景可視化,讓玩家/觀眾可以看見場景,從而讓玩家能夠根據(jù)屏幕上所看到的東西作出適當(dāng)?shù)臎Q斷。 盡管我們下面的探討可能讓新手感到有些恐懼,先別去理會它。 渲染器做些什么?為什么它是必須的?我們將會解釋這些重要問題。  

  當(dāng)構(gòu)造一個游戲引擎的時候, 你通常想做的第一件事情就是建造渲染器。 因?yàn)槿绻床灰娙魏螙|西 – 那么你又如何知道你的程序代碼在工作呢? 超過 50% 的 CPU 處理時間花費(fèi)在渲染器上面; 通常也是在這個部分,游戲開發(fā)者將會受到最苛刻的評判。 如果我們在這個部分表現(xiàn)很差,事情將會變得非常糟糕, 我們的程序技術(shù),我們的游戲和我們的公司將在 10 天之內(nèi)變成業(yè)界的笑話。 它也是我們最依賴于外部廠商和力量的地方,在這里他們將處理最大限度的潛在操作目標(biāo)。 如此說來, 建造一個渲染器確實(shí)不象聽起來那么吸引人(事實(shí)如此), 但如果沒有一個好的渲染器, 游戲或許永遠(yuǎn)不會躋身于排行榜前10 名。  

  如今,在屏幕上生成像素,涉及到 3D 加速卡, API ,三維空間數(shù)學(xué), 對 3D 硬件如何工作的理解等等。對於主機(jī)(游戲機(jī))游戲來說,也需要相同類型的知識,但是至少對于主機(jī), 你不必去嘗試擊中一個移動中的目標(biāo)。 因?yàn)橐慌_主機(jī)的硬件配置是固定的 "時間快照", 和PC(個人計算機(jī))不同, 在一臺主機(jī)的生命期中,它的硬件配置不會改變。  

  在一般意義上,渲染器的工作就是要創(chuàng)造出游戲的視覺閃光點(diǎn),實(shí)際上達(dá)到這個目標(biāo)需要大量的技巧。3D圖形本質(zhì)上是用最少的努力創(chuàng)造出最大效果的一門藝術(shù), 因?yàn)轭~外的 3D 處理在處理器時間和和內(nèi)存帶寬方面都是極為昂貴的。 它也是一種預(yù)算, 要弄清楚你想在什么地方花費(fèi)處理器時間,而你寧愿在什么地方節(jié)省一些從而達(dá)到最好的整體效果。 接下來我們將會介紹一些這方面的工具,以及怎樣更好的用它們讓游戲引擎工作。


建造3D世界
  最近,當(dāng)我和一位從事計算機(jī)圖形方面工作長達(dá)數(shù)年之久的人會談時,她向我吐露道, 當(dāng)她第一次看到實(shí)時操縱計算機(jī) 3D 圖象時, 她不知道這是怎么實(shí)現(xiàn)的, 也不知道計算機(jī)如何能夠存儲 3D 圖象。 今天這對于在大街上的普通人來說或許是真實(shí)的,即使他們時常玩 PC 游戲, 游戲機(jī)游戲, 或街機(jī)游戲。

  下面我們將從游戲設(shè)計者的角度討論創(chuàng)造 3D 世界的一些細(xì)節(jié),你也應(yīng)該看一看 Dave Salvator 所寫的“3D 管線導(dǎo)論“,以便對3D 圖象生成的主要過程有一個整體的了解。

  3D 物體(對象)被儲存成 3D 世界中的一系列點(diǎn)(被稱為頂點(diǎn)), 彼此之間有相互關(guān)系,所以計算機(jī)知道如何在世界中的這些點(diǎn)之間畫線或者是填充表面。 一個立方體由8個點(diǎn)組成,每個角一個點(diǎn)。立方體有6個表面, 分別代表它的每一個面。 這就是 3D 對象儲存的基礎(chǔ)。 對于一些比較復(fù)雜的 3D 物體, 比如說一個 Quake 的關(guān)卡,將有數(shù)以千計(有時數(shù)以十萬計)的頂點(diǎn), 和數(shù)以千計的多邊形表面。  

  參見上圖的線框表示(注:原文在這里有一幅圖)。 本質(zhì)上與上面的立方體例子類似, 它僅僅是由許許多多的小多邊形組成的一些復(fù)雜場景。模型和世界如何儲存是渲染器的一部份功能, 而不屬于應(yīng)用程序/游戲部份。 游戲邏輯不需要知道對象在內(nèi)存中如何表示, 也不需要知道渲染器將怎樣把他們顯示出來。 游戲只是需要知道渲染器將使用正確的視野去表示對象, 并將在正確的動畫幀中把正確的模型顯示出來。

  在一個好的引擎中,渲染器應(yīng)該是可以完全被一個新的渲染器替換掉, 并且不需要去改動游戲的一行代碼。許多跨平臺引擎, 而且許多自行開發(fā)的游戲機(jī)引擎就是這樣的,如 Unreal 引擎, --舉例來說, 這個游戲 GameCube 版本的渲染器就可以被你任意的替換掉。  

  讓我們再看看內(nèi)部的表示方法—除了使用坐標(biāo)系統(tǒng),還有其他方法可以在計算機(jī)內(nèi)存里表示空間的點(diǎn)。在數(shù)學(xué)上,你可以使用一個方程式來描述直線或曲線, 并得到多邊形, 而幾乎所有的 3D 顯示卡都使用多邊形來作為它們的最終渲染圖元。 一個圖元就是你在任何顯示卡上面所能使用的最低級的繪制(渲染)單位,幾乎所有的硬件都是使用三個頂點(diǎn)的多邊形(三角形)。 新一代的 nVidia 和 ATI 顯卡可以允許你以數(shù)學(xué)方式渲染(被稱為高次表面), 但因?yàn)檫@不是所有圖形卡的標(biāo)準(zhǔn), 你還不能靠它作為渲染策略。

  從計算的角度來看,這通常有些昂貴,但它時常是新的實(shí)驗(yàn)技術(shù)的基礎(chǔ),例如,地表的渲染,或者對物件銳利的邊緣進(jìn)行柔化。 我們將會在下面的曲面片小節(jié)中更進(jìn)一步介紹這些高次表面。


剔除概觀
  問題來了。 我現(xiàn)在有一個由幾十萬個頂點(diǎn)/多邊形描述的世界。 我以第一人稱視角位于我們這個 3D 世界的一邊。 在視野中可以看見世界的一些多邊形, 而另外一些則不可見, 因?yàn)橐恍┪矬w, 比如一面看得見的墻壁, 遮擋住了它們。 即使是最好的游戲編碼人員, 在目前的 3D 顯卡上, 在一個視野中也不能處理 300,000個三角形且仍然維持 60fps (一個主要目標(biāo))。 顯卡不能處理它, 因此我們必須寫一些代碼,在把它們交給顯卡處理之前除去那些看不見的多邊形。 這個過程被稱為剔除。

  有許多不同的剔除方法。 在深入了解這些之前,讓我們探討一下為什么圖形顯示卡不能處理超高數(shù)量的多邊形。 我是說,最新的圖形卡每秒鐘不能處理幾百萬個多邊形嗎?它不應(yīng)該能夠處理嗎? 首先,你必須理解市場銷售宣稱的多邊形生成率和真實(shí)世界的多邊形生成率。 行銷上宣稱的多邊形生成率是圖形顯示卡理論上能夠達(dá)到的多邊形生成率。  

  如果全部多邊形都在屏幕上, 相同的紋理,相同的尺寸大小, 正在往顯示卡上傳送多邊形的應(yīng)用程序除了傳送多邊形以外什么也不做, 這時顯卡能處理多少多邊形數(shù)量, 就是圖形芯片廠商呈現(xiàn)給你的數(shù)字。  

  然而,在真實(shí)的游戲情形中,應(yīng)用程序時常在后臺做著許多其他的事情 -- 多邊形的 3D 變換, 光照計算, 拷貝較多的紋理到顯卡內(nèi)存, 等等。 不僅紋理要送到顯示卡, 而且還有每個多邊形的細(xì)節(jié)。一些比較新的顯卡允許你實(shí)際上在顯卡內(nèi)存本身里面儲存模型/世界幾何細(xì)節(jié), 但這可能是昂貴的,將會耗光紋理正常可以使用的空間,所以你最好能確定每一幀都在使用這些模型的頂點(diǎn), 否則你只是在浪費(fèi)顯示卡上的存儲空間。 我們就說到這里了。 重要的是,在實(shí)際使用顯卡時,并不必然就能達(dá)到你在顯卡包裝盒上所看到的那些指標(biāo),如果你有一個比較慢速的CPU , 或沒有足夠的內(nèi)存時,這種差異就尤為真實(shí)。


基本的剔除方法
  最簡單的剔除方式就是把世界分成區(qū)域, 每個區(qū)域有一個其他可見區(qū)域的列表。 那樣, 你只需要顯示針對任何給定點(diǎn)的可見部分。 如何生成可見視野區(qū)域的列表是技巧所在。 再者, 有許多方法可以用來生成可見區(qū)域列表, 如 BSP 樹, 窺孔等等。  

  可以肯定,當(dāng)談?wù)?DOOM 或 QUAKE 時,你已經(jīng)聽到過使用 BSP 這個術(shù)語了。 它表示二叉空間分割。  

  BSP 是一種將世界分成小區(qū)域的的方法,通過組織世界的多邊形,容易確定哪些區(qū)域是可見的而哪些是不可見的 – 從而方便了那些不想做太多繪制工作的基于軟件的渲染器。它同時也以一種非常有效的方式讓你知道你位于世界中的什么地方。  

  在基于窺孔的引擎 ( 最早由 3D Realms 已經(jīng)取消的 Prey 項(xiàng)目引入游戲世界 )里,每個區(qū)域 ( 或房間) 都建造有自己的模型, 通過每個區(qū)域的門 ( 或窺孔 )能夠看見另外的區(qū)段。 渲染器把每個區(qū)域作為獨(dú)立的場景單獨(dú)繪制。 這就是它的大致原理。 足以說這是任何一個渲染器的必需部份,而且非常重要。  

  盡管一些這樣的技術(shù)歸類在 "遮擋剔除"之下,但是他們?nèi)慷加型瑯拥哪康? 盡早消除不必要的工作。 對於一個FPS游戲(第一人稱射擊游戲) 來說,視野中時常有許多三角形,而且游戲玩家承擔(dān)視野的控制,丟棄或者剔除不可見的三角形就是絕對必要的了。 對空間模擬來說也是這樣的, 你可以看見很遠(yuǎn)很遠(yuǎn)的地方 – 剔除超過視覺范圍外面的東西就非常重要。 對于視野受到限制的游戲來說 – 比如 RTS (即時戰(zhàn)略類游戲)--通常比較容易實(shí)現(xiàn)。 通常渲染器的這個部份還是由軟件來完成, 而不是由顯卡完成, 由顯卡來做這部分工作只是一個時間問題。


基本的圖形管線流程
  一個簡單的例子,從游戲到多邊形繪制的圖形管線過程大致是這樣:
    · 游戲決定在游戲中有哪些對象, 它們的模型, 使用的紋理, 他們可能在什么動畫幀,以及它們在游戲世界里的位置。 游戲也決定照相機(jī)的位置和方向。

    · 游戲把這些信息傳遞給渲染器。以模型為例 ,渲染器首先要查看模型的大小 ,照相機(jī)的位置, 然後決定模型在屏幕上是否全部可見, 或者在觀察者 (照相機(jī)視野) 的左邊,在觀察者的后面,或距離很遠(yuǎn)而不可見。它甚至?xí)褂靡恍┦澜鐪y定方式來計算出模型是否是可見的。 (參見下面這條)

    · 世界可視化系統(tǒng)決定照相機(jī)在世界中的位置,并根據(jù)照相機(jī)視野決定世界的哪些區(qū)域 / 多邊形是可見的。有許多方法可以完成這個任務(wù), 包括把世界分割成許多區(qū)域的暴力方法,每個區(qū)域直接為"我能從區(qū)域 D 看見區(qū)域 AB & C", 到更精致的 BSP(二叉空間分割)世界。 所有通過這些剔除測試的多邊形被傳遞給多邊形渲染器進(jìn)行繪制。  

    · 對於每一個被傳遞給渲染器的多邊形, 渲染器依照局部數(shù)學(xué) ( 也就是模型動畫) 和世界數(shù)學(xué)(相對于照相機(jī)的位置?)對多邊形進(jìn)行變換,并檢查決定多邊形是不是背對相機(jī) (也就是遠(yuǎn)離照相機(jī))。背面的多邊形被丟棄。 非背面的多邊形由渲染器根據(jù)發(fā)現(xiàn)的附近燈光照亮。然后渲染器要看多邊形使用的紋理,并且確定 API/ 圖形卡正在使用那種紋理作為它的渲染基礎(chǔ)。 在這里,多邊形被送到渲染 API,然后再送給顯卡。  

  很明顯這有些過分簡單化了,但你大概理解了。 下面的圖表摘自Dave Salvator's 3D 管線一文,可以給你多一些具體細(xì)節(jié):  

  3D 管線
  - 高層的概觀
   1. 應(yīng)用程序/ 場景
  ·場景/ 幾何數(shù)據(jù)庫遍歷
  ·對象的運(yùn)動,觀察相機(jī)的運(yùn)動和瞄準(zhǔn)
  ·對象模型的動畫運(yùn)動
  ·3D 世界內(nèi)容的描述
  ·對象的可見性檢查,包括可能的遮擋剔除
  ·細(xì)節(jié)層次的選擇 (LOD)

  2. 幾何
  ·變換 (旋轉(zhuǎn),平移, 縮放)
  ·從模型空間到世界空間的變換 (Direct3D)
  ·從世界空間到觀察空間變換
  ·觀察投影
  ·細(xì)節(jié)接受/ 拒絕 剔除
  ·背面剔除 (也可以在后面的屏幕空間中做)
  光照
  ·透視分割 - 變換到裁剪空間
  ·裁剪
  ·變換到屏幕空間

  3. 三角形生成
  ·背面剔除 ( 或者在光照計算之前的觀察空間中完成)
  ·斜率/ 角度計算
  ·掃瞄線變換

  4. 渲染 / 光柵化
  ·著色
  ·紋理
  ·霧
  ·Alpha 透明測試
  ·深度緩沖
  ·抗鋸齒 (可選擇的)
  ·顯示

  通常你會把所有的多邊形放到一些列表內(nèi), 然後根據(jù)紋理對這個列表排序(這樣你只需要對顯卡傳送一次紋理, 而不是每個多邊形都傳送一次), 等等。在過去,會把多邊形按照它們到相機(jī)的距離進(jìn)行排序,首先繪制那些距離相機(jī)最遠(yuǎn)的多邊形, 但現(xiàn)在由于 Z 緩沖的出現(xiàn),這種方法就不是那么重要了。 當(dāng)然那些透明的多邊形要除外,它們要在所有的非半透明多邊形繪制之后才能夠繪制 ,這樣一來,所有在它們后面的多邊形就能正確地在場景中顯現(xiàn)出來。 當(dāng)然,象那樣,實(shí)際上你必須得從后到前地繪制那些多邊形。 但時常在任何給定的 FPS 游戲場景中, 通常沒有太多透明的多邊形。 它可能看起來像有,但實(shí)際上與那些不透明的多邊形相比,其比率是相當(dāng)?shù)偷摹?nbsp; 

  一旦應(yīng)用程序?qū)鼍皞鬟f到 API, API 就能利用硬件加速的變換和光照處理 (T&L), 這在如今的 3D 顯卡中是很平常的事情。 這里不討論涉及到的矩陣數(shù)學(xué)(參見Dave的 3D 管線導(dǎo)論),幾何變換允許 3D 顯卡按照你的嘗試,根據(jù)相機(jī)在任何時間的位置和方向,在世界的正確角度和位置繪制多邊形。  

  對于每個點(diǎn)或頂點(diǎn)都有大量的計算, 包括裁剪運(yùn)算,決定任何給定的多邊形實(shí)際上是否可見,在屏幕上完全不可見或部分可見。 光照運(yùn)算,計算紋理色彩明亮程度,這取決于世界的燈光從什么角度如何投射到頂點(diǎn)上。 過去,處理器處理這些計算,但現(xiàn)在,當(dāng)代圖形硬件就能為你做這些事情, 這意謂著你的處理器可以去做其他的事情了。很明顯這是件好事情 (tm) ,由于不能指望市面上所有的 3D 顯卡板上都有T & L, 所以無論如何你自己將必須寫所有的這些例程 (再一次從游戲開發(fā)者角度來說)。 你將在本文各處的不同段落看到 "好事情 ( tm)" 這個詞匯。 我認(rèn)為,這些特征為使游戲看起來更好作出了非常有用的貢獻(xiàn)。 毫不令人吃驚,你也將會看見它的對立面;你猜到了,那就是“壞事情 (tm)”。 我正在嘗試爭取這些詞匯的版權(quán), 你要使用他們就得支付一筆小小的費(fèi)用喲。


曲面片(高次表面)
  除了三角形,曲面片的使用現(xiàn)在正變得更普遍。 因?yàn)樗麄兡苡脭?shù)學(xué)表達(dá)式來描述幾何 ( 通常涉及某種曲線的幾何形體) ,而不僅僅只是列出大量的多邊形以及在游戲世界中的位置, 所以曲面片 ( 高次表面的另一個名稱) 非常好。 這樣,你實(shí)際上就能夠動態(tài)地根據(jù)方程式來建立( 和變形 )多邊形網(wǎng)格, 并決定你實(shí)際想要從曲面片上看到的多邊形數(shù)量。 因此,舉例來說,你可以描述一個管道, 然后在世界中就可以有這種管道的許多樣例。 在一些房間中, 你已經(jīng)顯示了 10,000個多邊形,你可以說,"因?yàn)槲覀円呀?jīng)顯示了大量的多邊形,而且任何更多的多邊形將會使幀速率下降, 所以這個管道應(yīng)該只有 100 個多邊形"。 但在另外一個房間中, 視野中只有 5,000個可見的多邊形,你可以說,"因?yàn)槲覀冞€沒有達(dá)到預(yù)算可以顯示的多邊形數(shù)量 , 所以,現(xiàn)在這個管道能有 500 個多邊形"。 非常美妙的東西 --但你必須首先知道所有這些,并建立網(wǎng)格,這不是無足輕重的。 通過 AGP 傳送同一個對象的曲面方程確實(shí)要比傳送其大量頂點(diǎn)節(jié)省成本。 SOF2 就使用了這個方法的一種變體來建立它的地表系統(tǒng)。

  事實(shí)上現(xiàn)在的 ATI 顯卡具有 TruForm, 它能帶一個以三角形為基礎(chǔ)的模型,并將該模型轉(zhuǎn)換為基于高次表面的模型,使其平滑 — 接著再用十倍三角形數(shù)量把模型轉(zhuǎn)換回基于大量三角形的模型 (被稱為retesselation)。然后模型送往管線做進(jìn)一步的處理。 實(shí)際上 ATI 僅僅在 T & L 引擎之前增加了一個階段來處理這個過程。這里的缺點(diǎn)是,要控制哪些模型需要被平滑處理而哪些又不需要。你常常想要一些邊緣比較尖銳, 比如鼻子,但它卻被不恰當(dāng)?shù)钠交^了。 這仍然是一種很好的技術(shù),而且我能預(yù)見它在將來會被更多的應(yīng)用。  

  這就是第一部份 -- 我們將會在第二部分繼續(xù)介紹光照和紋理,下面的章節(jié)會更加深入。