天天看點

Unity ZTest 深度測試 & ZWrite 深度寫入

    初學Shader,一開始對于渲染隊列,ZTest 和 ZWrite一頭霧水,經過多方查閱和實驗,有了一些自己的了解。發此文與初學Shader的朋友分享,也算是為自己做個筆記。不對或不足之處歡迎指正。

    不說廢話,直接進入正題。 

    首先是實驗場景,一藍一紅兩個Cube。藍在紅前。

    兩個方塊所使用的Shader都是最簡單的 V&F 着色程式,不同的是藍色方塊alpha傳回值為0.6,紅色為1。

     但是藍色方塊并沒有絲毫透明的效果,這時我們在藍色方塊的Shader内加上這樣一行代碼 : 

     Blend SrcAlpha OneMinusSrcAlpha 。

     稍微解釋一下,這行指令意思就是将本 Shader 計算出的顔色值(源顔色值,即藍色) * 源Alpha值(0.6) + 目标顔色值(可以了解為背景色) * (1-0.6),進而讓藍色方塊展示出了40%的透明度。

    然後我們看到了這樣的效果:

    似乎有些透明的樣子了,但是紅色方塊還是顯示不出來。我們再加上這樣一行代碼:

     Tags {"Queue" = "Transparent"}

    意思是設定它在渲染隊列中的值為 Transparent (透明) = 3000,值越小越先渲染,而後渲染( Queue 值大)的物體會覆寫先渲染的物體(紅塊未設定 Queue 值,預設為 Geometry(幾何體) = 2000)。在理想的世界中,我們應該讓遠處的物體先渲染,近處的物體後渲染,這樣遠處的物體就不會遮擋住近的物體。

    接下來我們看到了正确的結果:

    Queue 其他預定義的值為:Background = 1000 , AlphaTest = 2450,Overlay = 4000。預設值是Geometry 。

    例如:如果我們想讓遠處的紅色方塊遮擋住近處的藍色方塊,即讓藍色的先渲染,紅色的後渲染,隻需将紅塊的Queue 也設定為 Transparent ,藍塊的Queue值-1。

    然後我們看看效果:

    好像并沒有什麼卵用。。。這是為什麼呢?

    原因在于這樣兩條指令:

    雖然我們的代碼裡并沒有這兩行,但它們是預設存在的。

     ZTest ,深度測試;LEqual ,小于等于。

     ZWrite ,深度寫入,On ,打開。

     ZTest 可取值為:Greater , GEqual , Less , LEqual , Equal , NotEqual , Always , Never , Off,預設是 LEqual,ZTest Off 等同于 ZTest Always。

     ZWrite 可取值為:On , Off,預設是 On。

    系統中存在一個顔色緩沖區和一個深度緩沖區,分别存儲顔色值和深度值,來決定畫面上應該顯示什麼顔色。

    深度值是物體在世界空間中距離錄影機的遠近。距離越近,深度值越小;距離越遠,深度值越大。

    例如在我們的場景中,藍色方塊比紅色更靠近相機,藍塊的深度值就比紅塊小。

    假設藍塊的深度值為 0.5,紅塊為 0.7。還記得在上面的例子中,我們讓藍塊在渲染隊列中排在紅塊前面,系統就先将藍色值存入了顔色緩沖區中對應的區域,将深度值 0.5 存入了深度緩沖區中對應的區域。接下來渲染紅塊,系統會将紅塊的深度值與深度緩沖區中的值進行比較(這個過程就是深度測試),由于預設的 ZTest 深度測試的方式是 LEqual 小于等于,即深度值小于等于 0.5 的顔色才會通過測試。如果通過了測試,且 ZWirte 處于 On 的狀态,該顔色的深度值就會替代深度緩沖區中的值,顔色值也會替代顔色緩沖區中的值,進而顯示出新顔色。

    很顯然,0.7 > 0.5,是以紅色并不能通過測試,紅塊也就不能顯示在藍塊前面。

    如果我們硬要遠處的紅塊遮擋住近處的藍塊,很顯然,我們應該改變或關閉深度測試,或者關閉深度寫入(關閉了深度測試或者深度寫入之後,物體顔色的遮擋關系就會和渲染隊列一緻,即排在後面的會擋住前面的)。

    接下來我們試試關閉藍塊的深度寫入:

    得到了想要的結果:

    再試試單獨關閉紅塊的深度測試,注釋藍塊的深度寫入:

    結果還是一樣。但如果我們改變紅塊深度測試的方式呢:

    即深度值大于深度緩沖區中的值就能通過測試,還記得我們假設紅塊深度值為 0.7,藍塊為 0.5。理論上會得到我們想要的結果:

    奇怪的是,紅塊的另一半去哪了?

    答案是被背景擋住了。

    按照距離相機的遠近,我們可以假設背景的深度值為 1。在消失的另一半的深度緩沖區中的深度值應該是背景的深度值 1。而我們設定了 ZTest Greater,0.7 < 1,是以紅塊另一半沒有通過深度測試。

     本文到此結束,由于是第一次寫部落格,還希望大家能多多指正!

上一篇: 分子
下一篇: 編寫