Depth-Buffer(深度緩存)有兩種:Z-Buffer 和 W-Buffer,這里討論這兩種深度緩存的區(qū)別,以及如何在兩者之間轉(zhuǎn)換。
w 的含義
3D空間點的坐標(biāo)是(x,y,z),為了使矩陣乘法具有平移變換的功效,我們用4D空間中的點(x,y,z,w)來表示3D空間中的點(x',y',z'),這兩個不同空間點之間的關(guān)系是:
x' = x / w
y' = y / w
z' = z / w
像這樣用四維空間點表示三維空間點,或者說用 n + 1 維空間點表示 n 維空間點的方法叫做 “齊次坐標(biāo)表示法”。
實際使用中,在模型->世界轉(zhuǎn)換、世界->視圖轉(zhuǎn)換過程中,w 通常保持不變,總是等于一,這樣,齊次坐標(biāo)的前三個分量就是對應(yīng)3D空間點的三個坐標(biāo)分量。但是,經(jīng)過投影變換后,w 將得到一個比例值,比如,一般的透視投影變換矩陣是:
| W 0 0 0 |
| 0 H 0 0 |
| 0 0 Q 1 |
| 0 0 -QZn 0 |
其中 Zn = 近裁剪面 z 坐標(biāo)
Zf = 遠(yuǎn)裁剪面 z 坐標(biāo)
W = 2 * Zn / 視口寬度
H = 2 * Zn / 視口高度
Q = Zf / (Zf - Zn)
將點(x,y,z,1)乘以此矩陣,w 便不再是一,而對應(yīng)的3D空間點坐標(biāo)(x / w,y / w,z / w)將出現(xiàn)一個縮放效果。同時,因為 w 的值通常與 z 坐標(biāo)成正比(比如經(jīng)過上面這個矩陣的變換,w 的值其實就是 z 坐標(biāo)的值),所以經(jīng)過投影變換,物體會產(chǎn)生近大遠(yuǎn)小的效果。
Z-Buffer 與 W-Buffer 的區(qū)別
簡單的說,z-buffer 與 w-buffer 的區(qū)別就是前者保存的是點的 z 坐標(biāo),而后者保存的是點的 w 坐標(biāo)。
具體的說,兩者因為保存的值有不同的含義,所以表現(xiàn)出來的實際效果也會有差別。
z-buffer 保存的是經(jīng)過投影變換后的 z 坐標(biāo),前面說過,投影后物體會產(chǎn)生近大遠(yuǎn)小的效果,所以距離眼睛比較近的地方,z 坐標(biāo)的分辨率比較大,而遠(yuǎn)處的分辨率則比較小,換句話說,投影后的 z 坐標(biāo)在其值域上,對于離開眼睛的物理距離變化來說,不是線性變化的(即非均勻分布),這樣的一個好處是近處的物體得到了較高的深度分辨率,但是遠(yuǎn)處物體的深度判斷可能會出錯。
w-buffer 保存的是經(jīng)過投影變換后的 w 坐標(biāo),而 w 坐標(biāo)通常跟世界坐標(biāo)系中的 z 坐標(biāo)成正比,所以變換到投影空間中之后,其值依然是線性分布的,這樣無論遠(yuǎn)處還是近處的物體,都有相同的深度分辨率,這是它的優(yōu)點,當(dāng)然,缺點就是不能用較高的深度分辨率來表現(xiàn)近處的物體。
從硬件實現(xiàn)角度來說,幾乎所有的硬件3D加速卡都支持 z-buffer,而 w-buffer 的支持沒有 z-buffer 那么廣泛。另外,早期的 Direct3D 版本看起來也不支持 w-buffer。
Z-Buffer 與 W-Buffer 之間的轉(zhuǎn)換
根據(jù)上面的矩陣變換,可以很容易的導(dǎo)出將 w-buffer 轉(zhuǎn)換成 z-buffer 的公式:
zDepth = Q * ( wDepth - Zn ) / wDepth
= Zf / ( Zf - Zn ) * ( wDepth - Zn ) / wDepth
這個轉(zhuǎn)換公式有什么用處?舉個例子:3DS MAX 使用的是 w-buffer,如果從 3DS MAX 中導(dǎo)出深度信息到 Direct3D 中,作為預(yù)渲染的背景使用,就有可能用到上面這個轉(zhuǎn)換。當(dāng)然,如果在 D3D 中使用 w-buffer,問題就不大了,但是如果使用 z-buffer,不經(jīng)過這樣的轉(zhuǎn)換,渲染結(jié)果就會出錯。