透明物體的深度寫入問題

通常來說,透明物體是不需要寫深度的,例如:

  • 透明物體與非透明物體間的渲染不會有問題
    因為所有透明物體會在所有非透明物體之后渲染。

  • 大多數情況下,透明物體之間的渲染也不會有問題
    因為,所有透明物體按由遠及近的順序渲染,所以不會出現前面的透明物體擋住后面的透明物體,導致后面的透明物體不顯示。

但有些情況下,透明物體必須要寫深度,例如:

  • 兩個透明物體間有交叉
    如果不寫深度,深度則無法正確比較,就會出現遮擋關系錯誤的現象。

圖1為俯視角度看兩面片的實際位置關系。紅色透明面片與藍色透明面片相交,一部分紅色面片在前,另一部分紅色面片在后。

1

圖2為不寫深度時相機渲染的結果。藍色面片完全遮住了紅色面片,與實際的前后關系不符。

2

圖3為兩個面片都寫入深度之后的渲染結果,看似正常,但會發現透過左側紅色的面片看不到紫色的面片了。因為紅色面片先繪制,寫了深度,當紫色面片繪制時深度測試失敗,會被丟棄。

3
  • 自身有交叉的透明物體
4.png

圖4為模型透明效果。想要保證透明物體的渲染結果正確,必須要讓遠離相機的面先繪制,近相機的面后繪制。然而一個物體內部所有三角面的渲染順序是由mesh中定義的三角面順序決定的,所以無法保證前后渲染關系。此時如果不借助寫深度,是無法實現正確的渲染的。

思路:模型要跟自身深度值比較,在一個Pass內不可能做到。所以先用一個pass記錄模型的深度值。第二個pass再跟上一個pass中記錄的自身深度進行比較。這樣就可以分清面片的前后關系了。

5

圖5是修改后的渲染結果,這才正常。

Shader "Transparent"
{
    Properties
    {
        _MainTex("MainTex", 2D) = "white"{}

        _Alpha("Alpha", Range(0,1)) = 1
    }

    SubShader
    {
        Tags{"Queue"="Transparent" "RenderType"="Opaque"}
        LOD 200
        Cull Back
        
        Pass 
        {
            ZWrite On
            ColorMask
        }

        Pass
        {
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
                
                #include "UnityCG.cginc"
                #pragma vertex vert
                #pragma fragment frag

                sampler2D _MainTex;
                half _Alpha;

                struct V2F
                {
                    float4 pos:POSITION;
                    float2 uv:TEXCOORD0;
                };

                V2F vert(appdata_img i)
                {
                    V2F o;

                    o.pos = UnityObjectToClipPos(i.vertex);
                    o.uv = i.texcoord;

                    return o;
                }

                fixed4 frag(V2F i):COLOR
                {
                    fixed4 col = tex2D(_MainTex, i.uv);
                    col.a = _Alpha;

                    return col;
                }

            ENDCG
        }
    }
}

透明渲染寫深度總結

  • 不寫深度
    a. 當一個物體自身沒有穿插,兩個物體間沒有穿插時,不寫深度沒有問題。

    b. 當兩個物體間有穿插時,會導致一個物體完全擋住另外一個物體,與現實不符。

  • 寫深度
    a. 當一個物體自身有穿插時,使用兩個pass,才可以保證透明正常,且不會透過物體的正面看到后面的面。

    b. 但是寫了深度后,這兩個物體穿插時,會導致不能透過一個角色看到另外一個角色。

兩物體沒有穿插時正常
兩物體有穿插時就不正常了

最后

  • 正常情況下,透明物體渲染不需要寫深度
  • 特殊情況下,根據需求才寫深度,雖然會帶來小問題,但也還可以接受。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容