1. 程式人生 > >Unity Shader學習3——幾何階段

Unity Shader學習3——幾何階段

前言:

        在之前的文章中,我們補充了影象繪製管線的三個階段:應用程式階段、幾何階段和光柵階段,其中幾何階段和光柵階段使我們理解繪製過程的重點,在這裡我們需要著重分析一下這兩個過程。

幾何階段

        幾何階段的主要任務就是:“變換三維頂點座標”和“光照計算”,這也與顯示卡中的兩個標示“T&L”對應(Transform & Lighting)。

一、變換三維頂點座標:

        輸入到計算機中的資料其實就是一系列的三維座標資料,但是最後通過GPU計算後顯示在二維的螢幕上,這就是說:GPU的計算過程實際上就是將三維的座標資料繪製到二維螢幕上

        要完全理解上述過程,我們需要先知道幾個座標型別:

1.Object space —— 模型座標空間

2.World space —— 世界座標空間,

3.Eye space —— 觀察座標空間

4.Clip and Project space —— 螢幕座標空間

        如下是GPU工作流程中,頂點座標空間的變換流程:

        

二、Object space轉換到World space:

        Object space(模型座標空間),其實就是模型在建模時建立的一個與其他物體沒有任何參照關係的基於自己原點的三維座標空間,包含模型的頂點值。模型座標空間對於操作模型自身屬性比較實用,但當空間中有許多個物體,為了表達各個物體間的相對關係,由於模型座標空間不包含與任何物體的參照關係,所以這裡我們需要引用一個統一的空間座標,每個物體在這個座標中都有一個自己的相對於此座標原點的確定座標位置,這個座標空間就是World space(世界座標空間)。

        從Object space到World space的轉換過程由一個四階矩陣控制,稱之為world matrix

        光照計算通常在World space中進行的,當然也可以在Eye space中得到相同的光照效果,因為,在同一觀察空間中物體之間的相對關係是保持不變的

注意:頂點法向量是在模型檔案中屬於Object space,在GPU的頂點程式中,必須將法向量轉換到world space中才能使用,如同必須將頂點座標從object space轉到world space中一樣,但是兩者的轉換矩陣是不同的,法向量從object space到world space的轉換矩陣是world matrix的轉置矩陣的逆矩陣

三、World space轉換到Eye space:

        在計算機中,每次只能從唯一的視角觸發渲染物體。在遊戲中,引入了視點漫遊的功能,螢幕中顯示的內容隨著視點的變化而變化。這些都是因為GPU將物體頂點座標從world space轉換到了eye space。

        Eye space(視點座標空間),即以Camera(視點或相機)為原點,由視線方向、視角和遠近平面,共同組成的一個梯形體的三維空間,稱之為viewing frustum(視錐體),如下圖所示:

        

        遠近平面:近平面,是梯形體中較小的矩形面,作為投影平面;遠平面,是梯形體中較大的矩形。在這個梯形體中的所有頂點資料都是可見的,而超出這個梯形體之外的場景資料,會被視點去除(Frustum Culling,也稱為視錐裁剪)。

四、Eye space轉換到Clip and Project space:

        一旦頂點座標被轉換到eye space中,就需要判斷哪些點是視點可見的。位於視錐體以內的頂點為可見,以外的則為不可見的,會被視點去除。這個步驟就是clip(裁剪),識別指定區域內或者區域外的圖形部分的過程稱之為裁剪演算法。

        裁剪演算法包括:視域裁剪(View Frustum Culling)、背面剔除(Back-Face Culling)、遮擋剔除(Occlusing Culling)和視口裁剪等。

        裁剪的具體實現是在一個單位立方體中進行的,該立方體的對角頂點分別是(-1,-1,-1)和(1,1,1),通常稱這個單位立方體為規範立方體(CVV)。CVV的近平面(梯形體中較小的矩形面)的XY座標對應螢幕畫素座標(左下角為0,0),Z座標則代表畫面畫素深度。多邊形的裁剪就是在CVV中完成的。

        所以,從視點座標空間到螢幕座標空間的操作步驟有三個:

1.用透視變換矩陣把頂點從視錐體中變換到裁剪空間的CVV中;

2.在CVV中進行圖元裁剪;

3.螢幕對映:將經過上述過程的到的座標對映到螢幕座標系上。

        只有當圖元完全或者部分存在於視錐體內部時,才需要將去光柵化。當一個圖元完全位於視體內部時,直接進入下一個步驟;完全位於視體外的圖元,將被剔除;部分位於視體內的圖元,將進行裁剪。

五、Primitive Assembly && Triangle setup

1.Primitive Assembly:

        圖元裝配,即將頂點根據primitive(原始的連線關係),還原出網格結構。網格由頂點和索引組成,之前的操作都是對頂點的處理,在此步驟,根據索引將頂點連起來,組成線或面單元。之後就是對超出螢幕外的三角形進行裁剪,想象一下:一個三角形其中一個頂點在畫面外,另外兩個頂點在畫面內,這是我們在螢幕上看到的就是一個四邊形。然後將該四邊形切成兩個小的三角形。

        此外還有一個操作涉及到三角形的頂點順序 (其實也就是三角形的法向量朝向),根據右手定則來決定三角面片的法向量,如果該法向量朝向視點(法向量與到視點的方向的點積為正) ,則該面是正面。一般是頂點按照逆時針排列。如果該面是反面,則進行背面去除操作(Back-face Culling)。在 OpenGL 中有專門的函式 enable 和 disable 背面去除操作。所有的裁剪剔除計算都是為了減少需要繪製的頂點個數。

2.Triangle setup:

        處理三角形的過程稱為Triangle Setup,到這一步操作之後,我們得到一堆在螢幕座標上的三角面片,這些面片是用於光柵化的。