Thursday, October 7, 2010

Z prepass & alpha test

我想我終於真正領悟了Z prepass renderer的奧義,我們的場景裡如果有很多alpha test的物件例如樹的話,效能常常會下降很多,這是因為alpha test的物件沒辦法有early Z,所以所有的pixels都會執行pixel shader,但如果在Z prepass架構下:

第一個pass用最簡單的shader,開啟alpha test,把樹的Z值寫到Z buffer。
第二個pass執行真正的複雜的shader,Z function用equal,然後把alpha test關掉,因為Z test已經可以把樹刻出來拉,如此複雜的shader就有了early Z的效果。

今天測試了一下,有些樹的效能可以從0.7ms提升到0.2ms以下。當然,樹如果用了alpha to coverage,這個方法就沒辦法用了,幸好我們的場景沒有這種樹。

4 comments:

Silent Wolf 18 said...

請問 early z 的觸發條件是什麼?

ianslayer said...

依據nvidia GPU Programming Guide Version for GeForce 8 and later GPUs
section 4.8,early Z會沒有作用的情況是以下
1. If the pixel shader outputs depth

2. If the pixel shader uses the .z component of an input attribute with the
SV_Position semantic (only on GeForce 8 series in D3D10)

3. If Depth or Stencil writes are enabled, or Occlusion Queries are
enabled, and one of the following is true:
• Alpha-test is enabled
• Pixel Shader kills pixels (clip(), texkil, discard)
• Alpha To Coverage is enabled
• SampleMask is not 0xFFFFFFFF (SampleMask is
D3D10 using OMSetBlendState and in D3D9 setting
D3DRS_MULTISAMPLEMASK renderstate)

ianslayer said...

比起early Z,Z cull(hierarchical z buffer)的條件可能更嚴苛,因為只要一個render的物件違反了條件(例如z test function方向改變了),z cull最佳化就會完全關閉,直到下一次清z buffer之後才會再開啟。

ianslayer said...

恩,所以看起來開啟alpha to coverage也可以有early z,一樣只要depth write關掉,有開depth test就可以(假設z buffer裡面已經有東西的話)...這樣對嗎?