深度緩衝優化指南

最近涉足一點移動開發,倒是剛上來就被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帶到溝里去?
新成立的遊戲外包公司怎樣尋找客戶?
為什麼國內做不出《皇室戰爭》這樣的遊戲?

TAG:计算机图形学 | 游戏开发 | 手机游戏开发 |