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