第一章 DirectX 计算机图形学(上)
計算機圖形學是一種使用數學算法將二維或三維圖形轉化為計算機顯示器的柵格形式(像素單位)的科學。計算機圖形學的研究對象是圖形(3D模型),我們需要使用這些圖形來模擬現實世界的物體。構成圖形的要素有兩類,一是形狀的點線面等幾何要素,二是反映物體表面的屬性,如顏色等非幾何要素。在計算機中表示圖形的方法通常有三種:線框,表面和實體。線框模型采用點和線的集合來描述三維圖形。線框模型的優點就是結構簡單,缺點不能表示物體的表面。表面模型在線框模型的基礎上,增加了物體面的信息,用面的集合來表示三維圖形。表面模型又分為平面模型和曲面模型。表面模型也存在一些不足,它只能表示物體的表面特征,而不能展示物體的內部屬性。因此,一個用表面模型表示的三維圖形只是一個空殼。實體模型則是在表面模型的基礎上記錄了物體的拓撲信息。
當前游戲行業廣泛使用平面模型(三角面網格/四角面網格)來表示三維圖形(3D模型)。三角面網格可以采用足夠多的表面去逼近復雜的曲面。在三維空間里,一個三角面由三個不同位置的點構成的。每一個點都有自己的X、Y、Z坐標。兩個點連接起來,構成一條線,三個點兩兩相連,就構成了一個三角面。大量的三角面共用頂點和邊線,就構成了一個三維網格模型。從存儲的角度看,三角面網格模型只是由一個個頂點組成,既沒有“面”,也沒有“體”。因為平面可以由三個頂點來確定,體積可以由閉合的面確定,不用額外存儲信息,以此達到最小化存儲的目的。所以三維模型看上去是由若干個三角面組成,實際存儲時都是一些頂點而已,這些頂點包含了重要幾何信息(位置坐標),還有其他非幾何信息(顏色)。
?
坐標系是為了定量描述物體的位置變化。例如,經緯度是我們經常使用的地理坐標系統,它是一種利用三度空間的球面來定義地球上的空間的球面坐標系統,能夠標示地球上的任何一個位置。我們使用GPS定位出來的就是經緯度。在2D和3D的游戲世界中,坐標系就是用來確定所有物體的位置變化。2D空間就是一個矩形平面,例如我們的電腦和手機屏幕,它只有寬度和高度。在2D下,采用的是笛卡爾坐標系,即x軸為水平方向,向右為正。y軸為垂直x軸,向上為正。原點位于坐標值為(x=0,y=0)處。在笛卡爾坐標系中,每一個點都可以有一個準確的x,y值來表示其位置。而3D比2D多一個深度,笛卡爾坐標系多了一個z軸,z軸同時垂直于x軸和y軸,向外為正。我們可以理解垂直于我們的電腦和手機屏幕向里/向外的方向就是z軸,但是它并不存在的,我們的電腦和手機屏幕仍然是一個2D空間。那么,如何將3D空間下的模型顯示到2D平面上呢?想要在計算機屏幕上輸出三維場景就要通過投影變換來降低維數。投影就是從投影中心(視點)發出射線,穿過三維物體上的每一點后,與投影平面相交所形成的交點集合,因此把三維坐標轉變為二維坐標的過程稱之為投影變換。這個就類似于我們在燈光下玩手影是一個道理,我們使用手來模擬物體的3D形狀,但是通過燈光投影后,在墻上呈現的則是一個2D形狀。投影可分為平行投影和透視投影。透視投影的特點是所有投影線都是從空間一點(視點)投射,距離視點近的物體投影大些,距離視點遠的物體投影小些。透視投影模擬了人眼觀察物體的過程,符合人類視覺習慣。3D游戲使用的就是透視投影(透視攝像機)。而平行投影則不會產生近大遠小的效果,應為平行投影的投影線是一個與投影平面一樣大的矩形平面,也就是說平行投影的形狀是一個立方體,從一個面投影到對立的另一面上,這樣不管物體在立方體那個位置,它在投影面上的成像都是固定不變的大小。因此2D游戲經常使用平行投影(正交攝像機)。關于透視攝像機和正交攝像機,我們后續會繼續詳細介紹。
投影變換
這里我們著重講解一些3D投影,首先我們要清楚的是,3D游戲中存在以下幾種坐標系,物體在不同坐標系之間呈現的時候,需要通過矩陣進行變換。請注意,這種轉換并不是說物體的位置真實發生了改變,而是對應的參照物改變了,因此位置也就相對改變了。
本地坐標系,也稱之為局部坐標系。我們使用三角面表示三維模型,存儲的三維模型的頂點中包含了坐標信息。這個坐標信息實際就是本地坐標系,它的坐標原點在三維模型的某一個位置(可以認為物體的中心)。所有的頂點坐標信息都是基于這個原點做參照。
世界坐標系,就是游戲世界坐標系。所有的三維模型都要在游戲世界擁有自己的位置坐標,這個坐標就是基于世界坐標系原點做參照。將三維模型放置到游戲世界某一個位置的過程,就是將三維模型中頂點的本地坐標轉換成世界坐標的過程。這種坐標系轉換是通過變換矩陣實現的。矩陣(Matrix)是一個按照長方陣列排列的數字集合,屬于高等代數學。我們可以簡單的理解一個M x N維的矩陣就是一個m行和n列的二維數字數組。三維模型變換矩陣是一個4 x 4方陣。三維模型變換過程就是表示三維模型頂點集合的規范化齊次坐標矩陣與某一個變換矩陣相乘,它的本質就是三維模型的頂點從一個位置變換到另一個位置。三維模型變換分為平移變換,縮放變換和旋轉變換,因此也就對應了平移變換矩陣,縮放變換矩陣和旋轉變換矩陣三種類型。三維模型的動畫也都是通過這三種變換矩陣來實現的。
觀察者坐標系,也可以理解為攝像機坐標系,或者視圖坐標系。我們看到的游戲世界的三維模型,都是通過攝像機采集的,就如同我們自己的眼睛看到這個世界是一樣的。攝像機的移動會影響到我們看到游戲世界的內容,也就是說世界空間中的所有三維模型物體都跟隨著攝像機一同進行變換。這種變換稱之為取景變換(也叫視角變換),就是將三維模型的世界坐標轉換成觀察者的坐標。觀察者坐標系的原點就是攝像機的位置。這個過程需要一個取景變換矩陣(視圖矩陣)來完成。
在觀察者坐標系中,我們的最終任務是要獲取3D場景的2D表示,也就是我們上文提到的透視投影。投影中心(視點)就是攝像機,投影平面也稱之為投影窗口(正方形平面)。透視投影是按照三維模型近大遠小的原則進行投影,距離攝像機近的就大一些,距離攝像機遠的就小一些。透視投影中有一個視域體的概念,也稱之為平截臺體,它就是一個由視點連接投影窗口(正方形平面)形成的一個正四棱錐。在正四棱錐內的三維模型物體將會投影到投影窗口中。這個過程需要一個投影變換矩陣來完成。投影變換矩陣就是將三維模型的觀察者坐標轉換為二維平面坐標。在這個過程中丟失z方向的坐標信息會以另一種方式保存。
視口坐標系,就是屏幕上的游戲窗口,它的原點在游戲窗口右上角。視口變換就是將投影窗口(二維平面)的物體坐標轉換到屏幕上的一塊矩形坐標區域中,本質是一個放縮+平移的過程(2D變換2D過程),這個過程需要視口變換矩陣來完成。
備注:以上所有變換矩陣的數學推導過程都不需要大家理解,在實際開發過程中,我們都可以通過API中方法創建矩陣并對模型進行變換,這些方法的參數基本都是符合人性思維的。例如平移變換的話,只需要給出目標坐標值,就能創建平移矩陣并對模型進行平移變換。在比如取景變換,只需要給出攝像機的位置以及觀察點即可,投影變換矩陣則是通過弧度和遠近面來定義視域體(正四棱錐)即可,都非常的容易理解。
光照和材質
在計算機圖形學當中,我們的最終目的就是在屏幕上繪制圖像,而這些圖像的表示方式就是顏色。我們的電腦屏幕和手機屏幕都是由像素點組成的,像素點越多,屏幕顯示越清晰。每個像素點的顏色在計算機中一般使用RGB來表示,也就是說顏色由紅色(Red),綠色(Green)和藍色(Blue)組成。這三個分量的混合決定了最終的顏色。在三維模型的頂點中就有顏色屬性的存儲,我們就可以使用RGB來定義頂點的顏色值。但是,這種簡單的表達方式并不能模擬繪制出現實世界豐富多彩的顏色。我們知道在自然界中,物體的顏色是靠它所反射的太陽光的顏色決定的,比如,某物體大量反射光線中的紅色部分,那么我們看到的這個物體就呈現紅色。因此,我們需要盡可能的模擬這種物理現象,才能繪制出接近現實世界的圖像。真實感圖形繪制是計算機圖形學的一個重要組成部分,它綜合利用數學、物理等知識在計算機圖形設備上生成像彩色照片那樣的具有真實感的圖形。
為了能夠真實模擬物體的表面細節,我們需要在游戲世界里創建光源,物體根據自身的材質和紋理圖案來確定最終的顯示效果。我們首先說一下光源,光源的本質就是顏色。光源由Ambient color(環境色),Diffuse color(漫反色),以及Specular color(高光色)三種顏色所組成。也就是說,我們定義一個光源的時候,需要指定三種類型的顏色值。這三種顏色的光對應物體的影響效果是不一樣的。計算機中的光源就是根據光在物體上的反射效果而定義。
漫反射(Diffuse Light)表示光源在物體表面的反射光中那些向空間各方向均勻反射出去的光,這些光常稱為漫反射光。我們所說的物體顏色基本上指的就是漫反射產生的的顏色。
如果光朝一特定方向進行反射的話,那么這個區域就會非常的亮,這也是我們物理學上的鏡面反射。例如,光照射一個光滑的金屬球時會在球面上形成一塊特別亮的區域,也就是高光效果。這種效果則是由高光色(Specular Light)來決定的。對于較光滑物體,其鏡面反射光的高光區域小而亮;相反,粗糙表面的鏡面反射光呈發散狀態,其高光區域大而不亮。
一般情況,光的反射不會發生一次。例如,一束光可以通過一面鏡子反射照亮其他的物體。也就是說,物體除了受到光源的直接影響之外,還會受到從周圍環境來的反射光(例如來自地面、天空、墻壁等的反射光)的間接影響,這些光常統稱為環境光(Ambient Light)。
當有了光照,還有另一個決定物體顏色的重要因素——材質。每一個物體都有它獨特的材質,比如說,光滑的玻璃,粗糙的木頭,堅硬的巖石等。這些物體通過發射不同的光來呈現不同的表面效果。我們在定義光源的時候,通過三種反射效果的顏色來構造光。同樣的,材質也分成環境光反射、漫反射和高光反射三個部分。在進行光照計算時,物體對環境光的反射率與光源的環境光結合,對漫反射光的反射率與光源的漫反射光結合,對鏡面光的反射率與光源的鏡面反射光結合。材質的顏色與光源的顏色是一一對應關系。
對于光源,R、G、B值等于R、G、B對其最大強度的百分比。若光源顏色的R、G、B值都是1.0,則是最強的白光;若值變為0.5,顏色仍為白色,但強度為原來的一半,于是表現為灰色;若R=1.0,G=0.0,B=0.0,則光源為紅色。我們就是使用這種方式,分別使用三組RGB值來定義漫反射光,高光和環境光。
對于材質,R、G、B值為材質對光的R、G、B成分的反射率。比如,一種材質的R=1.0,G=0.5,B=0.0,則材質反射全部的紅色,一半的綠色,不反射藍色。同理,我們使用這種方式,分別使用三組RGB值來定義漫反射光的反射,高光反射和環境光發射。
光照模型就是一個計算公式,若光源顏色為(LR, LG, LB),材質顏色為(MR, MG, MB),那么,最終到達眼睛的光的顏色為(LR*MR, LG*MG, LB*MB)。當然,這個公式并不是這么簡單。一般情況下,影響物體最終顏色的首先就是漫反射光,其次是環境光,高光只會影響物體產生的亮點。需要注意的是,光照模型在游戲運行中的性能開銷非常大。
紋理映射
物體表面細節分為兩類:1.表面的顏色紋理,顏色紋理取決于物體表面的光學屬性(反色率)2.表面的幾何紋理,幾何紋理由物體表面的微觀幾何形狀決定(凹凸)。僅僅使用上述的光照模型我們很難去繪制出現實世界物體的微觀細節。紋理貼圖(紋理映射)在計算機圖形學中就是把一張2D圖像包裹到3D物體的表面。紋理貼圖給物體提供了豐富的細節,用簡單的方式模擬出了復雜的外觀。這個包裹的過程就是映射的過程。比如繪制一面磚墻,就可以用一幅真實的磚墻圖像作為紋理貼到一個矩形上,就繪制成了一個磚墻的圖形。這里,我們只需要了解這個映射的原理是什么。首先紋理貼圖是一個正方形(大部分情況),在紋理貼圖的2維坐標系中,左上角是原點(0,0)位置,右下角是(1.0, 1.0)位置。紋理中每一個像素點都有一個紋理坐標(UV坐標)。在三維模型的頂點中同樣對應著一個屬性,就是UV坐標值,也就是說我們可以將三維模型上的每一個頂點都對應上紋理貼圖上的一個點,這樣紋理貼圖就會按照這種映射關系被附屬在三維模型上面了。紋理貼圖映射其實就是使用圖像來表現物體的顏色,當然最終呈現的色彩還要考慮到光照模型。
紋理映射技術使用非常的廣泛,有時候我們可以將光源信息存儲到紋理貼圖中,這種紋理貼圖稱之為“光照貼圖”。我們將光照貼圖和物體的紋理貼圖同時施加到物體表面,就能讓物體在沒有光源的情況下展示出有光源照射的相同效果。我們講過,光照模型在游戲運行中的性能開銷非常大,而這種“光照貼圖”則是一種比較折中的解決方案。除了“光照貼圖”之外,還有類似于“凹凸貼圖”,“高光貼圖”等等,實現不同的視覺效果。
游戲動畫
傳統的動畫,一般是對一個物體對象進行位移、旋轉、縮放,然后把動作以關鍵幀的數據形式記錄下來,在播放的時候按照關鍵幀時間對物體對象進行位移、旋轉、縮放,并在關鍵幀與關鍵幀之間做插值運算,最終形成一套連續的完整的動作動畫。動畫就是把每幀的頂點數據輸出到文件中,所以3D模型的一個動作就是一系列的模型。這樣做的雖然簡單,但是會因為產生大量的動畫文件。后來人們根據人體動作的原理創建了骨骼動畫。骨架由一系列具有層次關系的關節(骨骼)組成,是一種樹結構,該結構中存在一個是根關節,其它關節是根關節的子孫。父關節運動能影響子關節運動,但子關節運動對父關節不產生影響。這個其實就是模擬我們人體骨骼的運動,所以這種動畫稱之為骨骼動畫。骨骼的本質是什么?它就是變換矩陣。我們之前講過模型的平移,旋轉和縮放變換,這些都是通過矩陣來實現的。動畫的形成也就是通過對模型的其中一部分進行平移,旋轉和縮放變換。
骨架被外部皮膚包圍,皮膚由多邊形(頂點)構成。骨架中的每一根骨骼都會影響皮膚的形狀和位置。而皮膚則可以由多個骨骼共同影響,只是影響的權值是不一樣的。當移動骨骼時,會將骨骼的變換矩陣施加給與骨骼綁定的皮膚頂點,皮膚頂點的改動就更改模型的幾何形狀,從而顯示出動畫效果。皮膚其實就是存儲頂點的同時,還是存儲了影響它的骨骼。
骨骼動畫的特點是,需要做動畫的物體對象本身不記錄位移、旋轉、縮放信息,而是通過“骨骼”記錄動畫信息(按照時間記錄骨骼變換矩陣),然后物體對象本身只記錄受到骨骼物體影響的權重(皮膚)。在播放的時候,通過骨骼物體的關鍵幀和物體對象記錄的權重,讓動畫重現。也就是說,一個帶骨骼動畫的模型需要包含三部分信息:骨架,皮膚和幀動畫。骨架就是一個骨骼層次結構,例如一個人體骨骼結構可能包括頭骨骼,胸骨骼,上臂骨骼,下臂骨骼,大腿骨骼,小腿骨骼等等。皮膚則是模型的頂點信息和影響該頂點的骨骼信息。幀動畫就是按照時間來記錄骨架中各個骨骼的變換矩陣。在三維模型當中。bone就是骨骼,皮膚就是skin mesh,也叫蒙皮網格。骨骼動畫都是在3ds max或者maya中完成的,我們只需要根據圖形API進行文件解析,并播放對應的動畫即可。
游戲API和引擎
目前游戲領域有兩個圖形API,一個是OpenGL,一個是DirectX。前者是一項開源的標準,主要用于圖形應用和3D游戲。DirectX則是微軟制定的API標準。由于OpenGL跨平臺和免費性,得到很多顯卡制造商的支持。在端游開發方面,DirectX占據絕對的優勢。但是隨著移動互聯網的發展,OpenGL則是Android和ios的首選。但是OpenGL只是圖形函數庫,不能用于輸入,聲音,網絡的開發,需要借助第三方來完成。DirectX并不是一個單純的圖形API,它是由微軟公司開發的用途廣泛的API,它包含有Direct Graphics、Direct Input、Direct Play、Direct Sound、Direct Show等多個組件,它提供了一整套的多媒體接口方案。
2002年,微軟發布DirectX9.0(DirectX 9.0b和DirectX 9.0c)。這是DirectX發展歷程中的重要轉折點。2006年,微軟發布Windows Vista操作系統,內置了DirectX 10。2009年,微軟發布Windows 7操作系統,內置了DirectX 11。2014年,微軟發布了最新的DirectX 12。
從技術層面講,游戲產品本質上是一種以游戲引擎技術為核心的模擬仿真軟件。3D游戲引擎的架構設計非常復雜,設計到很多系統協調工作才能使用戶獲得最佳的交互控制和感官體驗。這些系統包括圖形渲染系統,資源管理系統,音視頻系統,物理模擬系統,網絡通信系統,腳本系統和人工智能系統等等。此外,游戲引擎還需要為策劃和美工等非編程人員提供輔助工具,包括地圖編輯器,關卡編輯器,腳本編輯器,特效編輯器等等。
Unity 3D引擎和 Unreal Engine(虛幻引擎)是當前最為流行的游戲引擎。Cocos引擎也是一款非常流行的國產游戲引擎。當然還有一些開源的游戲引擎,比如OGRE引擎,Cryengine引擎。很多大的公司都有自己的游戲引擎,但基本上都是自己公司使用,不對外開放的。我們的游戲開發課程主要是Unity 3D引擎的學習,以及使用Unity 3D來開發游戲項目。Unreal Engine引擎會在后期中介紹。個人認為,Unreal Engine才是最棒的游戲引擎,值得學習!
?本課程的所有代碼案例下載地址:
workspace.zip
備注:這是我們游戲開發系列教程的第二個課程,這個課程主要使用C++語言和DirectX來講解游戲開發中的一些基礎理論知識。學習目標主要依理解理論知識為主,附帶的C++代碼能夠看懂且運行成功即可,不要求我們使用DirectX來開發游戲。課程中如果有一些錯誤的地方,請大家留言指正,感激不盡!
總結
以上是生活随笔為你收集整理的第一章 DirectX 计算机图形学(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: D. Binary Spiders(思维
- 下一篇: 计算机维修5级,电脑芯片级维修教程