3D遊戲編程入門(八)電腦圖形學
(2007-01-01 15:43:13)
轉載▼
07年到來了,新的一年並沒有帶了更多的欣喜感,只有年齡又大了一歲,壓力更沉重了一份,於是積累知識也更顯的緊要了.07年,加倍奮鬥的一年.
07年第一個早上竟是被夢驚醒的,夢裡有朋友到部落格中留言大罵我沒有繼續寫3D遊戲編程,沒有信用,正準備辯解,憤怒的朋友卻不知哪兒弄了個木棒子打中我後腦勺,嚇醒後發現原來是掛著的衣服掉在臉上了,遮的我透不過氣來.仔細想想,寫的這些東西始終無法與正規書籍相行比較,相信願意看的人也不多,但它確實為我個人的複習帶來極大的好處,令我記性好了很多,所以我還會繼續.相信夢中那強烈的負罪感也不是毫無根據的襲來吧,呼
趁著元旦放假三天,我將全部精力投入到3D複習中,預計每日能放出5篇左右的日誌吧,3天15節應該可以說完頂點,紋理,燈光,相關部分吧。因為這裡整體把握不好,我會從各個方面重點進行反覆的複習和說明。
恩,開始正題 電腦圖形學
向量 瞭解DirectX之前,我們有必要瞭解這部分知識。
電腦圖形學主要是研究使用電腦及其圖形裝置來輸入,表示,變換,運算和輸出圖形的原理,演算法及系統的學科。
從定義中我們可以看出,我們的基本步驟可以分為5步,輸入源圖形,結構表示圖形屬性,變換矩陣,運算矩陣,輸出靶心圖表形。我們瞭解的重點則是相關的運算原理,最佳化其中的演算法,以及熟悉整個渲染系統流程。
我們首先來瞭解下電腦圖形裝置,我們可以看下面的圖,首先我們從外圍裝置進行輸入資料,系統匯流排將這部分資料根據類別或放置於系統儲存空間中,或發送到CPU中,或發送到顯存GPU中,再根據顯卡中的相應運算,將其發送視頻控制器中,顯示器將其顯示出來。我們最需要重視的則是資料如何存放於CPU,GPU中,又是如何進行運算後進行輸出的。
在3D遊戲編程中,我們使用圖形編程的首要任務是要類比真實世界中物理的各種屬性,給玩家以真實感。這些屬性包括著物體的形狀,紋理,材質,物體間的相對位置,遮擋關係,骨骼運動效果等。我也將按照這個流程進行複習和講述。
電腦圖形學基礎
我們大致瞭解形學需要知道的東西,接下來將對其幾何概念和運算進行說明。這部分需要一定的空間想象能力和線性代數或者立體幾何的知識,當然,即使你不瞭解這些細節也沒有大的關係,因為它們並非想象中的複雜。
首先我們來理解一下向量。在高中物理中我們應該知道向量和向量的區別,前者是沒有方向的線段,後者是有方向的線段。我們物理中的各種力全是用向量來描述的。向量的兩大特性就是:有長度,和有方向。當兩個向量在空間中,方向相同且長度相同,我們就認為它們是相等的,即使在圖上相對描繪位置不同也沒有關係,因為我們並不關心它的位置關係。所以無論一個向量如何進行平移,我們都認為它是不變的,因為它的兩個屬性沒有發生變化。
但當這個向量尾部和座標系統的原點一致時,向量就處於標準位置。這裡要和標準向量進行區別,標準向量的定義是,長度為1的向量就成為一個標準單位向量,這裡希望大家記清楚。
當我們已經獲得一個標準位置的向量時,我們相當於已經獲得了一個向量的尾頂點(0,0,0),向量是一個有方向的線段,而線段是由兩個點即可確定的,我們僅需要再獲得向量的頂點座標,我們就可以得到這個向量的長度,和它的方向,所以我們在二維世界中,可以用這樣的模式確定一個向量U= ( Ux, Uy ),想象一下,尾頂點為( 0,0 ),頭頂點為( Ux, Uy)的向量是否是確定的唯一的?而三維座標中我們同樣而已這樣表示一個向量N= ( Nx, Ny, Nz)。當然這樣寫出來很容易讓人混淆,這是一個點還是一個向量?我們必須再從定義上來區別兩者,點是一個座標系中一個位置,而向量擁有著長度和方向。
三維座標系這裡要提一下,我們3D遊戲編程中通常使用的左手座標系,即左為X軸正方向,上為Y軸正方向,裡為Z軸正方向(即你的螢幕向裡面是正方向,所以我們眼睛的Z座標一直是負的)。為方便大家理解,我們下面繼續給出圖示。其中i,j,k三個向量我們假設長度都為1,則可以分別表示為(1,0,0),(0,1,0),(0,0,1),因為它們的長度為1,我們可以稱其為單位向量,又因為它們的方向特殊,正沿三軸伸展,我們又稱其為基本向量。
在二維世界中,我們計算一個線段的長度是如何進行的呢?我們假如由(0,0)點和(4,5)點為兩頂點的線段,我們求其長度,應該是(4-0)的平方+(5-0)的平方再開2倍根號吧。而三維中,假如向量的尾頂點為座標原點(0,0,0)頭頂點為(4,5,6),則其長度也為(4-0)的平方+(5-0)的平方+(6-0)的平方,最後開2倍根號。我們稱向量的長度為它的模。因為我說過,向量在座標系中無論如何平移,它的方向和長度兩大屬性是不變的,我們終究把它看成相等的。這時我們一定可將任意一個向量進行平移,最終總會獲得一個尾頂點為座標原點的相等向量,則我們通過獲得它的頂點座標可以獲得該向量的模。我們可以舉例:一個尾座標為(1,2,3)頂座標為(4,5,6)的向量,經過平移後,它將變成一個尾座標為(0,0,0),頭頂點座標為(3,3,3)的相等向量(你可以去想想,是否改變了此向量的方向和長度)。再求它的摸,則為3的平方+3的平方+3的平方,再開2次根,結果為3倍根號3。
當我們獲得了一個向量的模後,我們再將其除以其模,則可獲得一個長度為1方向不變的單位向量(注意,不是標準向量)。依舊拿(1,2,3)(4,5,6)這個向量來舉例,平移後該向量為N(3,3,3),模為3倍根號3,拿Nx=3,Ny=3,Nz=3除以模,則其單位向量是(根號3/3,根號3/3,根號3/3),你可以計算下,其長度是否為1,方向是否為1。
我們獲得一個向量的單位向量是很重要的,學過線形代數的朋友可以去想想當一個矩陣乘以一個單位矩陣會發生什麼變化。這些我後面會再詳細說明其重要性。
學過物理力學的朋友應該回想一下,當一個物體受兩個力的作用時,我們是如何算出其合力的?這裡涉及的東西較雜,我不再詳細解釋。給出大家一個圖,大家可以參考回憶下,我直接給出兩向量相加相減的公式了
U + V = ( Ux+Vx, Uy+Vy, Uz+Vz );
U - V = ( Ux-Vx, Uy-Vy, Uz-Vz )
就如開始我們去除模的道理一樣,當我們將一個向量和一個標量(無方向的長度)相乘時,向量的長度大小會變化,其方向不變化(若乘的是負數,則反向),我們獲得的新向量也可求出,公式如下
V = kU = ( kUx, kUy, kUz );
當我們記住並理解上述基本公式後,我們可以接下來理解下向量的點乘和叉乘。
點乘公式為S = U 點乘 V = U的模乘以 V的模 再乘以 COS(UV之間的角度)
這樣得出來的是一個標量S,是沒有方向的值。但是根據這個值與0的比較,我們可以獲得U,V兩標量之間的關係。
如果 =0,那麼向量 u . v相等。
如果 >0,那麼向量 u 、v之間的夾角小於90度。
如果 <0,那麼向量 u 、v之間的夾角大於90度。
我們可以自己想想為什麼。
叉乘在我們設定法線時非常重要,大家應該很好的記住這裡
首先叉乘公式為:S = U 叉乘 V =[( UyVz - UzVy ),( UzYx - UxVy ),( UxVy - UyVx)];
我們從中可以看出,我們叉乘得到的不再是一個無方向標量值。而是一個向量。那麼這個向量是什麼樣的向量呢。我們看
我們應該去記住,兩個向量叉乘得到的是一個同時垂直於這兩個向量的一個新向量。恩,具體的道理,實在難以解釋,自己無法理解的朋友還是死記吧。>_< 矩陣 恩,懂得編程的朋友應該清楚數組,學過幾何線性代數的朋友應該清楚矩陣,其實個人認為這兩者沒有任何區別,起碼在D3D編程中很難去找到什麼區別。
這兩者都是以一個M行N列的矩形數字數組去記錄一系列的數字。我們常稱M,N為此矩陣的維數。當兩個矩陣的維數和其中元素都相同時,我們稱它倆是相等的。
當一個矩陣只有一個單行或者一個單列時,我們稱其為行向量或列向量。我們的一個三維向量座標就是一個三列的行向量。
矩陣的加減法。首先我們要求這兩個矩陣的維數必須相等,否則我們無法去進行這種運算。矩陣的和就是兩個矩陣中對應位置的元素相加得到一個新的矩陣。
矩陣的數乘法。就是用一個矩陣和一個標量數字相乘。我們將此矩陣中的所有元素分別與此數字相乘得到的一個新的矩陣就是矩陣的數乘。
矩陣的相乘。即矩陣A乘以矩陣B。首先,我們要求矩陣A的列數和矩陣B的行數必須相等,即前列後行相等的要求。從這裡我們應該明白,AB是不等於BA的,矩陣相乘是很注意前後順序的,它不滿足乘法交換律。這裡公式不好寫,我建議大家去網上簡單找個線形代數的資料看下。
單位矩陣。我們開始說過三個標準向量,並且給了圖,當我們將i,j,k三個向量順序排列,則是一個三維標準單位矩陣。任何矩陣乘以一個單位矩陣都不會進行任何改變,它是一個僅主對角線為1,其他元素均為0的特殊矩陣。
逆矩陣。僅有行列數相等的方矩陣才會有逆矩陣,它即是將矩陣中的所有元素相對與主對角線進行位置互換的矩陣,我們可以理解成,將元素的行列下標進行替換得到的矩陣。一個方矩陣和它的逆矩陣相乘時,結果會是一個單位矩陣。
轉置矩陣。和逆矩陣不同的是,它適用於任何行列的矩陣,但它也是將一個矩陣的行列進行交換,一個mXn的矩陣,轉置矩陣則是nXm的矩陣。
矩陣的齊次座標變換。我們說過,矩陣相乘是有要求的,它要求我們前矩陣列數和後矩陣行數相等,假如我們現在擁有一個2X2的矩陣,一個3X3的矩陣,我們是無法直接進行乘法運算的,這就要求我們將2X2的矩陣列數變成3,此矩陣變成2X3的矩陣才能參與運算,這時我們可以在新添加的這列中兩個元素都補0,獲得一個新的2X3的矩陣,這就是矩陣的齊次座標變換。它是為了方便我們的矩陣乘法運算而存在的。 圖形變換
說完了向量矩陣,我們可以聯絡遊戲來說明象變換。
圖象的變換一般是分為三類的,旋轉,平移,縮放。而在二維遊戲中,我們比較少用縮放,因為它原本就沒有深度概念,我們可以想想《傳奇》裡是否有人物越走越遠時是否有變小?三維遊戲中,這三者都會有很深的涉及。
因為二維遊戲比較容易,我們先拿它進行舉例。
首先我們要清楚,一個圖象在螢幕上,它原本就是由一個個象素組成的,而一系列的象素點就組成了一個矩陣,當我們想對圖象進行翻轉,縮放,平移等,則需要對它的矩陣點進行運算就可以獲得改變後的圖象了。這是基本原理。
一般來說,我們是將圖象的矩陣乘以一個變換矩陣來獲得改變後的圖象矩陣。
二維變換矩陣是一個三行三列的矩陣,其中a11,a12,a21,a22是對圖形進行旋轉,縮放,對切變換的。a13,a23是對圖形進行投影變換的,它將控制滅點的產生.a31,a32是控製圖形的平移變化.a33是控製圖形縮放的。大家有興趣的話,可以自己設定一個簡單的矩陣組,其中每一點記錄三個數值,x座標,y座標,和該點顏色,再和不同的二維變換矩陣相乘,獲得新矩陣,看看變化情況。
三維變換矩陣則是由一個四行四列的矩陣構成。
此矩陣中a41控製圖形x軸平移度,A42控Y軸平移量,A43控制Z軸平移量。A11,12,13,21,22,23,31,32,33均控製圖形的旋轉軸和角度。縮放則由A11,A22,A33分別控制x,y,z的縮放度。 如何,是否一片暈暈的,呵呵,其實這些基本的東西進行瞭解就好,沒必要去嚴格的死記,在之後的深入研究才會真正有些用處的。暫時沒有消化也不成大問題的。別放棄。不清楚的可以留言問下:)