MaterialPropertyDrawer
Shaderlabのシェーダ・プロパティに、インスペクタでトグルや列挙型(enum)などを使うには、UnityEditorのMaterialPropertyDrawerクラスを使う。
Unityの組み込みMaterialPropertyDrawerには次がある。
Drawer | 記述 | 機能 |
---|---|---|
ToggleDrawer | [Toggle], [Toggle(変数名)] | トグル |
EnumDrawer | [Enum(列挙型名)], [Enum(列挙型要素名/インデックス)] | 列挙型 |
KeywordEnumDrawer | [KeywordEnum(要素名,...)] | キーワード列挙型 |
PowerSliderDrawer | [PowerSlider(指数)] | 指数スライダ |
IntRangeDrawer | [Toggle] | 整数スライダ |
Space | [Space(スペース量)] | インスペクタの行間スペース |
Header | [Header(表示テキスト)] | インスペクタのヘッダ情報 |
MaterialPropertyDrawerをつかったサンプルシェーダー
シェーダ・プロパティにトグルを実装する
次のチュートリアルにあるシェーダ(Transparent Shader)を、透明度(Transparency)の適用・非適用を切り替えるトグルを追加する。
Transparencyの適用・非適用を、ToggleDrawerを使って実装してみる。
Propertyにトグル要素を追加する。
[Toggle] _Apply_Transparency("Apply Transparency", Float) = 0
トグルの設定値は、"大文字のプロパティ名+_ON"というシェーダーキワードに、トグルの状態に応じて、0または1の値がセットされる。上の例では、_APPLY_TRANSPARENCY_ON
というシェーダーキーワードを参照する。
あるいは、シェーダーキーワードを直接指定することもできる。その場合は、Toggleに引数をつけ、
[Toggle(TRANSPARENCY)] _Apply_Transparency("Apply Transparency", Float) = 0
のように記述する。
シェーダーキーワードの取得と参照
シェーダーキーワードをCGINCブロックで使うためには、シェーダーキワードを
#pragma shader_feature シェーダーキーワード
のようにする。上の例では次のようになる。
#pragma shader_feature _APPLY_TRANSPARENCY_ON
実はこれはシェーダーキーワードがない場合の省略形で、フル標記は、
#pragma shader_feature _ _APPLY_TRANSPARENCY_ON
となる。
あるいは、
#pragma multi_compile _ _APPLY_TRANSPARENCY_ON
とも書ける。
shader_featureとmulti_compileの違いは、UnityのShader Variantについて調べてみた - Qiitaを参照ください。
シェーダーキーワードの参照(評価)は、
#ifdef シェーダーキーワード シェーダーキーワードがTrue(1)の場合の処理 #else シェーダーキーワードがFalse(0)の場合の処理 #endif
のように書く。
サンプルシェーダー
冒頭のTransparent Shaderに、Transparencyの適用・非適用を指定するトグルを追加したシェーダは次の通り。
Shader "XOOMS/Test/Transparent" { Properties { _MainTex ("Albedo Texture", 2D) = "white" {} _TintColor("Tint Color", Color) = (1,1,1,1) _Transparency("Transparency", Range(0.0,0.5)) = 0.25 _CutoutThresh("Cutout Threshold", Range(0.0,1.0)) = 0.2 _Distance("Distance", Float) = 1 _Amplitude("Amplitude", Float) = 1 _Speed ("Speed", Float) = 1 _Amount("Amount", Range(0.0,1.0)) = 1 [Toggle] _Apply_Transparency("Apply Transparency", Float) = 0 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Transparent" } LOD 100 ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _TintColor; float _Transparency; float _CutoutThresh; float _Distance; float _Amplitude; float _Speed; float _Amount; v2f vert (appdata v) { v2f o; v.vertex.x += sin(_Time.y * _Speed + v.vertex.y * _Amplitude) * _Distance * _Amount; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } #pragma shader_feature _APPLY_TRANSPARENCY_ON fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv) + _TintColor; #ifdef _APPLY_TRANSPARENCY_ON col.a = _Transparency; #else col.a = 1; #endif clip(col.r - _CutoutThresh); return col; } ENDCG } } }
列挙型(enum)プロパティを実装する
同じサンプルシェーダに、列挙型(enum)プロパティを適用してみる。
列挙型プロパティの場合のシェーダーキーワードは、"プロパティ名_列挙名"となる。シェーダーキーワードは、
#pragma multi_compile シェーダーキワード( シェーダーキワード2 シェーダーキーワード3 ......)
で、CGINCブロック内で利用できるようになる。
次は、enumプロパティで、透明度を3段階に切り替えるサンプル。
Shader "XOOMS/Test/Transparent" { Properties { _MainTex ("Albedo Texture", 2D) = "white" {} _TintColor("Tint Color", Color) = (1,1,1,1) _Transparency("Transparency", Range(0.0,0.5)) = 0.25 _CutoutThresh("Cutout Threshold", Range(0.0,1.0)) = 0.2 _Distance("Distance", Float) = 1 _Amplitude("Amplitude", Float) = 1 _Speed ("Speed", Float) = 1 _Amount("Amount", Range(0.0,1.0)) = 1 [KeywordEnum(Zero, Weak, Strong)] _Strength ("Transparant Strength", Float) = 0 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Transparent" } LOD 100 ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _TintColor; float _Transparency; float _CutoutThresh; float _Distance; float _Amplitude; float _Speed; float _Amount; v2f vert (appdata v) { v2f o; v.vertex.x += sin(_Time.y * _Speed + v.vertex.y * _Amplitude) * _Distance * _Amount; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } #pragma multi_compile _STRENGTH_ZERO _STRENGTH_WEAK _STRENGTH_STRONG fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv) + _TintColor; #ifdef _STRENGTH_ZERO col.a = 0.1; #elif _STRENGTH_WEAK col.a = 0.5; #else col.a = 1; #endif clip(col.r - _CutoutThresh); return col; } ENDCG } } }
独自のMaterialPropertyDrawerの作成
MaterialPropertyDrawerクラスを継承して、オリジナルのPropertyを作ることもできる。