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

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

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

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

シェーダートグルを追加

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

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

サンプルとして、
UseSilhouette
というトグルを作成し、これをOnにした場合画像が灰色のシルエットになるシェーダーを作りました。
プロパティにトグルを追加
OffとOnで画像が以下のように切り替わります。
トグルを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