シェーダー基礎、Unityのマテリアルプロパティ

シェーダー基礎、Unityのマテリアルプロパティ

[Unityシェーダー基礎] マテリアルのInspectorからシェーダー変数にアクセス。
マテリアルプロパティとSRP Batcherについて。

関連ページ
参考URL
シェーダーの変数にはマテリアルのInspectorからもアクセスできます。
この機能を知らないと、動的に動かす必要のないシェーダー変数も一々コードから変更する必要があるので、開発効率が数十倍落ちます。
シェーダーをUI Imageに適用する方法は こちら
またマテリアルが仲介することでC#からシェーダーにアクセスすることもできます。それに関しては こちら の記事をどうぞ。

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

プロパティが実装されたシェーダー

Unity Shaderでは、
Properties
内に変数を記入すると、その値をInspectorから操作できます。
下の例は、
BlendRate
の値に応じて、画像を灰色に塗りつぶすシルエットシェーダーです。


コードは次の通りです。
Shader "UI/TestSilhoutte"
{
    
//Inspectorに表示するプロパティの宣言

    Properties
    {
        _BlendRate ("BlendRate", Range(0.0, 1.0)) = 0
    }

    SubShader
    {
        Tags
        {
            "RenderPipeline" = "UniversalPipeline"
            "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
        }
    }
}

プロパティ実装の解説

Inspectorに変数を表示させるためには、まず
Properties
ブロックの記述が必要になります。
    
//Inspectorに表示するプロパティの宣言

    Properties
    {
        _BlendRate ("BlendRate", Range(0.0, 1.0)) = 0
    }
ここでは
_BlendRate
が実際にShader内で使う変数名です。
第一引数の
"BlendRate"
がInspectorに表示される文字列。Shader内で使う変数名と一致している必要はありません。
何なら日本語でも問題なく動きます。
第二引数は型指定、ここでは
Range
指定しています。Rangeは最小値と最大値を限定させたfloat型のことです。
最後に=0で_BlendRateの初期値を代入。

Propertiesブロック以外にも、
HLSLPROGRAM
内にも同じ変数名を宣言する必要があります。
            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            
//SRP Batcherを適用

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

                half _BlendRate;
            CBUFFER_END         

SRP Batcher

half _BlendRate;の前後に
CBUFFER_START(UnityPerMaterial)
CBUFFER_END
というコードも確認できます。
これはURPから追加された
SRP Batcher
という機能です。
簡単に言うとこのコードを入れるだけでPropertiesで宣言した変数の取得速度が大きく向上します。
このマテリアルを適用したオブジェクトの数が増えるほど、その効果が顕著になります。

ただし何でもかんでもSRP Batcherが使える訳ではなく、Propertyの中でも簡単な数値データのみ適用可能です。
SRP Batcher適用可能なもの
: float, int, half, float4(Vector/Color)などの数値データ。
SRP Batcher適用不可能なもの
: テクスチャ、サンプラー。

プロパティの補足

今回は_BlendRateが0未満だったり1より上になるとバグになるのであえてRangeで制限しています。
実際は制限のない単純なfloatもプロパティに追加できます。下がそのコードサンプルです。
    
//Inspectorに表示するプロパティの宣言

    Properties
    {
        _BlendRate ("BlendRate", Range(0.0, 1.0)) = 0
        _FloatTest ("FloatTest", float) = 0
    }
            
//プロパティと紐づくShader内で使う変数の宣言

            half _BlendRate;
            float _FloatTest;

以前の記事 で書いた通り、内部で使える浮動小数点数はfloat以外にhalfもあります。
プロパティ自体には実質floatしか記述できませんが、対応するHLSLPROGRAM内の変数はhalfに落とし込むことができます。
            
//プロパティと紐づくShader内で使う変数の宣言

            half _BlendRate;
            half _FloatTest;

残念ながらシェーダープロパティに単純なintは使えません。
バグやエラーなどは発生しませんが、内部的には完全にfloatとして処理されてしまいます。
        _BlendRate ("BlendRate", Range(0.0, 1.0)) = 0
        _FloatTest ("FloatTest", float) = 0
        _IntTest ("IntTest", int) = 0
シェーダープロパティのfloatとintの関係
見ての通り、intを指定してるのに0.5が入力できてしまっています。

一方でHLSLPROGRAM内の対応する変数にはintを指定できます。
            
//プロパティと紐づくShader内で使う変数の宣言

            half _BlendRate;
            half _FloatTest;
            int _IntTest;
上の例では、インスペクターからはIntTestに対して小数点以下を指定できるものの、
_IntTest
は小数点以下の数値を無視して処理します。
0
0