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の二択が確定している。つまり
といった感じで、全く描画処理を変えないか、灰色に一色に染めるか二択になる。
0
0