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

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

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

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

※コードが古くなっていたのでURP用に記事を改修しました(2026/03/15)

今回使うシェーダー全文

今回は
_BlendRate
というShader変数に応じて、画像をシルエット化するシェーダーを作ります。
コードの内容としては こちら のコードからPropertiesの数行を削っただけになります。
(今回はInspectorから値を変更しないのでPropertiesは要りません)
Shader "UI/TestSilhoutte2"
{
    SubShader
    {
        Tags { "Queue" = "Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha 

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                half2 uv : TEXCOORD0;
                half4 color : COLOR;
                float4 positionOS : POSITION;
            };

            struct Varyings
            {
                half2 uv : TEXCOORD0;
                half4 color : COLOR;
                float4 positionCS : SV_POSITION;
            };

            
//uGUI Image > Source Imageにアタッチされた画像を参照する

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            
//SRP Batcherを適用

            CBUFFER_START(UnityPerMaterial)
                
//プロパティと紐づくShader内で使う変数の宣言

                half _BlendRate;
            CBUFFER_END            

            Varyings vert (Attributes input)
            {
                Varyings output;
                output.uv = input.uv;
                output.color = input.color;
                output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                return output;
            }

            half4 frag (Varyings input) : SV_Target
            {
                half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
                col *= input.color;

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

                half3 grayColor = half3(0.5, 0.5 , 0.5);
                col.rgb = lerp(col.rgb, grayColor, _BlendRate);
                
                return col;
            }
            ENDHLSL
        }
    }
}
_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
は型宣言はhalfになっていますが、
C#から見るとShaderの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