在超大型場景下,遠*裁剪*面一半要很遠的距離,使用普通的深度緩衝經常會因為誤差,造成一些很難看的鋸齒,本來不相交的圖元相互穿透,z-fighting等現象。
普通的z/w深度緩衝,深度值不是線性的。在*處,深度比較精確,所使用的深度區間也比較大。在遠處,僅會使用很小一部分深度區間,誤差就會變得很大,產生難看的現象。
例如,在*裁剪*面為10,遠裁剪*面為10000時:
zz/w深度
90.09009
0.900901
490.4905
0.980981
990.991
0.990991
10000
1.0可見*處的所用到的區間大,90以內的就用了0-0.9,越遠越小,精度越低。
一種辦法就是將深度轉化為線性的,在d3d中用shader自己算乙個深度。
由於z最終會被除以w,所以,可以在vs中,完成worldviewproj之後,先對z上乘以w,等最後被除以w的時候,就相當於什麼事情也沒有發生。
當然,也要除以遠裁剪*面距離。使深度值對映到0-1之間。也可以通過修改投影矩陣來完成。
線性的深度分布,會使遠處和*處的精度一樣。即傳說中的w緩衝。在超大場景下,遠處就沒有那麼多鋸齒了。但是,這樣有時候,*處的精度就會不足。
還有一種辦法就是在vs中用對數計算深度。
公式z = log(c*z + 1) / log(c*far + 1) * w
其中,c是常量,不同的值,會影響深度的精度。
在z處的解析度為
log(c*far + 1) / (2^n * c/(c*z+1))
一下是乙個參考的精度表,使用24位深度緩衝,遠裁剪*面10000km110
1001k
10k100k
1m10m
c=11.9e-6
1.1e-5
9.7e-5
0.001
0.01
0.096
0.96
9.6c=0.001
0.0005
0.0005
0.0006
0.001
0.006
0.055
0.549
5.49
使用對數深度問題是深度是被線性插值的,而不是對數。所以網格必須足夠精確……或者直接在ps中算深度,不是很費效能,如果可以接受的話……
這種辦法效果非常好,做真實比例的星球系統沒啥問題。
使用這些非標準的深度,雖然效果好,但也是有壞處的。
首先,普通z/w深度,在螢幕空間是線性的,如圖所示:
這是使用ddx和ddy對z/w深度求的導數圖。
由顏色相同可以看出,深度是線性的(在螢幕空間)。原始為無損png,可以用畫圖顏料桶測試顏色是否相同。
對線性深度使用相同辦法,效果如圖。
可見是非線性的。
這對於一些基於螢幕空間深度的post effect來說不利。例如ssao,hdao,景深等。
深度緩衝區
深度緩衝區是direct3d用來儲存繪製到螢幕上每乙個畫素點的深度資訊的 塊記憶體緩衝區。它為每個畫素儲存乙個深度值 z值 這個深度值是從攝像機到對應該畫素點的頂點之間的距離。深度緩衝區的大小和顏色緩衝區 frame buffer 的大小一致。例如 如果要繪製乙個640 480解析度的,則在深度緩衝...
反向Z Reversed Z 的深度緩衝原理
參考文章 在數學中,與浮點數對應的是小數 數學上區間 0,1 之間的小數有無窮多個 計算機中,32位浮點數最多可以表示2 32個數 所以,計算機是不可能描述得盡的,必然會有一些近似,一些精度所示 當前,計算機中浮點數採用的是ieee 754標準。浮點數分為單精度浮點數 32位 和雙精度浮點數 64位...
深度緩衝中的深度值計算及視覺化
在渲染管線中的頂點變換中,介紹了頂點在各個座標空間的變換。變換到最後,是螢幕座標空間。在opengl中,螢幕空間座標的z值即是深度緩衝中的深度值。深度緩衝包含了乙個介於0.0和1.0之間的深度值,它將會與觀察者視角所看見的場景中所有物體的z值進行比較。本文將介紹深度值的計算,以及從深度值反向計算出相...