z pre-pass
是指在渲染流程中,第一個pass先畫一張深度buffer出來,得到需要繪制的最前面這層深度,用這個在接下來的pass中做深度剔出,這樣在第二個pass中會省略很多繪制。
這項技術在渲染透明物體時可以的到理想結果。因為有了這層深度剔除,透明物體內部的錯亂的內部結構就不會顯示出來。
有關z pre-pass 的效率問題,實際上並不那么樂觀。
http://casual-effects.blogspot.hk/2013/08/z-prepass-considered-irrelevant.html
http://www.gamedev.net/topic/641257-depth-pre-pass-worth-it/
這兩位作者都做了測試,前者測試相當嚴格。結論是z pre-pass在forward+基本沒有效率提升。
z pre-pass在第一個pass有從vertexshader到rasterize的開銷。這個和后面用這張depth buffer剔除后面的繪制節省的開銷在很多情況下是互相抵消,基本沒多少優勢。我想這也是AC2關掉z pre-pass的原因。但這會導致透明物體渲染次序的問題。
front-to-back
是指渲染opaque物體時從前向后畫,開深度測試,這樣后面的物體被前面物體遮住的部分就會被剔除,效率得到提升。
合並批次
是指把渲染狀態相同的batch,頂點數據合並起來提交。一次繪制出來,減少drawcall的調用次數,進而也提升了效率。判斷是否需要合並是通過batch的填充率滿不滿來決定的。如果batchsize不滿,又是同樣render state的批次,就應該合並起來。
但front-to-back 和合並批次有個矛盾的地方在於同樣渲染狀態的物體,比如一種類型的草,它們通常位於場景的各個位置,如果嚴格由近及遠畫,就會導致渲染狀態反復被切換,就無法合並批次了。
針對這個問題,zxy和chenzhe討論得出一個觀點,如果做了z pre-pass就不需要 front-to-back 這樣就可以合並批次了。
之前得到大家的一致認同,但后來我看了上述兩篇文章意識到上述觀點有如下問題:
z pre-pass繪制的時候 如果可以做front-to-back 也是可以極大提升這個階段效率的,這是我們在討論過程中一直忽視的一個問題。z pre-pass 和 front-to-back不是互斥的。
討論的時候忽視了z pre-pass在第一個pass有從vertexshader到rasterize的開銷。雖然是很簡單的ps,從上文兩個連接測試來看,前面這部分vs的開銷也不少。
綜述,z pre-pass加合並批次不見得是最優解。個人傾向在front-to-back和合並批次之間取個折中,即不那么嚴格的front-to-back排序。
引用Morgan McGuire (G3D作者)的話:
In other words, the z-prepass may be irrelevant in modern rendering systems that submit many draw calls for well-sorted objects,
and ispotentially harmful as tessellation (and thus rasterizer setup) and skinning workloads increase.
歡迎提出意見。