3D遊戲引擎系列 一 渲染流程和座標轉換

2021-06-17 18:19:50 字數 4236 閱讀 5603

在3d遊戲中,真實遊戲場景會經過一系列的變化,最終會以2d的形式在螢幕中向我們展示出來。這一整個過程就是通常所說的「繪製流水線」,大多數時候稱之為「管

線」。所謂「固定管線」是指資料進入硬體(gpu)後,使用的是directx或者opengl內建指令,我們無法去干涉整個流程。而「可程式設計管線」是指這裡面某些環節是我們可

控的,我們可以使用gpu指令編寫更豐富的內容,達到更好的效果。深入了解各流程的意義,有助於更好地開發遊戲引擎。

《計算機實時圖形學》將圖形繪製管線分為應用程式階段、幾何階段以及光柵階段。而《3d管線導論》則在幾何階段和光柵階段細分了乙個三角形設定階段。雖然不同的書對

於細節的劃分不一樣,但是整個流程大致都是一致的。

座標轉換是渲染流程的一部分,不過因為程式中我們經常使用,再加上本次會介紹多一點,所以在標題中單提了出來。

有的觀點認為應用程式階段嚴格來說並不屬於管線的一部分,但由於跟渲染結果息息相關,姑且還是把它看成整個過程的起點。這個階段主要是跟cpu、記憶體互動,建立場景

圖、管理場景、視錐裁剪、碰撞檢測等等,都是此階段進行的。本次,不對該階段做過多介紹。

幾何階段,主要負責頂點座標變換、光照、裁剪、投影以及螢幕對映。通常顯示卡資訊中有個「t&l」的硬體部分,就是transform & lighting----變換3維頂點座標和光照計算。

當我們在遊戲中轉換視角的時候,看到的畫面最總會在螢幕中以2d形式呈現出來。3d世界中的點,轉化成螢幕中畫素點的過程,就是頂點座標轉換。

物體座標系即區域性座標系,是以物體自身定義的座標係為基準的。採用此座標系的優勢是方便建模。使用3dmax、maya等建模工具時,你不必考慮乙個房子到底應該放在城市

的哪個地方,只需要考慮這個房子本身模型是什麼就可以了。之後,再將物體放入世界空間中的特定點就可以了。

有了模型後,我們需要將模型放入乙個3d場景中,這個3d場景的就是世界空間。從物體空間到世界空間的轉換由乙個四階矩陣控制,一般叫做worldmatrix。該變換可以控制物

體的平移、縮放以及旋轉。這樣可以控制物體在世界座標系中的位置、大小和角度。光照等計算一般在這個階段,因為光照會涉及到光源的位置等。

作為人眼的代替,在遊戲中使用了相機這一概念。

單純的世界座標系並不夠,因為我們很多時候並不是在世界座標系原點觀察場景,而可能是任意一點。這時候需要將世界座標系轉換為相機座標系。即將世界座標系做一定變

換,讓原點與相機重合,並且讓相機的觀察方向與z軸一致。

很明顯,玩遊戲的時候我們會發現螢幕中的影象總是整個場景的一部分。這是因為我們看到的東西跟乙個叫做「視錐體」的東西有關。

如同模擬人眼一樣,相機只能觀察到一定範圍內的空間。範圍就是視錐體所包圍的空間。視錐體很像乙個被切掉了頂部的金字塔。靠近相機的平面是近裁剪面,作為投影面,對

應的就是螢幕。

將相機座標系中的頂點經過投影矩陣,變化為視口座標系中的點。主要的投影有平行投影和透視投影,一般遊戲中用的是透視投影。這樣更符合近大遠小的習慣。視錐體中的點

經過透視投影後,會被轉換到乙個立方體中,x和y的範圍是-1到1,z的範圍是0到1。

視口座標需要轉換到螢幕上顯示,這一過程中,會有背面消影,深度測試等,然後將符合的畫素寫入快取顯示出來。

光柵化階段主要操作有消除者當面、紋理操作、blending、filtering。

寫這一節的主要原因是因為前段時間用ogre的時候,做矩陣變換時結果始終不對。後來查了資料發現是因為矩陣乘法順序的問題。

1.矩陣和線性變換:

矩陣是用來表示線性變換的一種工具,它和線性變換之間是一一對應的。

考慮線性變換:

a11*x1 + a12*x2 + ...+a1n*xn = x1'

a21*x1 + a22*x2 + ...+a2n*xn = x2'

...am1*x1 + am2*x2 + ...+amn*xn = xm'

對應地,用矩陣來表示就是:

|a11 a12 ... a1n | |x1| |x1'|

|a21 a22 ... a2n | |x2| |x2'|

|... |* |...|= |... |

|am1 am2 ... amn | |xn| |xm'|

也可以如下來表示:

|a11 a21 ... am1|

|a12 a22 ... am2|

|x1 x2...xn|*|... |= |x1' x2'... xm'|

|a1n a2n ... amn|

其中涉及到6個矩陣。分別為a[m*n],x[n*1],x'[m*1]以及x[1*n],a[n*m],x'[1*m]。

可以理解成向量x(x1,x2,...,xn)經過乙個變換矩陣a[m*n]或a[n*m]後變成另外乙個向量x'(x1',x2',...,xm'))。

2.矩陣的表示法:行矩陣 vs. 列矩陣

行矩陣和列矩陣的叫法是衍生自行向量和列向量。

其實,矩陣a[m*n]可以看成是m個n維的row vector構成的row matrix,也可看成是n個m維的column vector構成的column matrix。

其中,x[n*1]/x'[m*1]就等價於1個n/m維的column vector。x[1*n]/x'[1*m]就等價於1個n/m維的row vector。

row matrix和column matrix只是兩種不同的表示法,前者表示把乙個向量對映到矩陣的一行,後者表示把乙個向量對映到矩陣的一列。

本質上體現的是同一線性變換。矩陣運算規定了它們可以通過轉置運算來改變這個對映關係。

3.矩陣的相乘順序:前乘或左乘 vs. 後乘或右乘

需要注意的是兩種不同的表示法對應不同的運算順序:

如果對乙個column vector做變換,則變換矩陣(row matrix/vectors)必須出現在乘號的左邊,即pre-multiply,又叫前乘或左乘。

如果對乙個row vector做變換,則變換矩陣(column matrix/vectors)必須出現在乘號的右邊,即post-multiply,又叫後乘或右乘。

一般不會弄錯,因為矩陣乘法性質決定了相同的內維數的矩陣才能相乘。至於為什麼是這個規律,為什麼要row vector乘以column vector或column vector乘以row vector???想想吧。。。

所以左乘還是右乘,跟被變換的vector的表示形式相關,而非儲存順序決定。

4.矩陣的儲存順序:按行優先儲存 vs. 按列優先儲存

涉及到在計算機中使用矩陣時,首先會碰到儲存矩陣的問題。

因為計算機儲存空間是先後有序的,如何儲存a[m*n]的m*n個元素是個問題,一般有兩種:按行優先儲存和按列優先儲存。

row-major:存成a11,a12,...,amn的順序。

column-major:存成a11,a21,...,amn的順序。

這樣問題就來了,給你乙個儲存好的矩陣元素集合,你不知道如何讀取元素組成乙個矩陣,比如你不知道a12該放在幾行幾列上。

所以,每個系統都有自己的規定,比如以什麼規則儲存的就以什麼規則讀取。dx使用row-major,ogl使用column-major.即乙個相同的矩陣a[m*n]在dx和ogl中的儲存序列是不一樣的,這帶來了系統間轉換的麻煩。

不過,乙個巧合的事情是:dx中,點/向量是用row vector來表示的,所以對應的變換矩陣是column matrix/vectors,而ogl中,點/向量是用column vector來表示的,所以對應的變換矩陣是row matrix/vectors.所以,如果在dx中對乙個向量x(x1,x2,x3,1)或點(x(x1,x2,x3,1))應用a[4*4]的矩陣變換,就是x' = x(x1,x2,x3,1) * a[4*4],由於採用row-major,所以它的儲存序列是a11,a12,...,a43,a44。在ogl中,做同樣的向量或點的變換,因為其使用row matrix/vectors,其應用的變換矩陣應該是a'[4*4] = a[4*4]( ' 表示transpose/轉置),就是x' = a'[4*4] * x'(x1,x2,x3,1),但是由於採用column-major,它的儲存序列正好也是a11,a12,...,a43,a44!!!

所以實際上,對dx和ogl來講,同乙個變換,儲存的矩陣元素序列是一樣的.比如:都是第13,14,15個元素儲存了平移變化量deltaz,deltay,deltaz.

3D遊戲引擎系列一

筆者介紹 姜雪偉,it公司技術合夥人,it高階講師,csdn 社群專家,特邀編輯,暢銷書作者,國家專利發明人 已出版書籍 手把手教你 架構 3d遊戲引擎 電子工業出版社 和 unity3d 實戰核心技術詳解 電子工業出版社等。為了能讓開發者重視引擎開發,最近一直在寫一些關於學習引擎的一些博文,為此還...

3D遊戲引擎系列四

筆者介紹 姜雪偉,it公司技術合夥人,it高階講師,csdn社群專家,特邀編輯,暢銷書作者,國家專利發明人 已出版書籍 手把手教你架構3d遊戲引擎 電子工業出版社和 unity3d實戰核心技術詳解 電子工業出版社等。在設計引擎時,首先我們要做的是把整個引擎的框架設計好,引擎設計採用的都是模組化開發,...

3D渲染管線流程

首先用一張圖來回顧一下渲染管線的各個階段,目前為止我們接觸的著色器有頂點著色器和畫素著色器,而接觸到的渲染管線階段有 輸入裝配階段 頂點著色階段 光柵化階段 畫素著色階段 輸出合併階段.可以看到,幾何著色器是我們在將頂點送入光柵化階段之前,可以操作頂點的最後乙個階段。它同樣也允許我們編寫自己的著色器...