【技術(shù)美術(shù)百人計劃】Early-Z 和 Z-prepass
一、深度測試DepthTest

深度測試是為了解決物體可見遮擋性的問題。




二、提前深度測試Early-Z


Early-Z階段不僅可以進(jìn)行深度測試,同樣可以添加模板測試
Early-Z失效
開啟AlphaTest或clip/discard等丟棄片元操作
手動修改GPU插值得到的深度
開啟AlphaBlend
關(guān)閉深度測試DepthTest

因此為了達(dá)到最大的優(yōu)化效果,就要從近到遠(yuǎn)進(jìn)行渲染,可以通過cpu將物體按據(jù)攝像機(jī)近平面由近到遠(yuǎn)進(jìn)行排序后,再交付cpu進(jìn)行渲染。但是當(dāng)場景十分復(fù)雜時,頻繁的排序操作將消耗cpu的性能;并且如果嚴(yán)格按照由近及遠(yuǎn)進(jìn)行渲染的話,無法同時搭配合批優(yōu)化手段
Z-prepass便是用來解決這個問題的
三、使用Z-Prepass
方式1:雙Pass
第一個Pass即Z-Prepass只寫入深度,不計算顏色
第二個Pass關(guān)閉深度寫入并且將深度比較設(shè)為相等

動態(tài)批處理問題
一個物體擁有多個Pass的shader是無法進(jìn)行動態(tài)批處理的,這也就會帶來DrawCall的問題。

方式2:提前分離的Prepass
仍然使用兩個Pass,但:
將第一個Pass(Z-Prepass)單獨(dú)分離出來作為一個單獨(dú)的shander,并先使用這個shader對整個場景的Opaque物體渲染一遍
第二個Pass仍關(guān)閉深度寫入,深度比較函數(shù)設(shè)為相等


四、Z-Prepass所帶來的問題

Z-prepass并不是一個一成不變的決策,而是要根據(jù)實際項目情況來自行判斷是否采用。比如說有一個場景,有非常多的overdraw并且沒辦法很好的將透明物體從前往后進(jìn)行排序,那么此時Z-prepass的計算消耗是遠(yuǎn)小于這些overdraw的消耗的
Early-Z和Z-Prepass的實際應(yīng)用
頭發(fā)是層疊的半透明面片,需要從后往前進(jìn)行渲染才能得到正確的透明度混合結(jié)果

普通的渲染方法是先將不透明的部分渲染出來,再渲染透明部分的背面和正面
這種渲染方式會產(chǎn)生非常多的overdraw,因此需要用early-Z進(jìn)行剔除。但是Early-Z不能啟用透明度測試,因此需要額外用一個pass進(jìn)行透明度測試來形成Z-buffer,即使用Z-prepass

Early-Z的局限性
Early-Z是硬件支持的功能,圖形API無法決定是否進(jìn)行
如果進(jìn)行了Alpha Clip或者深度寫入,會造成Early-Z失效
Early-Z通常是通過preZ來實現(xiàn)的,但是在DrawCall特別高的場景里使用preZ會造成負(fù)優(yōu)化
如果開啟了Alpha Test(Discard),導(dǎo)致Early-Z失效,即使被遮擋也一定會進(jìn)行Pixel計算; 與之相對的Alpha Blend卻可以進(jìn)行正確的Early計算