iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 10
0
自我挑戰組

初見Unity Shader系列 第 10

深度緩衝,又或是Z緩衝

目的

  • 認識深度緩衝(Depth Buffer)

深度緩衝

這個東西搜尋一下會發現有很多種叫法,深度緩衝、Z緩衝、depth buffer、z-buffer,都是指同一件東西。

先給各位看一張圖:

from wiki

有些讀者或許看過這張圖,這張圖就是把深度緩衝的值取出來,當作顏色繪製的結果,顏色越黑表示越靠近相機,越白則離相機越遠。

在Day4介紹幾何階段的時候,有介紹到深度緩衝,在這邊以我理解的方式解詳細一點,以下將深度緩衝的實作步驟列出來:

  1. 把三維世界的物件,或是指相機拍到的視野,轉化成二維的一張圖
  2. 準備一張只能填小數點[0, 1]的表格,叫做深度緩衝,大小為投影圖的像素數量,表格的單位位置也也映射於圖像。
  3. 把每個表格的內容都先填上1,表示離相機最遠,反之,如果完全貼在相機上則填0
  4. 試想表格在視野的場景內,開始從最遠的地方接近相機
  5. 每經過為物件的一個片段,就比較表格內該位置對應的,並依照開發者的設定更新表格內的數字。

例如:當前表格的數字是1,碰到了一個片段,它的深度值為0.8,且設定為「若比表中原有的值小則更新」,0.8 < 1,所以更新表格。

  1. 持續第五點的動作,直到碰到相機。

以下這張圖作為輔助,希望讀者可以比較清楚上面的步驟再說甚麼:

from 【3D】深度測試與 Z fighting

繪製設定

此為上面步驟五的的範例中提到的「設定」

在介紹渲染管線的時候,說過有些階段開發者只能對他設定一些功能,深度緩衝就是如此。

我們必須把繪製設定寫在Unity Shader這個地方:

...
SubShader {
    Pass {
        // 繪製設定寫在這裡!
        ZWrite On
        ZTest Less
        
        CGPROGRAM
        ...
        ENDCG
    }
}
...

關於深度緩衝的操作有這兩種

  • ZTest(深度測試)
  • ZWrite(深度寫入)

深度寫入表示是否開啟測試,狀態就最簡單只有開啟(On)跟關閉(Off)而已,深度測試的後面則表示通過測試的比較方法,分別有:

ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always

例如:ZTest Less會去比較深度緩衝內,新的數值有沒有小於已填入的數值,有的話則更新成新數值。

ZTest Always 等同於 ZWrite Off,表示不論如何都通過。

除了本篇的深度測試以及寫入,還有混合效果(Blend)跟剔除(Cull),之後也會介紹這兩個設定會用在哪裡。

關於Buffer這個詞

Buffer,或是中文譯作緩衝,這個詞在我剛踏入軟體領域的時候讓我疑惑。根據我淺薄的電子學知識,我所認識Buffer是這個:

from wiki

於是我找到了這篇stackoverflow問答第二個答案,一句話說明了Buffer的作用,下面的一句話我按照原意,添加了一些東西,若讀者認為有誤也請給予批評

是一個用來暫存資料(訊號)的地方,為了要防止輸入與輸出之間不同的頻率及速度

Z-fighting

將兩個正方體重疊,然後由相機俯視他們的重疊面,就會看到以下這個現象,這現象就是所謂的Z-fighting,原因在於深度緩衝的精度不夠,無法正確辨識誰在前或誰在後,目前我知道有兩種解決這個現象的方法:

  • 拉大模型之間的間距,把要顯示在前面的物件對Z軸調整0.001單位即可
  • 利用Shader調整Offset

Reference


上一篇
紋理貼圖,又或是叫做Texture
下一篇
混和效果和一些我忘記的東西
系列文
初見Unity Shader30

尚未有邦友留言

立即登入留言