本日はShader学習枠です。
〇複数の機能を切り分けて使用できるシェーダー
Unityのマテリアルではシェーダーごとに提供されているパラメータを使用してマテリアルごとの特徴を出すことができます。
例えば上図では同じシェーダーを使用していながらマテリアルのパラメータで差を出しています。
これはShaderLabの中のPropertiesブロックで記述しています。
Properties { _MainColor("Color" ,color) = (1,1,1,1) }
またC#のようにチェックボックスを表示して有効な場合に処理を行うということもできます。
上図の場合はMicrosoft MRTK GraphicsToolsのStandardShaderですが、DirectionalLightのチェックボックスによってUintyのライトを使用するか使用しないかを処理を分けています。
また、これを使用して汎用的なシェーダーで必要な機能にチェックボックスを有効化して実装することで無駄な処理を省いて最適なパフォーマンスを出すという使い方ができます。
このようなシェーダーをウーバーシェーダーと呼びます。
今回はこの実装を紹介します。
〇プロパティの実装
まずはマテリアルプロパティでチェックボックスを表示させる実装を行います。
これはfloat型のパラメータの属性として[Toggle]をつけることで可能です。
Properties { _MainTex ("Texture", 2D) = "white" {} [Toggle]_Params("Params",float)=0 }
また、シェーダーコード内でチェックボックスの状態を使用して分岐を行うために次のように実装することもできます。
Properties { _MainTex ("Texture", 2D) = "white" {} [Toggle(PARAMS)]_Params("Params",float)=0 }
〇ShaderFeature
ShaderFeatureはウーバーシェーダーを使用するうえでキーワードを指定する際に使用します。
CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma shader_feature PARAMS; struct appdata { ・・・ }; ・・・ ENDCG
ここではプロパティで指定したPARAMSを指定しています。
〇処理の分岐
最後に処理の分岐を行います。
これは#if defined() ~#endifの条件コンパイルの形をとります。
fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); //チェックが入っている場合赤、そうではない場合Colが返される #if defined (_PARAMS) return float4 (1,0,0,1); #endif return col; }
コンパイル時に処理が分岐するため実機ではチェックボックスの動的変更は不能ですが、これでチェックボックスによる機能の切り分けが完了しました。
〇コード一覧
// Upgrade NOTE: replaced 'defined PARAMS' with 'defined (PARAMS)' Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "white" {} [Toggle(_PARAMS)]_Params("Params",float)=0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" #pragma shader_feature _PARAMS struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); //チェックが入っている場合赤、そうではない場合Colが返される #if defined (_PARAMS) return float4 (1,0,0,1); #endif return col; } ENDCG } } }