ShaderLab: 剔除和深度測試(Culling and ZTest) 概述: 工作時機: 語法: ZTest Offset 引用:

概述:

不渲染視野內不可見的多邊形的操作稱之爲剔除。
所有的多邊形都有正面和背面,視野永遠看不見背面,因此Unity也不需要渲染背面。這個過程用專業術語稱之爲:背面剔除(Backface culling)
另外有一項技術,保證渲染的永遠是離視野最近的面,從容讓渲染出的效果看起來更真實,這項技術被深度檢測(Depth testing)

工作時機:

語法:

Cull

Cull Back | Front | Off 

控制剔除多邊形的那些邊?

  • Back Don't render polygons that are facing away from the viewer. default: back-facing polygons are culled.
    背面,背對着觀察者的面,這是默認選項
  • Front Don't render polygons that are facing towards the view.Used for turning objects inside-out.
    前面,朝向觀察者的面,通常用於表現翻轉效果
  • Off Disable culling-all faces are drawn.Used for special effects.
    關閉剔除,所有朝向都繪製。通常用於特殊效果。

樣例:


Shader "Unlit/CullingTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [Header(Cull)]
        // https://docs.unity3d.com/ScriptReference/Rendering.CullMode.html
        // default need to be Front, because we need to make sure decal render correctly even if camera goes into decal cube
        [Enum(UnityEngine.Rendering.CullMode)]_Cull("_Cull (default = Front) _____to improve GPU performance, Set to Back if camera never goes into cube volume, else set to Front", Float) = 1 //1 = Front
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry" }
        Cull [_Cull]
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}


Cull [_Cull]  //從外面讀取數據

效果:

ZTest

ZTest  Less  |  LEqual | GEqual | NotEqual | Always

How should depth testing be perfromed.Default is LEqual(draw objects in from or at the distance as existing objects;hide objects behind them).
深度測試執行方式,默認爲 LEqual(小於等於)。Unity中離攝像機越近深度越小,越大離得越遠。LEqual 表示執行深度測試時,像素點與緩存中的進行比較,如果小於緩存值,便能通過測試。
除了LEqual 外,還有下面這些參數可用:

函數名 描述
Never 1 從不渲染
Less 2 當小於緩存值時執行
Equal 3 當等於緩存值時執行
LEqual 4 當小於等於緩存值時執行
Greater 5 當大於緩存值時執行
NoEqual 6 當不等於緩存值時執行
GEqual 7 當大於等於緩存值時執行
Alaways 8 一直執行

ZWrite

ZWrite On | Off

Controls whether pixels from this object are written to the depth buffer(default is On).if you're drawing solid objects,leave this on .if you're drawing semitransparent effects,switch to Zwrite off.
控制物體的像素點是否寫入深度緩存,如果繪製是固體(不透明)保持它爲打開狀態,如果是透明,關閉它。
設置在渲染過程中是否更新深度緩衝區內容。通常,ZWrite 對不透明對象啓用,對半透明對象禁用。
禁用 ZWrite 會導致不正確的深度排序。這種情況下,您需要在 CPU 上對幾何體進行排序。

當且僅當 ZTest 通過和 ZWrite 開啓時,像素點的深度纔會被寫入 ```depth buffer`` 中

Offset

Offset Factor, Units

Allows you specify a depth offset with two parameters.factor and units.Factor scales the maximum Z slop,with respect to X or Y of the polygon,and units scale the minimum resolvable depth buffer value.This allows you to force one polygon to be drawn on top of another although they are actually in the same position.
For example Offset 0,-1 pulls the polygon closer to the camera ignoring the polygon's slope,whereas Offset -1,-1 will pull the polygon even closer when looking at a grazing angle.

允許通過 Factor 和 Units 來指定深度偏移。Factor 是多邊形 Z 軸基於 X 或者 Y 的最大斜率的縮放量,Units 是深度緩存中最小可分值的縮放量。通過調整參數,你可以強制使同一位置的多邊形繪製在其它多邊形之上。
例如:Offset 0, -1 可以忽略多邊形的斜率,將其推進攝像機。Offset -1, -1 從波動角(grazing angle)觀察,多邊形被拉得更靠近。

Offset 主要用來解決 Z-fighting 問題

  • Z-fighting:當多邊形共面時,深度緩存無法分離它們,導致深度不穩定,從而會出現圖像在幀間來回穿插閃爍。

如下效果:

能解決這種問題的shader:

Shader "Test/Quad"
{
    Properties
    {
        _OffsetFactor("Offset Factor",Float) = 0
        _OffsetUnits("Offset Units",Float) = 0
        _Color ("Main Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Offset [_OffsetFactor],[_OffsetUnits]
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 normal : NORMAL;
            };

            struct v2f
            {
                float2 wnormal : NORMAL;
                float4 vertex : SV_POSITION;
            };
            fixed4 _Color;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.wnormal = UnityObjectToWorldNormal((v.normal,1));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return _Color * (dot(normalize(_WorldSpaceLightPos0.xyz),i.wnormal) * 0.5 + 0.5);
            }
            ENDCG
        }
    }
}

關鍵在下面兩段代碼:

  _OffsetFactor("Offset Factor",Float) = 0 // Factor 屬性面板可設置,默認0
  _OffsetUnits("Offset Units",Float) = 0 // Units 屬性面板可設置,默認0
  Offset [_OffsetFactor],[_OffsetUnits]

引用:

https://docs.unity3d.com/2020.1/Documentation/Manual/SL-CullAndDepth.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章