導航:首頁 > 源碼編譯 > zbuffer演算法

zbuffer演算法

發布時間:2023-05-28 12:05:09

1. 數控學習

就想學一門語言,那不難

2. 編程_游戲_演算法_War3游戲中的實時陰影是怎麼計算的,有沒有能參考的演算法的代碼或者可反編譯的游戲例子

7.2.1 陰影體

在3D動作游戲中,GPU往往要面對繪制大量光影效果的場景,而游戲的光影效果越復雜,提供的視覺真實感就越好。但復雜的光影計算往往需要耗費大量的計算資源,導致游戲的運行速度慢如蝸牛。DOOM3就是一個典型的例子,它帶來的逼近影視質量的效果令人折服,但過於復雜的光影變換極其耗費GPU的運算資源,導致現在沒有幾款顯卡能夠輕松應對。

先來看看3D游戲中陰影的生成原理。在現實世界中,陰影效應因光線被物體遮擋而產生,而在3D環境下同樣通過模擬這一機制來創建陰影:將物體沿著光線的方向擴展成一個稜台,該稜台內的所有物體都處於陰影之中,它也被稱為「陰影錐」或「陰影體」。那麼,GPU如何判斷某個物體是否在這個陰影錐內呢?這個時候,就必須用到模板緩沖。模板緩沖好比是蠟染中的蠟層,可以遮罩住3D畫面的任意區域,這樣,這些區域就暫時不被繪制,之後再對整個畫面作光照計算。由於陰影錐內的物體被模板緩沖遮住,光照計算並不會涉及到其中的物體,體現在視覺上就是陰影錐內的物體無法被光線「照到」,陰影效果由此誕生。

實時陰影是一種相對高級的技術,在每一幀,場景中的幾何體或燈光位置變動時,要計算一個叫做shadow volume 的物體。shadow volume實際是一個三維物體,是投影物體的輪廓,總是從光源方向投出。

例如飛機模型,投影的物體是一個兩翼飛機,在每一幀中飛機的輪廓被計算(使用一個邊檢測演算法,輪廓的每個邊要被建立,因為相鄰的多邊形針對光矢量分別有相反的法線),結果邊列表(輪廓的)被投影成一個沿光源方向的三維物體。這個三維物體就叫做shadow volume,而視點在volume里就是在陰影里。

接下來,shadow volume在模板緩沖區中被渲染兩次,開始時僅僅正面面對的多邊形被渲染,模板緩沖區每次數值被增加。然後背面面對的多邊形被渲染,模板緩沖區值被減小。一般來說,所有增加的值和減少的值將互相抵消,但是,因為場景中已經具有被渲染的正常的圖元(飛機和地形),當shadow volume被渲染時,一些像素將不能通過zbuffer測試,所有留在模板緩沖區中的值對應的像素處於陰影區。

最後,保留的模板緩沖區內容被用做一個模板,作為一個巨大的全包圍的黑方塊被alpha-blended到場景中,使用模板緩沖區作為模板,僅僅陰影中的像素是暗的。

前面所介紹的方法,即平面陰影(planar shadow),只適用於平面上。但是,除了少數的情形之外,絕大多數的情形下,根本無法預測陰影會被投射在什麼樣的表面上。所以需要自由度更高的方法。

在這里介紹一個較為靈活的方法,它可以將陰影投射在不規則的表面上。這個方法稱為體積陰影(volumetric shadow)。這個方法的特點在於,它並不是利用「把物體投影到表面」的方式來產生陰影,而是去找出場景中,有哪些像素在陰影中。也就是說,想像一個物體擋住光時,在物體的後面會形成一個大的「陰影錐」。很明顯,若一個像素在「陰影錐」之中,那它就是在陰影之中的,如圖7-6所示。


3. 計算機圖形學復習

第一章
1. 計算機圖形:用數學方法描述,通過計算機生成、處理、存儲和顯示的對象。
2. 圖形和圖像的主要區別是表示方法不同:圖形是用矢量表示;圖像是用點陣表示的。圖形和圖像也可以通過光柵顯示器(或經過識別處理)可相互轉化。
3. 於計算機圖形學緊密相關的學科主要包括 圖像處理、計算幾何和計算機視覺模式識別。它們的共同點是 以圖形/圖像在計算機中的表示方法為基礎。
4. 互動式計算機圖形系統的發展可概括為以下4個階段:字元、矢量、二維光柵圖形、三維圖形。
5. 圖形學研究的主要內容有:①幾何造型技術 ②圖形生成技術 ③圖形處理技術 ④圖形信息的存儲、檢索與交換技術 ⑤人機交互技術 ⑥動畫技術 ⑦圖形輸入輸出技術 ⑧圖形標准與圖形軟體包的研發。
6. 計算機輔助設計和計算機輔助製造 是計算機圖形學最廣泛最活躍的應用領域。
7. 計算機圖形學的基本任務:一是如何利用計算機硬體來實現圖形處理功能;二是如何利用好的圖形軟體;三是如何利用數學方法及演算法解決實際應用中的圖行處理問題。
8. 計算機圖形系統是由硬體系統和軟體系統組成的。
9. 計算機圖形系統包括處理、存儲、交互、輸入和輸出五種基本功能。
10. 鍵盤和滑鼠是最常用的圖形輸入設備。滑鼠根據測量位移部件的不同,分為光電式、光機式和機械式3種。
11. 數字化儀分為電子式、超聲波式、磁伸縮式、電磁感應式等。小型的數字化儀也稱為圖形輸入板。
12. 觸摸屏是一種 定位設備,它是一種對於觸摸能產生反應的屏幕。
13. 掃描儀由3部分組成:掃描頭、控制電路和移動掃描機構。掃描頭由光源發射和光鮮接收組成。按移動機構的不同,掃描儀可分為平板式和滾筒式2種。
14. 顯示器是計算機的標准輸出設備。彩色CRT的顯示技術有2種:電子穿透法和蔭罩法。
15. 隨機掃描是指電子束的定位及偏轉具有隨意性,電子束根據需要可以在熒光屏任意方向上連續掃描,沒有固定掃描線和掃描順序限制。它具有局部修改性和動態性能。
16. 光柵掃描顯示器是畫點設備。
17. 點距是指相鄰像素點間的距離,與分辨指標相關。
18. 等離子顯示器一般有三層玻璃板組成,通常稱為等離子顯示器的三層結構。
19. 用以輸出圖形的計算機外部設備稱為硬拷貝設備。
20. 列印機是廉價的硬拷貝設備,從機械動作上常為撞擊式和非撞擊式2種。
21. 常用的噴墨頭有:壓電式、氣泡式、靜電式、固體式。
22. 繪圖儀分為靜電繪圖儀和筆式繪圖儀。
23. 圖形軟體的分層。由下到上分別是:①圖形設備指令、命令集、計算機操作系統 ②零級圖形軟體 ③一級圖形軟體 ④二級圖形軟體 ⑤三級圖形軟體。
24. 零級圖形軟體是面向系統的、最底層的軟體,主要解決圖形設備與主機的通信與介面問題,又稱設備驅動程序。
25. 一級圖形軟體即面向系統又面向用戶,又稱基本子系統。
26. 圖形應用軟體是系統的核心部分。
27. 從物理學角度,顏色以主波長、色純度和輝度來描述;從視覺角度來看,顏色以色彩、飽和度和亮度來描述。
28. 用適當比列的3種顏色混合,可以獲得白色,而且這3種顏色中的任意2種的組合都不能生成第三種顏色,稱為三原色理論。
29. RGB模型的匹配表達式是:c=rR+gG+bB。
30. 常用顏色模型
顏色模型名稱 使用范圍
RGB 圖形顯示設備(彩色CRT和光柵顯示器)
CMY 圖形列印、繪制設備
HSV 對應畫家本色原理、直觀的顏色描述
HSL 基於顏色參數的模型
用基色青、品紅、黃定義的CMY顏色模型用來描述硬拷貝設備的輸出顏色。它從白光中濾去某種顏色,故稱為減色性原色系統。

第二章
31. 直線生成的3個常用演算法:數值微分法(DDA)、中點劃線法和Bresenham演算法。
32. DDA演算法的C語言實現:
DDA演算法生成直線,起點(x0,y0),終點(x1,y1).
Void CMy View ::OnDdaline()
{
CDC *pDC=GetDC(); //獲得設備指針
int x0=100,y0=100,x1=300,y1=200,c=RGB(250,0,0);//定義直線兩端點和直線顏色
int x,y,i;
float dx,dy,k;
dx=(float)(x1-x0);
dy=(float)(y1-y0);
k=dy/dx;
x=x0;
y=y0;
if(abs(k)<1)
{ for(;x<=x1;x++)
{pDC—>SetPixel(x,int(y+0.5),c);
y=y+k;}
}
if(abs(k)>=1)
{ for(;y<=y1;y++)
{pDC—>SetPixel(int(x+0.5),y,c);
x=x+1/k;}
}
ReleaseDC(pDC); //釋放設備指針
}
33. 任何影響圖元顯示方法的參數稱為屬性參數。圖元的基本表現是線段,其基本屬性包括線型、線寬和色彩。
34. 最常見的線型包括實線、虛線、細線和點劃線等,通常默認的線型是實線。
35. 線寬控制的實線方法:垂直線刷子、水平線刷子、方形線刷子。生成具有寬度的線條還可以採用區域填充演算法。
36. 用離散量表示連續量時引起的失真現象稱為走樣。為了提高圖形顯示質量,減少或消除走樣現象的技術稱為反走樣。
37. 反走樣技術有:提高解析度(硬體方法和軟體方法)、簡單區域取樣、加權區域取樣。
38. 區域連通情況分為四連通區域和八連通區域。四連通區域是指從區域上某一點出發,可通過上下左右4個方向移動,在不越出區域的前提下到達區域內的任意像素;八連通區域是指從區域內某一像素出發,可通過上下左右、左上左下、右上右下8個方向的移動,在不越出區域的前提下到達區域內的任意像素。
39. 字元的圖形表示可以分為點陣式和矢量式兩種形式。
40. 在圖形軟體中,除了要求能生成直線、圓等基本圖形元素外,還要求能生成其他曲線圖元、多邊形及符號等多種圖元。
41. 在掃描線填充演算法中,對水平邊忽略而不予處理的原因是實際處理時不計其交點。
42. 關於直線生成演算法的敘述中,正確的是:Bresenham演算法是對中點畫線演算法的改進。
43. 在中點畫圓演算法中敘述錯誤的是:為了減輕畫圓的工作量,中點畫圓利用了圓的四對稱性性質。
44. 多邊形填充時,下列論述錯誤的是:在判斷點是否在多邊形內時,一般通過在多變形外找一點,然後根據該線段與多邊形的交點數目為偶數即可認為在多邊形內部,若為奇數則在多邊形外部,且不考慮任何特殊情況。
第三章
1. Cohen-Sutherland演算法,也稱編碼裁剪法。其基本思想是:對於每條待裁剪的線段P1P2分三種情況處理:①若P1P2完全在窗口內,則顯示該線段,簡稱「取」之;②若P1P2完全在窗口外,則丟棄該線段,簡稱「舍」之;③若線段既不滿足「取」的條件也不滿足「舍」的條件,則求線段與窗口邊界的交點,在交點處把線段分為兩段,其中一段 完全在窗口外,可舍棄之,然後對另一段重復上述處理。
2. Sutherland-Hodgman演算法,又稱逐邊裁剪演算法。其基本思想是用窗口的四條邊所在的直線依次來裁剪多邊形。多邊形的每條邊與裁剪線的位置關系有4種情況(假設當前處理的多邊形的邊為SP):a>端點S在外側,P在內側,則從外到內輸出P和I;b>端點S和P都在內側,則從內到內輸出P;c>端點S在內側,而P在外側,則從內到外輸出I;d>端點S和P都在外側,無輸出。
3. 按裁剪精度的不同,字元裁剪可分為三種情況:字元串裁剪、字元裁剪和筆畫裁剪。
4. 在線段AB的編碼裁剪演算法中,如A、B兩點的碼邏輯或運算全為0,則該線段位於窗口內;如AB兩點的碼邏輯與運算結果不為0,則該線段在窗口外。
5. n邊多邊形關於矩形窗口進行裁剪,結果多邊形最多有2n個頂點,最少有n個頂點。
6. 對一條等長的直線段裁剪,編碼裁剪演算法的速度和中點分割演算法的裁剪速度哪一個快,無法確定。(√)
7. 多邊形裁剪可以看做是線段裁剪的組合。(X)
8. 對於線段來說,中點分割演算法要比其他線段裁剪演算法的裁剪速度快。(X)
9. 多邊形的Weiler-Atherton裁剪演算法可以實現對任意多邊形的裁剪。(√)
第四章
1. 幾何變換是指改變幾何形狀和位置,非幾何變換是指改變圖形的顏色、線型等屬性。變換方法有對象變換(坐標系不動)和坐標變換(坐標系變化)兩種。
2. 坐標系可以分為以下幾種:世界坐標系(是對計算機圖形場景中所有圖形對象的空間定位和定義,是其他坐標系的參照)、模型坐標系(用於設計物體的局部坐標系)、用戶坐標系(為了方便交互繪圖操作,可以變換角度、方向)、設備坐標系(是繪制或輸出圖形的設備所用的坐標系,採用左手系統)。
3. 將用戶坐標系中需要進行觀察和處理的一個坐標區域稱為窗口,將窗口映射到顯示設備上的坐標區域稱為視區。從窗口到視區的變換,稱為規格化變換。(eg.4-1)
4. 所謂體素,是指可以用有限個尺寸參數定位和定形的體,如長方體、圓錐體。
5. 所謂齊次坐標表示,就是用n+1維向量表示n維的向量。
6. 二維點(x,y)的齊次坐標可以表示為:(hx hy h),其中h≠0。當h=1時稱為規范化的齊次坐標,它能保證點集表示的唯一性。
7. 旋轉變換公式的推導、對稱變換

第五章
1. 交互繪圖技術是一種處理用戶輸入圖形數據的技術,是設計交互繪圖系統的基礎。常見的交互繪圖技術有:定位技術、橡皮筋技術、拖曳技術、定值技術、拾取技術、網格與吸附技術。
2. 常用的橡皮筋技術有:橡皮筋直線、橡皮筋矩形、橡皮筋圓。
3. 拖曳技術是將形體在空間移動的過程動態地、連續地表示出來,直到用戶滿意。
4. 定值技術有2種:一種是鍵入數值,另一種是改變電位計阻值產生要求的數量,可以用模擬的方式實現電位計功能。
5. 拾取一個基本的對象可以通過:指定名稱法、特徵點發、外界矩陣法、分類法、直接法。

第六章
1. 點、線、面是形成三維圖形的基礎,三維變換是從點開始。
2. 三維圖形變換分類:三維圖形變換包括三維幾何變換和平面幾何變換,三維幾何變換包括基本幾何變換和復合變換;平面幾何變換包括平行投影和透視投影,平行投影包括正投影和軸測投影,透視投影包括一點透視、二點透視、三點透視。
3. 投影中心與投影面之間的距離是無限的投影叫做平行投影,它包括正投影和軸測投影。
4. 正投影形成的視圖包括:主視圖、俯視圖和左視圖。軸測投影形成的視圖為軸測圖。
5. 透視投影也稱為中心投影,其投影中心與投影面之間的距離是有限的。其特點是產生近大遠小的視覺效果
6. 對於透視投影,不平行於投影面的平行線的投影會匯聚到一個點,這個點稱為滅點。透視投影的滅點有無限多個,與坐標軸平行的平行線在投影面上形成的滅點稱為主滅點。主滅點最多有3個,其對應的透視投影分別稱為一點透視、二點透視、三點透視。

第七章
1. 型值點是曲面或曲線上的點,而控制點不一定在曲線曲面上,控制點的主要目的是用來控制曲線曲面的形狀。
2. 插值和逼近是曲線曲面設計中的兩種不同方法。插值—生成的曲線曲面經過每一個型值點,逼近—生成的曲線曲面靠近每一個控制點。
3. 曲線曲面的表示要求:唯一性、統一性、幾何不變性、幾何直觀、易於界定、易於光滑連接。
4. 曲線曲面有參數和非參數表示,但參數表示較好。非參數表示又分為顯式和隱式兩種。
5. 對於一個平面曲線,顯式表示的一般形式是:y=f(x)。一個x與一個y對應,因此顯式方程不能表示封閉或多值曲線。例不能用顯式方程表示一個圓。
6. 如果一個曲線方程表示為f(x,y)=0的形式,我們稱之為隱式表示。其優點是易於判斷函數f(x,y)是否大於、小於或等於零,即易於判斷是落在所表示曲線上還是在曲線的哪一側。
7. 參數連續與幾何連續的區別:參數連續性是傳統意義上的、嚴格的連續,而幾何連續性只需限定兩個曲線段在交點處的參數導數成比例,不必完全相等,是一種更直觀、易於交互控制的連續性。
8. 在曲線曲面造型中,一般只用到C1(1階參數連續)、C2(2階參數連續)、G1(1階幾何連續)、G2(2階幾何連續)。切矢量(一階導數)反映了曲線對參數t的變化速遞,曲率(二階導數)反映了曲線對參數t變化的加速度。
9. 通常C1連續必能保證G1的連續,但G1的連續並不能保證C1連續。
10. 對於三次Hermite曲線,用於描述曲線的可供選擇的條件有:端點坐標、切矢量和曲率。
11. 三次Hermite曲線特點:①可局部調整,因為每個曲線段僅依賴於端點約束;②基於Hermite樣條的變化形式有Cardinal樣條和Kochanek-Bartels樣條;③具有幾何不變性。
12. Bezier曲線的性質:①端點性質②端點切矢量③端點的曲率④對稱性⑤幾何不變性⑥凸包性⑦變差縮減性。
13. 一次Bezier曲線是連接起點P0和終點P1的直線段,二次Bezier曲線對應一條起點P0終點在P2處的拋物線。
14. B樣條曲線的性質:①局部性②連續性或可微性③幾何不變性④嚴格凸包性⑤近似性⑥變差縮減性。
15. NURRS曲線具有以下性質:①局部性②可微性③仿射不變性④嚴格保凸性⑤一般性⑥變差縮減性⑦端點性質。

第八章
1. 要把三維物體的信息顯示在二維顯示設備中,必須通過投影變換。由於投影變換失去了深度信息,往往會導致二義性,要消除二義性,就必須在繪制時消除實際不可見的線和面,稱作消除隱藏線和隱藏面,簡稱消隱。
2. 面消隱常用演算法有:深度緩沖區(Z-buffer)演算法和深度排序演算法(畫家演算法)。
3. 深度緩沖區演算法和深度排序演算法的區別:

4. 3D游戲和2D游戲的製作方面那個難

你說的異常的難是指哪方面?

個人淺見:
2D難在素材和演算法。

比如說isometric對大物體的遮擋關系處理等,3D有了zbuffer,處理起來很簡單,2D演算法雖然速度比3D快,但因為缺少一個維度的數據,不存在完美的演算法,所以處理起來比較復雜。

即便是純2D,素材也是一個問題。因為手繪2D素材需要美術功力,成本比3D要高得多。雖然可以從3D生成2D, 但是可能達不到2D素材的質量。不過因為沒有硬體上的限制,渲染速度快,2D圖形可以做得看起來比3D的更為精美。

如果是引擎上的比較,一般只同2D和3D引擎做得是否易用有關,同2D/3D無關。

5. 等值面的等值面生成演算法

Cuberille方法
· Cuberrille等值面方法又稱Opaque Cube演算法,最初由Herman等人提出,後來又多次改進。演算法主要分為兩個步驟:
· (1) 確定邊界單元
對於規則網格數據,其網格單元可看成是正六面體單元,整個三維數據就是由這種正六面體組成的,這種組成三維圖象的基本正六面體單元稱為體元。對於給定的閾值Ft,遍歷體數據中的各個單元,將組成體元8個頂點上的值與Ft進行比較,找出頂點值跨越Ft的所有體元,即體元中有的頂點值大於閾值,有的頂點值小於閾值,因此體元內包含等值面片,這就是邊界單元。
(2) 繪制各邊界單元的6個多邊形面,即將等值面看成是由各單元的六個外表面拼合而成
每個單元均為一正六面體,包括6個多邊形面。對組成所有邊界體元的多邊形面進行繪制,即可產生最終的圖象結果。在繪制多邊形過程中應採用合適的光照模型和消隱技術。
如果在具有硬體深度緩存(Z-buffer)功能的計算機上運行立方體方法,可以將這組多邊形不分次序地提交給硬體,由硬體完成消除隱藏面的任務。如果以軟體方式執行立方體方法,在演算法中必須考慮多邊形的遮擋問題。一個有效的方法是把遍歷體元集合與顯示兩個步驟合二為一,遍歷體元集合時採用從後至前的次序。發現一個邊界體元,就立刻顯示它的6個面。後顯示到屏幕上去的多邊形將覆蓋先顯示的多邊形,這樣就達到了消除隱藏面的目的,這就是畫家演算法的思想。
Marching Cubes(MC)方法
Marching Cubes(移動立方體)方法是由W.E.Lorenson和H.E.Cline在1987年提出來的。由於這一方法原理簡單,易於實現,目前已經得到了較為廣泛的應用,成為三維數據等值面生成的經典演算法,Marching Cubes演算法又簡稱為MC演算法。MC方法的原理如下:
在Marching Cubes方法中,假定原始數據是離散的三維空間規則數據,一個體元定義為由相鄰層上的8個頂點組成的一個長方體。為了在三維數據中構造等值面,應先給定所求等值面的值,該方法的基本原理是逐個處理所有的體元,將體元各頂點處的值與給定的閾值進行比較,首先找出與等值面相交的體元,然後通過插值求等值面與體元棱邊的交點,並將各交點連成三角形來構成等值面片,所有體元中的三角形集合就構成了等值面。由於這一方法是逐個處理所有的體元,因此被稱為Marching Cubes方法。 在W.E.Lorenson和H.E.Cline於1987年提出Marching Cubes方法之後不久,他們就發現,當離散三維數據的密度很高時,由Marching Cubes方法在體元中產生的小三角面片常常很小,在圖像空間中的投影面積與屏幕上一個像素點的大小差不多,甚至還要小,因此,通過插值來計算小三角面片是不必要的。隨著新一代CT和MRI等設備的出現,二維切片中圖象的解析度不斷提高,斷層不斷變薄,已經接近並超過計算機屏幕顯示的解析度。在這種情況下,常用於三維表面生成的Marching Cubes方法已不適用。於是,在1988年,仍由W.E.Lorenson和H.E.Cline兩人提出了剖分立方體(Dividing Cubes)方法。

6. Unity Shader-渲染隊列,ZTest,ZWrite,Early-Z(轉)

簡介

在渲染階段,引擎所做的工作是把所有場景中的對象按照一定的策略(順序)進行渲染。最早的是畫家演算法,顧名思義,就是像畫家畫畫一樣,先畫後面的物體,如果前面還有物體,那麼就用前面的物體把物體覆蓋掉,不過這種方式由於排序是針對物體來排序的,而物體之間也可能有重疊,所以效果並不好。所以目前更加常用的方式是z-buffer演算法,類似顏色緩沖區緩沖顏色,z-buffer中存儲的是當前的深度信息,對於每個像素存儲一個深度值,這樣,我們屏幕上顯示的每個像素點都會進行深度排序,就可以保證繪制的遮擋關系是正確的。而控制z-buffer就是通過ZTest,和ZWrite來進行。但是有時候需要更加精準的控制不同類型的對象的渲染順序,所以就有了渲染隊列。今天就來學習一下渲染隊列,ZTest,ZWrite的基本使用以及分析一下Unity為了Early-Z所做的一些優化。

Unity中的幾種渲染隊列

首先看一下Unity中的幾種內置的渲染隊列,按照渲染順序,從先到後進行排序,隊列數越小的,越先渲染,隊列數越大的,越後渲染。

Unity中設置渲染隊列也很簡單,我們不需要手動創建,也不需要寫任何腳本,只需要在shader中增加一個Tag就可以了,當然,如果不加,那麼就是默認的渲染隊列Geometry。比如我們需要我們的物體在Transparent這個渲染隊列中進行渲染的話,就可以這樣寫:

我們可以直接在shader的Inspector面板上看到shader的渲染隊列:

另外,我們在寫shader的時候還經常有個Tag叫RenderType,不過這個沒有Render Queue那麼常用,這里順便記錄一下:
Opaque : 用於大多數著色器(法線著色器、自發光著色器、反射著色器以及地形的著色器)。
Transparent :用於半透明著色器(透明著色器、粒子著色器、字體著色器、地形額外通道的著色器)。
TransparentCutout : 蒙皮透明著色器(Transparent Cutout,兩個通道的植被著色器)。
Background : 天空盒著色器。
Overlay : GUITexture,鏡頭光暈,屏幕閃光等效果使用的著色器。
TreeOpaque : 地形引擎中的樹皮。
TreeTransparentCutout : 地形引擎中的樹葉。
TreeBillboard : 地形引擎中的廣告牌樹。
Grass : 地形引擎中的草。
GrassBillboard : 地形引擎何中的廣告牌草。

相同渲染隊列中不透明物體的渲染順序

拿出Unity,創建三個立方體,都使用默認的bump diffuse shader(渲染隊列相同),分別給三個不同的材質(相同材質的小頂點數的物體引擎會動態合批),用Unity5帶的Frame Debug工具查看一下Draw Call。(Unity5真是好用得多了,如果用4的話,還得用NSight之類的抓幀)

可以看出,Unity中對於不透明的物體,是採用了從前到後的渲染順序進行渲染的,這樣,不透明物體在進行完vertex階段,進行Z Test,然後就可以得到該物體最終是否在屏幕上可見了,如果前面渲染完的物體已經寫好了深度,深度測試失敗,那麼後面渲染的物體就直接不會再去進行fragment階段。(不過這里需要把三個物體之間的距離稍微拉開一些,本人在測試時發現,如果距離特別近,就會出現渲染次序比較亂的情況,因為我們不知道Unity內部具體排序時是按照什麼標准來判定的哪個物體離攝像機更近,這里我也就不妄加猜測了)

相同渲染隊列中半透明物體的渲染順序

透明物體的渲染一直是圖形學方面比較蛋疼的地方,對於透明物體的渲染,就不能像渲染不透明物體那樣多快好省了,因為透明物體不會寫深度,也就是說透明物體之間的穿插關系是沒有辦法判斷的,所以半透明的物體在渲染的時候一般都是採用從後向前的方法進行渲染,由於透明物體多了,透明物體不寫深度,那麼透明物體之間就沒有所謂的可以通過深度測試來剔除的優化,每個透明物體都會走像素階段的渲染,會造成大量的Over Draw。這也就是粒子特效特別耗費性能的原因。

我們實驗一下Unity中渲染半透明物體的順序,還是上面的三個立方體,我們把材質的shader統一換成粒子最常用的Particle/Additive類型的shader,再用Frame Debug工具查看一下渲染的順序:

半透明的物體渲染的順序是從後到前,不過由於半透相關的內容比較復雜,就先不在這篇文章中說了,打算另起一篇。

自定義渲染隊列

Unity支持我們自定義渲染隊列,比如我們需要保證某種類型的對象需要在其他類型的對象渲染之後再渲染,就可以通過自定義渲染隊列進行渲染。而且超級方便,我們只需要在寫shader的時候修改一下渲染隊列中的Tag即可。比如我們希望我們的物體要在所有默認的不透明物體渲染完之後渲染,那麼我們就可以使用Tag{「Queue」 = 「Geometry+1」}就可以讓使用了這個shader的物體在這個隊列中進行渲染。

還是上面的三個立方體,這次我們分別給三個不同的shader,並且渲染隊列不同,通過上面的實驗我們知道,默認情況下,不透明物體都是在Geometry這個隊列中進行渲染的,那麼不透明的三個物體就會按照cube1,cube2,cube3進行渲染。這次我們希望將渲染的順序反過來,那麼我們就可以讓cube1的渲染隊列最大,cube3的渲染隊列最小。貼出其中一個的shader:

其他的兩個shader類似,只是渲染隊列和輸出顏色不同。

通過渲染隊列,我們就可以自由地控制使用該shader的物體在什麼時機渲染。比如某個不透明物體的像素階段操作較費,我們就可以控制它的渲染隊列,讓其渲染更靠後,這樣可以通過其他不透明物體寫入的深度剔除該物體所佔的一些像素。

PS:這里貌似發現了個問題,我們在修改shader的時候一般不需要什麼其他操作就可以直接看到修改後的變化,但是本人改完渲染隊列後,有時候會出現從shader的文件上能看到渲染隊列的變化,但是從渲染結果以及Frame Debug工具中並沒有看到渲染結果的變化,重啟Unity也沒有起到作用,直到我把shader重新賦給材質之後,變化才起了效果...(猜測是個bug,因為看到網上還有和我一樣的倒霉蛋被這個坑了,本人的版本是5.3.2,害我差點懷疑昨天是不是喝了,剛實驗完的結果就完全不對了...)

**ZTest(深度測試)和ZWrite(深度寫入) **

上一個例子中,雖然渲染的順序反了過來,但是物體之間的遮擋關系仍然是正確的,這就是z-buffer的功勞,不論我們的渲染順序怎樣,遮擋關系仍然能夠保持正確。而我們對z-buffer的調用就是通過ZTest和ZWrite來實現的。

首先看一下ZTest,ZTest即深度測試,所謂測試,就是針對當前對象在屏幕上(更准確的說是frame buffer)對應的像素點,將對象自身的深度值與當前該像素點緩存的深度值進行比較,如果通過了,本對象在該像素點才會將顏色寫入顏色緩沖區,否則否則不會寫入顏色緩沖。ZTest提供的狀態較多。 ZTest Less(深度小於當前緩存則通過, ZTest Greater(深度大於當前緩存則通過),ZTest LEqual(深度小於等於當前緩存則通過),ZTest GEqual(深度大於等於當前緩存則通過),ZTest Equal(深度等於當前緩存則通過),ZTest NotEqual(深度不等於當前緩存則通過),ZTest Always(不論如何都通過)。注意,ZTest Off等同於ZTest Always,關閉深度測試等於完全通過。

下面再看一下ZWrite,ZWrite比較簡單,只有兩種狀態, ZWrite On(開啟深度寫入)和ZWrite Off(關閉深度寫入) 。當我們開啟深度寫入的時候,物體被渲染時針對物體在屏幕(更准確地說是frame buffer)上每個像素的深度都寫入到深度緩沖區;反之,如果是ZWrite Off,那麼物體的深度就不會寫入深度緩沖區。但是,物體是否會寫入深度,除了ZWrite這個狀態之外,更重要的是需要深度測試通過,也就是ZTest通過,如果ZTest都沒通過,那麼也就不會寫入深度了。就好比默認的渲染狀態是ZWrite On和ZTest LEqual,如果當前深度測試失敗,說明這個像素對應的位置,已經有一個更靠前的東西佔坑了,即使寫入了,也沒有原來的更靠前,那麼也就沒有必要再去寫入深度了。所以上面的ZTest分為通過和不通過兩種情況,ZWrite分為開啟和關閉兩種情況的話,一共就是四種情況:

1.深度測試通過,深度寫入開啟:寫入深度緩沖區,寫入顏色緩沖區;
2.深度測試通過,深度寫入關閉:不寫深度緩沖區,寫入顏色緩沖區;
3.深度測試失敗,深度寫入開啟:不寫深度緩沖區,不寫顏色緩沖區;
4.深度測試失敗,深度寫入關閉:不寫深度緩沖區,不寫顏色緩沖區;

Unity中默認的狀態(寫shader時什麼都不寫的狀態)是ZTest LEqual和ZWrite On,也就是說默認是開啟深度寫入,並且深度小於等於當前緩存中的深度就通過深度測試,深度緩存中原始為無限大,也就是說離攝像機越近的物體會更新深度緩存並且遮擋住後面的物體。如下圖所示,前面的正方體會遮擋住後面的物體:

寫幾個簡單的小例子來看一下ZTest,ZWrite以及Render Queue這幾個狀態對渲染結果的控制。

讓綠色的對象不被前面的立方體遮擋,一種方式是關閉前面的藍色立方體深度寫入:

通過上面的實驗結果,我們知道,按照從前到後的渲染順序,首先渲染藍色物體,藍色物體深度測試通過,顏色寫入緩存,但是關閉了深度寫入,藍色部分的深度緩存值仍然是默認的Max,後面渲染的綠色立方體,進行深度測試仍然會成功,寫入顏色緩存,並且寫入了深度,因此藍色立方體沒有起到遮擋的作用。
另一種方式是讓綠色強制通過深度測試:

這個例子中其他立方體的shader使用默認的渲染方式,綠色的將ZTest設置為Always,也就是說不管怎樣,深度測試都通過,將綠色立方體的顏色寫入緩存,如果沒有其他覆蓋了,那麼最終的輸出就是綠色的了。

那麼如果紅色的也開了ZTest Always會怎麼樣?

在紅色立方體也用了ZTest Always後,紅色遮擋了綠色的部分顯示為了紅色。如果我們換一下渲染隊列,讓綠色在紅色之前渲染,結果就又不一樣了:

更換了渲染隊列,讓綠色的渲染隊列+1,在默認隊列Geometry之後渲染,最終重疊部分又變回了綠色。可見,當ZTest都通過時,上一個寫入顏色緩存的會覆蓋上一個,也就是說最終輸出的是最後一個渲染的對象顏色。

再看一下Greater相關的部分有什麼作用,這次我們其他的都使用默認的渲染狀態,綠色的立方體shader中ZTest設置為Greater:

這個效果就比較好玩了,雖然我們發現在比較深度時,前面被藍色立方體遮擋的部分,綠色的最終覆蓋了藍色,是想要的結果,不過其他部分哪裡去了呢?簡單分析一下,渲染順序是從前到後,也就是說藍色最先渲染,默認深度為Max,藍色立方體的深度滿足LEqual條件,就寫入了深度緩存,然後綠色開始渲染,重疊的部分的深度緩存是藍色立方體寫入的,而綠色的深度值滿足大於藍色深度的條件,所以深度測試通過,重疊部分顏色更新為綠色;而與紅色立方體重合的部分,紅色立方體最後渲染,與前面的部分進行深度測試,小於前面的部分,深度測試失敗,重疊部分不會更新為紅色,所以重疊部分最終為綠色。而綠色立方體沒有與其他部分重合的地方為什麼消失了呢?其實是因為綠色立方體渲染時,除了藍色立方體渲染的地方是有深度信息的,其他部分的深度信息都為Max,藍色部分用Greater進行判斷,肯定會失敗,也就不會有顏色更新。
有一個好玩的效果其實就可以考ZTest Greater來實現,就是游戲裡面經常出現的,當玩家被其他場景對象遮擋時,遮擋的部分會呈現出X-光的效果;其實是在渲染玩家時,增加了一個Pass,默認的Pass正常渲染,而增加的一個Pass就使用Greater進行深度測試,這樣,當玩家被其他部分遮擋時,遮擋的部分才會顯示出來,用一個描邊的效果渲染,其他部分仍然使用原來的Pass即可。

Early-Z技術

傳統的渲染管線中,ZTest其實是在Blending階段,這時候進行深度測試,所有對象的像素著色器都會計算一遍,沒有什麼性能提升,僅僅是為了得出正確的遮擋結果,會造成大量的無用計算,因為每個像素點上肯定重疊了很多計算。因此現代GPU中運用了Early-Z的技術,在Vertex階段和Fragment階段之間(光柵化之後,fragment之前)進行一次深度測試,如果深度測試失敗,就不必進行fragment階段的計算了,因此在性能上會有很大的提升。但是最終的ZTest仍然需要進行,以保證最終的遮擋關系結果正確。前面的一次主要是Z-Cull為了裁剪以達到優化的目的,後一次主要是Z-Check,為了檢查,如下圖:

Early-Z的實現,主要是通過一個Z-pre-pass實現,簡單來說,對於所有不透明的物體(透明的沒有用,本身不會寫深度),首先用一個超級簡單的shader進行渲染,這個shader不寫顏色緩沖區,只寫深度緩沖區,第二個pass關閉深度寫入,開啟深度測試,用正常的shader進行渲染。其實這種技術,我們也可以借鑒,在渲染透明物體時,因為關閉了深度寫入,有時候會有其他不透明的部分遮擋住透明的部分,而我們其實不希望他們被遮擋,僅僅希望被遮擋的物體半透,這時我們就可以用兩個pass來渲染,第一個pass使用Color Mask屏蔽顏色寫入,僅寫入深度,第二個pass正常渲染半透,關閉深度寫入。

關於Early-Z技術可以參考ATI的論文Applications of Explicit Early-Z Culling以及PPT,還有一篇Intel的文章。

Unity渲染順序總結

如果我們先繪制後面的物體,再繪制前面的物體,就會造成over draw;而通過Early-Z技術,我們就可以先繪制較近的物體,再繪制較遠的物體(僅限不透明物體),這樣,通過先渲染前面的物體,讓前面的物體先佔坑,就可以讓後面的物體深度測試失敗,進而減少重復的fragment計算,達到優化的目的。Unity中默認應該就是按照最近距離的面進行繪制的,我們可以看一下Unity官方的文檔中顯示的:

從文檔給出的流程來看,這個Depth-Test發生在Vertex階段和Fragment階段之間,也就是上面所說的Early-Z優化。
簡單總結一下Unity中的渲染順序: 先渲染不透明物體,順序是從前到後;再渲染透明物體,順序是從後到前

Alpha Test(Discard)在移動平台消耗較大的原因

從本人剛剛開始接觸渲染,就開始聽說移動平台Alpha Test比較費,當時比較納悶,直接discard了為什麼會費呢,應該更省才對啊?這個問題困擾了我好久,今天來刨根問底一下。還是跟我們上面講到的Early-Z優化。正常情況下,比如我們渲染一個面片,不管是否是開啟深度寫入或者深度測試,這個面片的光柵化之後對應的像素的深度值都可以在Early-Z(Z-Cull)的階段判斷出來了;而如果開啟了Alpha Test(Discard)的時候,discard這個操作是在fragment階段進行的,也就是說這個面片光柵化之後對應的像素是否可見,是在fragment階段之後才知道的,最終需要靠Z-Check進行判斷這個像素點最終的顏色。其實想像一下也能夠知道,如果我們開了Alpha Test並且還用Early-Z的話,一塊本來應該被剃掉的地方,就仍然寫進了深度緩存,這樣就會造成其他部分被一個完全沒東西的地方遮擋,最終的渲染效果肯定就不對了。所以,如果我們開啟了Alpha Test,就不會進行Early-Z,Z Test推遲到fragment之後進行,那麼這個物體對應的shader就會完全執行vertex shader和fragment shader,造成over draw。有一種方式是使用Alpha Blend代替Alpha Test,雖然也很費,但是至少Alpha Blend雖然不寫深度,但是深度測試是可以提前進行的,因為不會在fragment階段再決定是否可見,因為都是可見的,只是透明度比較低罷了。不過這樣只是權宜之計,Alpha Blend並不能完全代替Alpha Test。

關於Alpha Test對於Power VR架構的GPU性能的影響,簡單引用一下官方的鏈接以及一篇討論帖:

最後再附上兩篇參考文章

http://blog.csdn.net/candycat1992/article/details/41599167
http://blog.csdn.net/arundev/article/details/7895839

閱讀全文

與zbuffer演算法相關的資料

熱點內容
一個男的看女生洗澡電影 瀏覽:291
虛擬幣充值源碼 瀏覽:87
我昨天看了航天電影英文翻譯 瀏覽:175
熙和宇電影高級家庭 瀏覽:236
主角10歲收了母親的小說 瀏覽:544
女獄電影日本 瀏覽:154
二龍湖浩哥最早的作品 瀏覽:699
異界收母入後宮 瀏覽:155
ida反編譯出來的代碼是匯編指令嗎 瀏覽:820
小孩子是天才的電影 瀏覽:450
輿情監控演算法 瀏覽:147
好看123電影 瀏覽:751
成龍主演的五行拳電影名字 瀏覽:954
好看的中文字幕經典 瀏覽:913
android仿qq輸入 瀏覽:117
看輕小說的網站 瀏覽:86
命令與征服3戰役存檔 瀏覽:147
台灣風月影片 瀏覽:326
彭偶么電視劇電影大全 瀏覽:291
重生井岡山林楓 瀏覽:519