e.blog

主にUnity周りのことについてまとめていきます

ShaderLabについてメモ

もっぱらQiitaで記事を書いていましたが、そろそろUnityの話題に絞ったブログを作りたくなったので、過去に少しだけ使っていたこのブログをまっさらにしました。 今後のUnityの記事はここにまとめていこうと思います。

ということで、第一回目はメモとして残しておいたやつを投稿しておこうと思いますw

Propertiesに使える属性

Propertiesにはいくつかの属性を指定することができるようになっています。 指定できる属性は以下の通り。(詳細はドキュメントをご覧ください)

  • [HideInInspector] ... マテリアルインスペクタでプロパティを非表示にする
  • [NoScaleOffset] ... 属性のテクスチャに関して、マテリアルインスペクタの texture tiling / offset を非表示にする
  • [Normal] ... テクスチャが法線マップであることを示す
  • [HDR] ... テクスチャが High Dynamic Range (HDR) テクスチャであることを示す
  • [Gamma] ... Float / Vector プロパティがUIでsRGB値で指定されており、使用するカラースペースに応じて変換が必要な可能性があることを示す
  • [PerRenderData] ... テクスチャは MaterialPropertyBlock の形式の各レンダラーごとのデータであることを示す(マテリアルインスペクタでは、このプロパティのテクスチャ部分のUIが変わる)
  • [KeywordEnum(A,B,C)] ... Enumとして値を設定できるようにする

バリアントについて(#pragma multi_compile A B)

バリアントを定義し、マルチコンパイルすることで、複数の状態に応じたシェーダをコンパイルすることができるようです。 (ドキュメントはこちら

なお、詳細についてはこちらの記事(UnityのShader Variantについて調べてみた)が分かりやすいです。

バリアントについては以下のように #pragma を用いて宣言します。

#pragma multi_compile __ A B C

ここで、__ はどれも指定されていない場合の処理もコンパイルしてほしいことをコンパイラに伝えます。

使い方は以下のようになります。

fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

#ifdef A
c.rgb += fixed3(0.5, 0.0, 0.0);
#elif B
c.rgb += fixed3(0.0, 0.5, 0.0);
#elif C
c.rgb += fixed3(0.0, 0.0, 0.5);
#endif

こうしておくことで、それぞれのバリアントが定義されているときように、すべての状態のシェーダがコンパイルされます。(なので マルチ なんですね)

[KeywordEnum()]を応用する

[KeywordEnum()] を応用することで、このバリアントをインスペクタから設定することも可能になります。

※ 注意点として、定義するバリアントはすべて大文字である必要があります。(小文字を含めるとうまく動きません)

各Pass共通の処理をまとめておく

以下のように CGINCLUDE を利用して、各Passで使う共通の処理などをまとめておくことができます。 (もし頂点シェーダの挙動はどれも共通で、フラグメントシェーダだけ違う、という場合も、ここに頂点シェーダを書いておいて使いまわすことができます)

Shader "Custom/AnyShader" {
    Properties {
        // ...
    }

    CGINCLUDE
    #include "UnityCG.cginc"
    
    sampler2D _MainTex;

    struct v2f {
        float4 pos : SV_POSITION;
        float2 uv : TEXCOORD0;
    };

    v2f vert(appdata_base v) {
        v2f o;
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = v.normal;
        return o;
    }
    ENDCG

    SubShader {
        Pass {
            // ...
            #pragma vertex vert
            // ...
        }
    }
}

セマンティクス

入力・出力に意味づけするもの。SV_POSITION などと指定しているのがそれ。

  • COLOR
  • SV_POSITION ... プロジェクション後の座標
  • POSITION ... 空間中の座標
  • TEXCOORD0
  • NORMAL ... 法線
  • TANGENT ... 接線
  • WPOS ... フラグメントシェーダで現在扱っているピクセルの座標