深度緩衝優化指南
最近涉足一點移動開發,倒是剛上來就被OPENGL系的深度問題給噁心壞了。由於unity無法拿到移動平台上硬體做的z-buffer,所以大家常規做法就是自己去寫個z-buffer。但是由於經過透視變換,透視本質上是不保持深度的線性變化的,結果很多利用深度的「奇技淫巧」在PC上用著沒問題,在手機上就有毛病了。Nathan Reed[1]對這個問題做過一次深入研究,評測了幾種緩解這個問題的方法。其中圖示了集中Z值保存方法,可以直觀看到精度的損失:
當使用整數值保存深度,已經可以看到z值在已經是在近剪裁面的精度比遠剪裁面要高。
當我們把近剪裁面進一步縮小後,只是改變了距離相機位置附近的精度分布:
當我們把遠剪裁面拉的更遠,其實對整個深度分布影響不大:
接著我們再看看浮點數保存深度時候的分布:
主要還是近距離的精度達到不必要的高,遠距離又太粗糙。
所以Eugene Lapidous[2], Matt Pettineo [3] 和 Brano Kemen[4]等人就想出了使用ReverseZ的方法保存精度:
對比之前已經有了翻天覆地的變化。你以為這是童話故事的happy ending? NO!
由於目前我在做移動平台的東西,所以我們看看GL系是有多麼的非主流:
居然精度都集中在一個「中間距離」,這就是為什麼unity里你如果自己寫深度,調相機的far沒啥變化,調near從0.1到1變化巨大。桌面級別的OPEN GL可以用 ARB_clip_control ,但是GLES就沒啥招了,由於「貴系」使用[-1,1]保存透視變換後的z值,即便後來硬體幫你映射到[0,1]也無事於補。原因是透視變化里已經把數值玩壞。。。
所以我們就放棄GLES吧?
...
開個玩笑,換個方法,直接保存Z,不做透視變換,還是可以搞滴!
2017年9月9日更新:深度緩衝優化指南-後續
[1]Depth Precision Visualized, Nathan Reed, 2015
[2]Optimal depth buffer for low-cost graphics hardware, Eugene Lapidous,Guofang Jiao, HWWS 99 Proceedings of the ACM SIGGRAPH/EUROGRAPHICS workshop on Graphics hardwarePages 67-73
[3]ATTACK OF THE DEPTH BUFFER, Matt Pettineo, 2010
[4]Maximizing Depth Buffer Range and Precision, Brano Kemen, 2012
推薦閱讀:
※在日本公司做手游,能賺多少?
※他們禁遊戲機的時候,我沒有說話
※Cocos2d-x 會不會被 Creator帶到溝里去?
※新成立的遊戲外包公司怎樣尋找客戶?
※為什麼國內做不出《皇室戰爭》這樣的遊戲?