學習shader之前必須知道的東西之計算機圖形學(一)渲染管線

引言 
shader到底是幹什麼用的?shader的工作原理是什麼? 
其實當我們對這個問題還很懵懂的時候,就已經開始急不可耐的要四處搜尋有關shader的資料,恨不得立刻上手寫一個出來。但看了一些資料甚至看了不少cg的語法之後,我們還是很迷茫,UNITY_MATRIX_MVP到底是個什麼矩陣?它和v.vertex相乘出來的又是什麼玩意?當這些問題困擾我們很久之後,我們才發現,原來我們是站在浮沙上築高臺,根基都沒有打牢當然不可能蓋得起高樓大廈了。 
那根基是什麼呢?大牛曰,計算機圖形學。 
shader中文名叫着色器,顧名思義,它的作用可以先簡單理解爲給屏幕上的物體畫上顏色。而什麼東西負責給屏幕上畫顏色?當然是GPU,所以我們寫shader的目的就是告訴GPU往屏幕哪裏畫、怎麼畫。說到這其實大家應該很明白了,如果我們連GPU的工作原理都不知道,何談指揮它? 
說到計算機圖形學,包括我在內很多同學都非常害怕它,因爲裏面包含了各種艱深的理論、變換,大量的公式什麼的。其實我們大可不必一開始就嚇倒自己,先從基本概念開始,慢慢來,總有一天我們也會成爲大牛~! 
最後,這篇文章不算是原創,最多算是摘要+讀後感,很多概念性文字都是我從書裏搬過來後再加上自己的理解,算是和大家一起學習,有理解不當之處還請多多指教。 
廢話不多說,讓我們來進入第一章的學習,GPU的渲染管線。 


正文 
所謂GPU的渲染管線,聽起來好像很高深的樣子,其實我們可以把它理解爲一個流程,就是我們告訴GPU一堆數據,最後得出來一副二維圖像,而這些數據就包括了”視點、三維物體、光源、照明模型、紋理”等元素。 
在各種圖形學的書中,渲染管線主要分爲三個階段:應用程序階段、幾何階段、光柵階段。 

1,應用程序階段。 
這個階段相對比較好理解,就比如我們在Unity裏開發了一個遊戲,其實很多底層的東西Unity都幫我們實現好了,例如碰撞檢測、視錐剪裁等等,這個階段主要是和CPU、內存打交道,在把該計算的都計算完以後,在這個階段的末端,這些計算好的數據(頂點座標、法向量、紋理座標、紋理)就會通過數據總線傳給圖形硬件,作爲我們進一步處理的源數據。 

2,幾何階段。 
主要負責頂點座標變換、光照、裁剪、投影以及屏幕映射,改階段基於GPU進行運算,在該階段的末端得到了經過變換和投影之後的頂點座標、顏色、以及紋理座標。簡而言之,幾何階段的主要工作就是“變換三維頂點座標”和“光照計算”。 
問題隨之而來,爲什麼要變換頂點座標?我是這麼理解的,比如你有一個三維遊戲場景,場景中的每個模型都可以用一個向量來確定它的位置,但如何讓計算機根據這些座標把模型正確的、有層次的畫在屏幕上?這就是我們需要變換三維頂點座標的原因,最終目的就是讓GPU可以將這些三維數據繪製到二維屏幕上。 
根據頂點座標變換的先後順序,主要有如下幾個座標空間:Object space,模型座標空間;World space,世界座標空間;Eye space,觀察座標空間;Clip and Project space,屏幕座標空間。下圖就是GPU的整個處理流程,深色區域就是頂點座標空間的變換流程,大家瞭解一下即可,我們需要關注的是每個座標空間的具體含義和座標空間之間轉換的方法。 
 

2.1,從object space到world space 
object space有兩層核心含義,第一,object space中的座標值就是模型文件中的頂點值,這些值是在建立模型時得到的,例如一個.max文件,裏面包含的數據就是object space的座標。第二,object space的座標與其他物體沒有任何參照關係,這是object space和world space區分的關鍵。world space座標的實際意義就有有一個座標原點,物體跟座標原點相比較才能知道自己的確切位置。例如在unity中,我們將一個模型導入到場景中以後,它的transform就是世界座標。 

2.2,從world space到eye space 
所謂eye space,就是以攝像機爲原點,由視線方向、視角和遠近平面,共同組成的一個梯形體,如下圖,稱之爲視錐(viewing frustum)。近平面,是梯形體較小的矩形面,也是靠近攝像機的平面,遠平面就是梯形體較大的矩形,作爲投影平面。在這個梯形體的內的數據是可見的,超出的部分會被視點去除,也叫視錐剪裁。 
例如在遊戲中的漫遊功能,屏幕的內容隨攝像機的移動而變化,這是因爲GPU將物體的頂點座標從world space轉換到了eye space。 
 
2.3,從eye space到project and clip space 
eye space座標轉換到project and clip space座標的過程其實就是一個投影、剪裁、映射的過程。因爲在不規則的視錐體內剪裁是一件非常困難的事,所以前人們將剪裁安排到一個單位立方體中進行,這個立方體被稱爲規範立方體(CCV),CVV的近平面(對應視錐體的近平面)的x、y座標對應屏幕像素座標(左下角0、0),z代表畫面像素深度。所以這個轉換過程事實上由三步組成: 
(1),用透視變換矩陣把頂點從視錐體變換到CVV中; 
(2),在CVV內進行剪裁; 
(3),屏幕映射:將經過前兩步得到的座標映射到屏幕座標系上。 

2.4,primitive assembly(圖元裝配)和triangle setup(三角形處理) 
到目前爲止我們得到了一堆頂點的數據,這一步就是根據這些頂點的原始連接關係還原出網格結構。網格由頂點和索引組成,這個階段就是根據索引將頂點鏈接到一起,組成線、面單元,然後進行剪裁,如果一個三角形超出屏幕以外,例如兩個頂點在屏幕內,一個頂點在屏幕外,這時我們在屏幕上看到的就是一個四邊形,然後把這個四邊形切成兩個小的三角形。 
現在我們得到了一堆在屏幕座標上的三角形面片,這些面片是用於光柵化的。 

3,光柵化階段。 
經過上面的步驟之後,我們得到了每個點的屏幕座標值,和我們需要繪製的圖元,但此時還有兩個問題: 
(1)屏幕座標是浮點數,但像素是用整數來表示的,如何確定屏幕座標值所對應的像素? 
(2)如何根據已確定位置的點,在屏幕上畫出線段或者三角形? 
對於問題1,繪製的位置只能接近兩指定端點間的實際線段位置,例如,一條線段的位置是(10.48, 20.51),轉換爲像素位置就是(10,21)。 
問題2,涉及到具體的畫線和填充算法,有興趣的話可以研究。 
這個過程結束後,頂點和圖元已經對應到像素,之後的流程就是如何處理像素,即給像素賦予顏色值。 
給像素賦予顏色的階段稱爲Pixel Operation,是在更新幀緩存之前,執行最後一系列針對每個片段的操作,其目的是計算出每個像素的顏色值。在這個階段,被遮擋的面通過一個被稱爲深度測試的過程消除。 
pixel operation包含下面這些流程: 
(1)消除遮擋面; 
(2)Texture operation,紋理操作,根據像素的紋理座標,查詢對應的紋理值; 
(3)Blending,通常稱爲alpha blending,根據目前已經畫好的顏色,與正在計算的顏色的alpha值混合,形成新的顏色。 
(4)Filtering,將正在計算的顏色經過某種濾鏡後輸出。 
該階段之後,像素的顏色值被寫入幀緩存中。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章