-100p

-10p

+10p

+100p

シェーダー基礎、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 
関数があり、これで現在のプロパティの値を取得できる。

このようにMaterialの関数から、Shaderを操作しアニメーションを実装していく。
0
0

-100p

-10p

+10p

+100p