-100p

-10p

+10p

+100p

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

Unityシェーダーの基礎知識。マテリアルのInspectorからシェーダー変数にアクセス。

関連ページ
参考URL
シェーダーの変数にはマテリアルのInspectorからもアクセスできる。
この機能を知らないと、動的に動かす必要のないシェーダー変数も一々コードから変更する必要があるので、開発効率が数十倍落ちる。

またマテリアルが仲介することでC#からシェーダーにアクセスすることもできる。それに関しては こちら の記事をどうぞ。

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

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


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

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

    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;
            
//プロパティと紐づくShader内で使う変数の宣言

            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
        }
    }
}

プロパティ実装の解説

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

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

Propertiesブロック以外にも、CGPROGRAM内にも同じ変数名を宣言する必要がある。
            sampler2D _MainTex;
            
//プロパティと紐づくShader内で使う変数の宣言

            fixed _BlendRate;

プロパティの補足

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

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

            fixed _BlendRate;
            float _FloatTest;

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

            fixed _BlendRate;
            fixed _FloatTest;

残念ながらシェーダープロパティに単純なintは使えない。
バグやエラーなどは発生しないが、内部的には完全にfloatとして処理されてしまう。
        _BlendRate ("BlendRate", Range(0.0, 1.0)) = 0
        _FloatTest ("FloatTest", float) = 0
        _IntTest ("IntTest", int) = 0

見ての通り、intを指定してるのに0.5が入力できてしまっている。

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

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

-100p

-10p

+10p

+100p