這一篇文章主要接著上一篇,介紹各種著色器的特點以及作用:
頂點著色器
這是GPU流水管線的第一個階段。是完全可編程的階段。正如其名,他只處理傳入的頂點數據,比如位置、顏色、法線、紋理坐標等。頂點著色器通常會將頂點從模型控件轉換到齊次裁減空間,因此頂點著色器必須輸出他的位置。
頂點著色器既不能創(chuàng)建和銷毀頂點,也不能將一個頂點處理的結果傳到另一個頂點。每個頂點都是被獨立處理的。
頂點著色器適用于如下場景:
1、 通過一次性的創(chuàng)建網格并通過頂點著色器使其變形來創(chuàng)建物體
2、 通過使用皮膚和變形技術來使得角色身體和面部具有動畫
3、 程序上的變形,比如旗幟、布料或水的移動
4、 通過發(fā)送退化網格到流水管線下端,并依據需要給定一定區(qū)域來生成粒子
5、 通過使用整個幀緩沖生成一個屏幕對齊的紋理去進行程序變形來制作:光學變形、熱霧、水波、頁面卷曲以及其他的效果
6、 通過頂點紋理獲取應用到地形高度領域
部分效果如圖(左側是普通的茶壺,中間是被頂點著色器執(zhí)行的簡單裁剪操作,右側噪聲功能使模型扭曲):

曲面細分著色器
曲面細分著色器最主要的作用是將曲面轉換成一組三角形。這是一個可選擇的著色器。他具有如下的幾個優(yōu)點:
曲面細分比提供相應的三角形描述一個曲面會更加緊密;節(jié)省內存;在處理角色或物體動畫上可以防止CPU到GPU之間運轉的瓶頸;使用適當的三角形可以有效的呈現曲面。比如:一個球距離攝像機很遠,那么只需要渲染幾個三角形就可以了;如果距離很近,那么可能就要上千的三角形來渲染曲面。這種控制細節(jié)等級的能力也可以應用程序控制性能,比如在低性能GPU上使用低質量的網格來保持幀率。
曲面細分階段包括了三個子階段:在DX中稱為外殼著色器、曲面細分和域著色器。
他們之間的執(zhí)行關系如圖所示:

輸入外殼著色器的是一個特殊的補丁圖元:定義曲面的控制點,貝塞爾曲面補丁或者其他類型的曲面元素。外殼著色器有兩個功能:它會告訴曲面細分階段有多少個三角形需要生成,以及他們的結構;以及對每個控制點進行處理;可選擇性的,外殼著色器可以更改傳進來的補丁,也可以增加或者刪除控制點。外殼著色器輸出一系列的控制點,伴隨著曲面細分階段處理的數據,傳到域著色器。
曲面細分階段在流水管線中是固定執(zhí)行階段,只與曲面細分著色器一起使用。他的任務是通過外殼著色器傳過來的有關曲面細分有關的信息:三角形、四邊形或者等值線,以及曲面細分因子,來添加新的頂點,并計算每個頂點的相對位置。
域著色器類似頂點著色器。它主要是處理從外殼著色器以及曲面細分階段傳送過來的頂點,生成相應的輸出頂點,沿著流水管現傳送下去。
部分效果如圖(左側是大概6000三角形的模型,右側是每個三角形使用PN三角形細分的效果):

幾何著色器
幾何著色器可以將一個圖元轉換成其他圖元。它位于曲面細分著色器的后面,也是一個可選的著色器。
幾何著色器輸入的是單個模型以及其關聯的頂點。對象通常是由三角形帶、線或單個點。幾何著色器也可以定義和處理拓展圖元。幾何著色器處理圖元并輸出0或者更多的頂點,這些頂點被視為點、折線或三角形帶。注意,幾何著色器可以沒有任何輸出。在這種方式下,網格可以通過編輯頂點有選擇的修改、增加或移除圖元。
幾何著色器是為了更改輸入的數據或者制作有限數量的副本而設計的。例如:生成6個轉換后的副本去同時渲染立方體紋理的6面;高效創(chuàng)建陰影紋理去顯示高質量陰影;從點數據創(chuàng)建可變粒子;皮毛渲染;為陰影算法尋找物體邊緣等。
幾何著色器需要確保輸出圖元的結果與輸入時候的順序一致,這會影響性能。因為如果一些著色器代碼是并行運行的,結果必須被保存以及排序,這一點因素不利于幾何著色器在一次調用中輔助或創(chuàng)建大量幾何圖元。
幾何著色器的行為是最不可預測的,需要考慮資源和內存。實際上,幾何著色器很少使用,因為他不能很好的映射出GPU的優(yōu)勢。
常見效果如圖(左側,金屬球等值面曲面細分被GS動態(tài)執(zhí)行。中間,使用GS進行線段不規(guī)則曲面細分以及流輸出,廣告牌被GS生成以顯示閃電。右側,通過使用頂點和幾何著色器和流輸出執(zhí)行布料模擬):

流輸出
通常GPU流水管線的標準使用是發(fā)送數據經過頂點著色器,然后光柵化三角形,在到像素著色器中處理。這些數據通過流水管線并且中間結果不能被訪問。著色器模型4.0添加了流輸出的概念。在頂點著色器處理過頂點之后,這些頂點數據可以輸出到一個流中,即一個順序數組,附加的傳送到光柵化階段。實際上,光柵化可以完全關閉,流水管線純粹作為一個無圖像流處理器。這種方式處理的數據可以通過流水管線返回,從而允許迭代處理??梢杂迷谀M水流或其他粒子效果。
流輸出返回的數據都是浮點類型的數據,因此會有顯著的內存消耗。另外流輸出是在圖元上工作的,而不是直直接在頂點上。如果網格被傳到流水管線下端,每個三角形都會生成他自己的三個輸出頂點集,原始網格上的任何共享頂點將丟失。由于這個原因,更典型的使用是僅僅將頂點作為頂點圖元集通過流水管線傳送。
像素著色器
在頂點、曲面細分和幾何著色器執(zhí)行之后,圖元將被裁減以及光柵化處理。光柵化計算出三角形覆蓋每個像素單元的面積,部分或者完全重疊像素的三角形這一部分稱為片元。三角形頂點的值,包括深度緩沖區(qū)的Z值,將會通過三角形表面,為每個片元插值運算,片元以及插值數據一起傳送到像素著色器。像素著色器實際上處理的是片元,而不是真正的像素。所有在OpenGL中,也稱為片元著色器。
像素著色器主要是計算并輸出片元的顏色,同樣可以產生不透明值以及可選擇性的更改他的Z深度值。像素著色器還具有特有的能力:丟棄一段片元,即,不輸出此片元的數據。
最初,像素著色器僅僅只能輸出到合并階段。但是隨著GPU的發(fā)展,像素著色器可執(zhí)行的指令數量在增加。其中就有多重渲染目標的指令。不同于僅僅將像素著色器程序結果發(fā)到顏色和深度緩沖區(qū),可以為每個片元生成多重設置數值并保存到不同的緩沖區(qū),每個緩沖區(qū)成為渲染目標。多重渲染目標在高效執(zhí)行渲染算法上是強有力的輔助工具。一個渲染通道用來生成顏色圖像,另一個生成對象標識符,第三個生成世界空間距離等。比如延遲渲染:第一個通道存儲關于每個像素的物體位置和材質數據,第二個通道進行光照計算和其他特效,其中可見性和著色是在單獨的通道中完成的。
像素著色器還有一個限制是:他只能處理對應的片元,而不能從相鄰的像素中讀取結果。也就是當像素著色器程序執(zhí)行時,他不能將輸出結果發(fā)送給相鄰像素,也不能訪問其他像素數據。但是有例外,比如像素著色器在梯度或者導數計算時可以間接的訪問相鄰片元信息。但是梯度信息不能受動態(tài)流程控制影響的像素著色器訪問,即if語句或可變數量的迭代循環(huán),所有組內的片元必須使用同一設置的指令進行處理,即使是在離線渲染系統,這也是一個最基本的限制。
合并
合并階段是處理單獨的片元深度以及顏色值(像素著色器生成)并與幀緩沖區(qū)合并的地方。如果片元可見,那么他將和緩沖區(qū)的像素顏色進行混合。對于不透明的片元,那么片元只是簡單的替換像素顏色,而對于透明的片元,才算的上是真正意義上的混合。
如果通過片元通過了像素著色器的計算到達了合并階段,但是根據深度值發(fā)現,他是被其他像素覆蓋著的,那么他在像素著色器中的計算將相當于是一次浪費。為了避免這種情況,有一些GPU采用early-z技術,即在像素著色器之前進行深度檢測,見檢測其可見性,如果不可見則不會傳送到像素著色器進行計算。但是前面說到像素著色器具有改變z深度值或者完全剔除片元的能力,如果在像素著色器程序中有這兩種任何一種操作,early-z通常不能使用,并且要關閉。合并階段是高度可配置的,我們可以決定混合操作的模式等。
計算著色器
計算著色器并沒有規(guī)定在圖形管線的什么位置執(zhí)行。他和其他著色器一樣,有相同的數據輸入集并且可以訪問緩沖區(qū)(比如紋理)用來輸入輸出。計算著色器被線程組執(zhí)行,每個線程組都有一段小內存在線程間共享。計算著色器最重要的優(yōu)點在于他們可以訪問GPU生成的數據。后處理是指渲染后的圖形進一步進行處理,是計算著色器的常見用途。共享內存意味著從采樣像素的結果可以與相鄰線程共享。例如,使用計算著色器去確定一個圖像的分布或平均亮度,其運行速度是像素著色器執(zhí)行此操作的兩倍。
計算著色器同樣用于粒子系統,網格處理比如面部動畫,裁剪,圖像過濾,改善深度精度,陰影,區(qū)域深度,以及其他的任何一組GPU處理器可以處理的任務。
常見效果如圖(左側使用計算著色器進行模擬風吹頭發(fā)的效果,頭發(fā)本身是用曲面細分執(zhí)行的;中間,計算著色器執(zhí)行快速模糊操作,右側,模擬波浪):

小結
主要是了解各個著色器的特點及其作用。至此,所有有關的介紹就結束了,從下一章開始就真正進入了圖形學的重頭戲。接下來的幾篇將帶領大家進入圖形學最重要的基礎:轉換。
參考資料:Real-Time-Rendering-4th