shader編-透明効果


shader編-透明効果


ラベル(スペース区切り):shader
  • shader編-透明効果
  • 透明効果実現方法概要
  • レンダリング順序の重要性
  • Unity shaderのレンダリング順序
  • 透明度テスト
  • 透明度ブレンド
  • 深さ書き込みの半透明効果
  • をオンにする.
  • 両面レンダリング

  • 透明効果の実現方法の概要


    Unityでは2つの方法で透明効果を実現します.1つは透明度テスト、2つは透明度混合です.透明度テスト:深さ書き込みを閉じる必要がなく、透明度が基準に達しないと削除されるので、物体は不透明か完全に透明になります.透明度ブレンド(Transparency Blend):実際の半透明効果を得ることができます.透明度とカラーバッファのカラーをブレンドして新しいカラーを得るのが原理です.ただし、これは深さ書き込みを閉じる必要があります.半透明の物体が不透明な物体や半透明の後ろの半透明の物体のレンダリングに影響しないことを保証します.

    レンダリング順序の重要性


    深度書き込みをオフにすると、オブジェクトのレンダリング順序に注意する必要があります.オフにする前のオブジェクトのレンダリングは深度z-bufferによって決定されるため、半透明なオブジェクトの後の非透明なオブジェクト(ここでは前後が仮想カメラからの距離を指す)をレンダリングし、透明なオブジェクトをレンダリングする必要があります.そうしないと、オフにしていない深度テストは透明度ブレンド後のカラーバッファを直接上書きし、ある半透明な効果を失うことになります.しかし、レンダリング順序が設定されていても、2本のロープで2つの物体の前後を区別することができず、合理的なレンダリング順序を制定できないなどの問題が発生することがあります.この問題を解決するには、グリッドを分割する必要があります.

    Unity shaderのレンダリング順序


    レンダリング順序を解決するためにunityはレンダリングキューを提供します.Queueラベルは、モデルがどのキューを使用するかを決定します.
    名前
    キューインデックス
    説明
    Background
    1000
    バックグラウンドをレンダリングする最も古いレンダリングキュー
    Geometry
    2000
    既定のレンダリングキュー、不透明な物体はこれを使用します
    AlphaTest
    2450
    透明度テスト
    Transparent
    3000
    透明度を使用して深さ書き込みのshaderをブレンドまたは閉じる
    Overlay
    4000
    いくつかのオーバーラップ効果を使用して、最後にレンダリングされたオブジェクトがキューを使用します.
    インスタンスを使用して透明度テストを使用する場合は、次のtagを追加する必要があります.
    SubShader {
            Tags {"Queue"="AlphaTest" 

    同様に、透明度ブレンドには、以下のtagを使用する必要があります.
        SubShader {
            Tags {"Queue"="Transparent"

    透明度テスト


    unityメタシェーダはclip関数を使用して透明度テストを行います
    void clip(float4 x)
    {
        if(any(x<0))
            discard;
    }

    コンフィギュレーションではtagsがかなり重要ですが、Queueラベルは前に述べましたが、RenderTypeはレンダリングのキューを作成するために使用されています.「IgnoreProjector」=「True」は、shaderがプロジェクタの影響を受けないことを保証します.
    Properties {
            _Color ("Color Tint", Color) = (1, 1, 1, 1)
            _MainTex ("Main Tex", 2D) = "white" {}
            _Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
        }
        SubShader {
    
            Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    
            Pass {
                Tags { "LightMode"="ForwardBase" }
    
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
    
                #include "Lighting.cginc"
    
                fixed4 _Color;
                sampler2D _MainTex;
                float4 _MainTex_ST;
    
                //_Cutoff [0,1], fix 
                fixed _Cutoff;
    
                struct a2v {
                    float4 vertex : POSITION;
                    float3 normal : NORMAL;
                    float4 texcoord : TEXCOORD0;
                };
    
                struct v2f {
                    float4 pos : SV_POSITION;
                    float3 worldNormal : TEXCOORD0;
                    float3 worldPos : TEXCOORD1;
                    float2 uv : TEXCOORD2;
                };

    頂点シェーダ(Vertex Shader)
    v2f vert(a2v v) {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
    
                    o.worldNormal = UnityObjectToWorldNormal(v.normal);
    
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    
                    return o;
                }

    シェーダの透明度テストはここで行います
    fixed4 frag(v2f i) : SV_Target {
                    fixed3 worldNormal = normalize(i.worldNormal);
                    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
    
                    fixed4 texColor = tex2D(_MainTex, i.uv);
    
                    // Alpha test
                    clip (texColor.a - _Cutoff);
                    // Equal to 
    //              if ((texColor.a - _Cutoff) < 0.0) {
    //                  discard;
    //              }
    
                    fixed3 albedo = texColor.rgb * _Color.rgb;
    
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
    
                    fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
    
                    return fixed4(ambient + diffuse, 1.0);
                }

    Fallbackは内蔵Transparent/Outout/VertexLitをfallbackとして使用し、shaderが現在のグラフィックスカードで動作している間に交換可能なshaderが存在しないことを保証します.
    FallBack "Transparent/Cutout/VertexLit"

    透明度のブレンド(Transparency Blend)


    同様に、透明度ブレンドに対応し、unityは内蔵コマンドBlendを提供します.
    意味
    説明
    Blend Off
    ブレンドを閉じる
    Blend SrcFactor DstFactor
    ブレンドをオンにする
    コード実装はまず構成です
    Properties {
            _Color ("Color Tint", Color) = (1, 1, 1, 1)
            _MainTex ("Main Tex", 2D) = "white" {}
            _AlphaScale ("Alpha Scale", Range(0, 1)) = 1
        }
        SubShader {
            Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    
            Pass {
                Tags { "LightMode"="ForwardBase" }
    
                // 
                ZWrite Off
                // 
                Blend SrcAlpha OneMinusSrcAlpha
    
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
    
                #include "Lighting.cginc"
    
                fixed4 _Color;
                sampler2D _MainTex;
                float4 _MainTex_ST;
                fixed _AlphaScale;
    
                struct a2v {
                    float4 vertex : POSITION;
                    float3 normal : NORMAL;
                    float4 texcoord : TEXCOORD0;
                };
    
                struct v2f {
                    float4 pos : SV_POSITION;
                    float3 worldNormal : TEXCOORD0;
                    float3 worldPos : TEXCOORD1;
                    float2 uv : TEXCOORD2;
                };

    シェーダ(Shader)
    fixed4 frag(v2f i) : SV_Target {
                    fixed3 worldNormal = normalize(i.worldNormal);
                    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
    
                    fixed4 texColor = tex2D(_MainTex, i.uv);
    
                    fixed3 albedo = texColor.rgb * _Color.rgb;
    
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
    
                    fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
    
                    // , Blend , 
                    return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
                }

    深度ライトの半透明効果をオンにする


    深さ書き込みをオンにしても半透明になりますが、passを2つ使うと一定の性能損失が発生します
    Pass {
        ZWrite On
        ColorMask 0
    }
    
    Pass {
         

    この最初のpassは、モデルの深さ情報を深さキャッシュに入力するために設定され、ColorMaskを0に設定してpassがマスクを出力しないようにします.

    両面レンダリング


    これは、すべてのオブジェクトをレンダリングするために除去機能をキャンセルし、より多くのパフォーマンスを消費することを実現します.
        Cull Off// 

    透明度ブレンドの両面レンダリング両面レンダリング両面レンダリングは、両面レンダリングがオンになっているため、レンダリング順序を保証するためにコードを再設定する必要があります.
    Pass {
    
        // First pass renders only back faces 
        Cull Front
    
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
        。。。。
    
        }
    
        Pass {
        Tags { "LightMode"="ForwardBase" }
    
        // Second pass renders only front faces 
        Cull Back
        。。。。

    2つのpassを使用してcullコマンドを使用してレンダリング順序を設定し、異なる方向のレンダリングエンティティを除去します.
    これは私個人の学習ノートと個人の総括にすぎません.もし不適切なところがあれば、指摘してください.