【Unity】【シェーダ】シェーダでマクロを使う

シェーダでマクロを使う方法です。

Unity2018.2

マクロ?

マクロはこんな感じで、名前と値で定義します。

// #define [名前] [値] で定義
#define MACRO_NAME 0.5

この名前をソースコードに記述することで値を使うことができます。

return MACRO_NAME * MACRO_NAME;

マクロはプリプロセッサなので、コンパイル時にマクロ名が値に置き換えられます。

また、置き換え時には「マクロの値がソースコード内に記述された状態」と同等になるので、
値は上記のような数値に限らず、式なども指定できます。

// RETURNが「return 0.5」に置き換えられる
#define RETURN return 0.5;

値をマクロにする

数値をマクロとして定義すると次のようになります。
(CGPROGRAM部分だけ抜粋しています。)

CGPROGRAM

#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

// マクロを定義
#define RETURN_VALUE 0.5

float4 vert (float4 vertex : POSITION) : SV_POSITION
{
    return UnityObjectToClipPos(vertex);
}

fixed4 frag () : SV_Target
{
    // マクロを使う
    return RETURN_VALUE;
}

ENDCG

式をマクロにする

下記のようなマクロをつくることもできます。

CGPROGRAM

#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

// RETURNが「return saturate(pow(2, 2) - 3);」に置き換わる
#define RETURN return saturate(pow(2, 2) - 3);
            
float4 vert (float4 vertex : POSITION) : SV_POSITION
{
    return UnityObjectToClipPos(vertex);
}
            
fixed4 frag () : SV_Target
{
    RETURN
}

ENDCG

改行もできる

マクロの値に\記号を使えば改行もできます。

CGPROGRAM
            
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

// \記号で改行
#define RETURN float value = saturate(pow(2, 2) - 3); \
   return value;
            
float4 vert (float4 vertex : POSITION) : SV_POSITION
{
    return UnityObjectToClipPos(vertex);
}
            
fixed4 frag () : SV_Target
{
    RETURN
}

ENDCG

引数もとれる

マクロには引数も渡せます。

// 引数を渡せるマクロを定義
#define POW2(value) value * value

// 使う側
float val = POW2(0.5);

引数に渡した変数名にPrefixやSuffixをつける

トークン連結演算子を使えば、引数の変数名にPrefixやSuffixをつけられます。

// Suffixをつけるマクロを定義
#define ADD_SUFFIX(value) value##Tex 

fixed4 frag (v2f i) : SV_Target
{
    // _MainTexテクスチャをサンプリングする
    fixed4 col = tex2D(ADD_SUFFIX(_Main), i.uv);
    return col;
}

トーク演算子については下記のサイトが詳しいです。

#と##演算子