-100p

-10p

+10p

+100p

シェーダー基礎、プロパティにトグルを追加

Unityシェーダーの基礎知識。Shaderでプロパティにトグルを追加する方法。

関連ページ
参考URL
Unityシェーダーでプロパティにfloatを設定する方法は分かっていたが、boolを設定する方法が分からなかった。
調べた結果boolと近い内容は実装できたのでメモ。

シェーダートグルを追加

結論から言うと、Unityシェーダーでbooleanは使えない。
そもそも シェーダープロパティにはintが設定できない ので、なんとなく事前に予想はしていた。
(コードでintを指定は出来るが、内部的にはfloatとして処理される)

その代わり、floatを使って疑似的にトグルをプロパティに表示することはできる。
この際、float値 = 0がトグルOff状態、float値 = 1がトグルのOn状態になる。

サンプルとして、UseSilhouetteというトグルを作成し、これをOnにした場合画像が灰色のシルエットになるシェーダーを作った。

OffとOnで画像が以下のように切り替わる。


以下は今回のサンプルシェーダーのコード全文。
Shader "Test/TestToggle"
{
    Properties
    {
        
//実際はfloatだがトグル表示にすることで外から見るとboolに見える

        [Toggle] _UseSilhouette("UseSilhouette", float) = 0
    }

    SubShader
    {
        Tags { "Queue" = "Transparent" }
        Cull Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

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

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

            sampler2D _MainTex;
            
//今回追加したプロパティに対応する変数

            float _UseSilhouette;

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

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

                
//_UseDoubleのトグルがOnの時はRGBを0.5にして灰色にする

                col.rgb  = ((1 - _UseSilhouette) * col.rgb) + (_UseSilhouette * fixed3(0.5, 0.5, 0.5));

                return col;
            }
            ENDCG
        }
    }
}

一応トグルはfloatではなくintを使ってもほぼ同じことは出来る。
        [Toggle] _UseSilhouette("UseSilhouette", int) = 0
            
//今回追加したプロパティに対応する変数

            int _UseSilhouette;
しかしトグルを多用した ウェーブシェーダー でfloatをintに変えて実装した所、2つ以上のトグルをOnにした時に正しく動かなくなった。
おそらくはトグルのOnOffを計算式に使った場合、バグが発生する可能性が高い。
公式が推奨するようにトグルはfloatで実装する方が無難。

コードを解説

以下の部分がトグル表示に関係するコード。[Toggle]のプロパティ属性を指定することでトグル表示を可能にしている。
    Properties
    {
        
//実際はfloatだがトグル表示にすることで外から見るとboolに見える

        [Toggle] _UseSilhouette("UseSilhouette", float) = 0
    }
[Toggle]の代わりに[MaterialToggle]を使っても全く同じ挙動になる。
どうも特定の場合では[Toggle]だけ受け付けて[MaterialToggle]を受け付けない事があるらしい。
単純に[Toggle]の方が上位互換だと思うのでここでは[Toggle]を指定。

下のコードでプロパティに対応する変数を宣言。
            
//今回追加したプロパティに対応する変数

            float _UseSilhouette;

下のコードがトグルのOnOff状態によって描画を描き分ける処理。
                
//_UseDoubleのトグルがOnの時はRGBを0.5にして灰色にする

                col.rgb  = ((1 - _UseSilhouette) * col.rgb) + (_UseSilhouette * fixed3(0.5, 0.5, 0.5));
シェーダーではif文が非推奨 なため少しややこしいコードになっている。
_UseSilhouetteはトグルによって0か1の二択が確定している。つまり
 _UseSilhouette = 0 

col.rgb = ((1 - 0) * col.rgb) + (0 * fixed3(0.5, 0.5, 0.5));
col.rgb = (1 * col.rgb) + (0 * fixed3(0.5, 0.5, 0.5));
col.rgb = col.rgb + 0;

 _UseSilhouette = 1 

col.rgb = ((1 - 1) * col.rgb) + (1 * fixed3(0.5, 0.5, 0.5));
col.rgb = (0 * col.rgb) + (1 * fixed3(0.5, 0.5, 0.5));
col.rgb = 0 + fixed3(0.5, 0.5, 0.5);
といった感じで、全く描画処理を変えないか、灰色に一色に染めるか二択になる。
0
0

-100p

-10p

+10p

+100p