シェーダー基礎、C#からShader変数にアクセス

シェーダー基礎、C#からShader変数にアクセス

Unityシェーダーの基礎知識。C#からShader変数にアクセスする方法。

関連ページ
参考URL
シェーダーの変数の値は マテリアルから操作が可能 となっています。
またUnity C#からマテリアルにアクセス可能なので、実質C#からシェーダー変数にもアクセスできます。
この知識がないとゲーム中に動的にシェーダー変数を動かすことができないので、シェーダーを使った演出を作ることができないです。

今回使うシェーダー全文

今回は
_BlendRate
というShader変数に応じて、画像をシルエット化するシェーダーを作ります。
Shader "Test/TestSilhoutte"
{
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" = "Transparent" }
        Cull Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                fixed2 uv : TEXCOORD0;
                fixed4 color : COLOR;
                fixed4 vertex : POSITION;
            };

            struct v2f
            {
                fixed2 uv : TEXCOORD0;
                fixed4 color : COLOR;
                fixed4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            
//この_BlendRateの値によってシルエット化の割合が決まる

            fixed _BlendRate;

            v2f vert (appdata v)
            {
                v2f o;
                o.uv = v.uv;
                o.color = v.color;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col *= i.color;

                
//元のImageのカラーと灰色を_BlendRateに応じてブレンド

                fixed4 SilhouetteColor = fixed4(0.5, 0.5 , 0.5, 1);
                col.r = (col.r * (1 - _BlendRate)) + (SilhouetteColor.r * _BlendRate);
                col.g = (col.g * (1 - _BlendRate)) + (SilhouetteColor.g * _BlendRate);
                col.b = (col.b * (1 - _BlendRate)) + (SilhouetteColor.b * _BlendRate);
                
                return col;
            }
            ENDCG
        }
    }
}
_BlendRate
のようなShader内で宣言された変数に対して、C#からアクセスが可能です。

C#からShader変数にアクセス

厳密に言うとまずMaterialのC#コードにアクセスし、そのMaterialがShaderコードにアクセスします。
下の動画は、ボタンを押すと星がシルエット化してから右端まで移動し、右端に到達すると1秒かけてシルエットが解除される処理です。


C#の関係するコード部分だけ紹介。まず最初の星移動前にシルエット化するコードです。
    [SerializeField]
    private Image star;
    star.material.SetFloat("_BlendRate", 1);
SerializeField
でアタッチしたImageコンポーネントから、
star.material.SetFloat("_BlendRate", 1)
でプロパティにアクセスしています。
ここでは
_BlendRate
というShader変数を1にするようにC#から指定。

SetFloat以外にもSetIntやSetColorなど様々な関数があります。
今回の
_BlendRate
は型宣言はfixedになっていますが、
C#から見るとShaderのfixed、half、floatは全部floatという扱いになります。


次に星が1秒かけてシルエット状態から_BlendRate=0に戻る処理。
    DOTween.To(() => star.material.GetFloat("_BlendRate"), (val) => 
    {
        star.material.SetFloat("_BlendRate", val);
    }, 0, 1f);
面倒なので Tween で処理。
SetFloat
と対になる形で
GetFloat
関数があり、これで現在のプロパティの値を取得できます。

以上のように、Shaderを操作しアニメーションを実装が可能です。

0
0