【Unity】【シェーダ】Surface Shader入門


はじめに

・何番せんじとか気にせず、自分の中でこのサイトさえ参照すれば事足りるを作っていきたい。要はチートシート

ShaderLab

・Unityの全てのファイルシェーダは「ShaderLab」という宣言型言語で記述される。

種類に関係無く、シェーダーのコードの中身は実際にはどれも ShaderLab にラップされています。ShaderLab はシェーダーの構造を整理するのに使われています。以下はその例です。
ShaderLab シンタックス で ShaderLab シンタックスの基本的な概念について読んでから、以下のチュートリアルに進むことをお勧めします。
※1

最小構成コード

Shader "Custom/001_ChangeColorShader"
{
    Properties {
        _Color ("Main Color", Color) = (1,.5,.5,1)
    }
    SubShader
    {
        Pass
        {
          Tags{"RenderType"="Opaque" }
          #pragma surface surf Standard fullforwardshadows vertex:vert
          #pragma target 3.0
          ~~  
        }
    }
    SubShader {
        ~~~
    }
    Fallback "Diffuse"
}

Shader

・Materialのインスペクタからシェーダを選択する際に使用される。(下図参照)
・一番外のブロックに記載する。
・「/」を付けることで階層管理できる。
・シェーダファイル名と別の名前を付けてもよいが、分かりづらくなるため統一したほうがいいかも。
※2

 Shader "Custom/001_ChangeColorShader"

Properties

・シェーダで使用するパラメタをインスペクタから設定可能にするための定義。
・ColorとVectorはシェーダ内では同じ型「float4」なので、プロパティの型をVectorにして色情報を設定してもエラーにはならない。
  (分かりづらいのでそうするべきではないが。)
※3

構文
  Properties {
    シェーダ内のパラメタ名 ("インスペクタに表示される文字列", ) = 初期値
  }
記述例
    Properties
    {
        // テキスト(整数)
        _Param0 ("Param0", Int) = 0
        // テキスト(小数)
        _Param1 ("Param1", Float) = 1.0
        // スライダ
        _Param2 ("Param2", Range(0.0, 10.0)) = 3.0
        // 色 (RGBA)
        _Param3 ("Param3", Color) = (1.0, 0.5, 1.0, 1.0)
        // ベクタ (XYZW)
        _Param4("Param4", Vector) = (1.0, 0.5, 1.0, 1.0)
        // テクスチャ (デフォルト値は 空文字、白、赤、グレー、バンプ、赤を設定できる。)
        _Param5 ("Param5", 2D) = "white" {}
    }

SubShader / Fallback

・SubShaderは複数, Fallbackは一つ定義できる。
・ユーザのPCで動作できる(スペックが満たせている)SubShaderがあればそれを1つ実行する。
・ユーザのPCのスペックが低く、どのSubShaderも実行できない場合、Fallbackシェーダと呼ばれるUnityのデフォルトシェーダを実行する。
※2

構文
    SubShader { ~~~ }
    SubShader { ~~~ }
    Fallback "~~~"

Pass

・SubShader内に複数定義できる。
・1つのPassで1回分の描画を行う。当然Passの定義が多いほど負荷が大きくなる。
※2

構文
    SubShader
    {
      Pass { ~~~ }  
      Pass { ~~~ }
    }

Tags

・シェーダの設定されたオブジェクトを「いつ」「どのように」描画するかを定義する。

Queue

・描画順序を定義する。(番号の若い順に描画する。)

種類 使用例 ソート番号
BackGround スカイボックス 1000
Geometry 不透明オブジェクト 2000
Transparent 半透明オブジェクト 3000
Overlay オーバーレイエフェクト 4000

・プラスすることで描画順序を微調整できる。

構文
   Tags {"Queue" = "Geometry+1"} // 2001

Render Type

・まだ理解できていないが以下のお決まりの形で設定する。

種類 使用例
Opaque 不透明オブジェクト
Transparent 半透明オブジェクト
構文
   Tags {"RenderType" = "Opaque"}

Pragma

surface

・surface : 自身がsurfaceシェーダであることを宣言する。
・サーフィス関数名 : 使用するサーフィス関数名
・ライティング関数名 : ライティングに使用する関数名。デフォルトはStandard
・バーティクス関数 : フックしたい自作のバーティクス関数名
・オプション : 処理軽減等様々なオプションを指定できる。(詳細については※7 公式リファレンス参照)

構文
    #pragma surface サーフィス関数名 ライティング関数 [オプション] vertex:バーティクス関数
記述例
    #pragma surface surf Standard fullforwardshadows vertex:vert

target

・コンパイルのレベル
・より高機能な記述をする場合、高いレベルが必要になる
※9 公式リファレンス

変数

・SubShader内で利用する変数の型は、Propertiesのそれと異なる。

変数の種類

説明
float 32ビット浮動小数点数
half 16ビット浮動小数点数
fixed 11ビット浮動小数点数
float4x4 4x4行列
sampler2D テクスチャ

変数の操作

・複数のパラメタを保持できる。(「packed array」と呼ぶ。)
fixed3 a; (fixed型の変数を3つ代入できる。)
・fixed3にfixed4の値を代入できる。
o.Albedo = _Color.rgb;
・変数の入れ替えができる。
o.Albedo = _Color.bgr;
・fixed4に単体の値を代入できる
o.Albedo = 1; //(1, 1, 1)
・行列の特定要素の参照
float4x4 mat;
mat._m12; (1行2列目の値)

Cg関数, ビルドイン変数/関数

Cg言語

・Cg言語で定義された関数を使用することができる。
・Cg言語はGPUのハードウェア上に定義されたものでNVIDIA社が作成している。
※4 公式リファレンス

関数 意味
abs(x)        abx(-3) = 3        絶対値     
dot(v1, v2) v1とv2の内積
saturate saturate(-1.5) = -1 -1以下を-1, 1以上を1として -1 ~ 1を返却する。
max(0, min(1, x))と同義
pow(x, y) pow(3, 4) = 81 xのy乗
lerp(x, y, p) lerp(1.0, 2.0, 0.1) = 1.1 線形補間 (x * p + y * (p - 1))
distance(v1, v2) 2点間の距離
frac(x) frac(2.3) = 0.3 小数部
floor(y) floor(2.3) = 2.0 整数部
mul(m1, m2) 行列の積

Unityが定義するビルドイン変数, 関数

・「Unityのインストールディレクトリ/Editor/Data/CGIncludes」の.cgincファイルをインクルードすることで便利な機能が利用できる。
・例) ライティング関数「Lambert」「BlinnPhong」「Standard」はLighting.cginc, UnityPBSLighting.cgincに定義されている。
※5 ビルドイン機能の公式リファレンス
・古いバージョンのビルドインシェーダは※6 公式サイトからダウンロードできる。

その他

discard

・レンダリング処理を行わない。

カスタムシェーダライブラリの作成

  1. Unityのプロジェクト内に.cgincファイルを作成する。
    (エクスプローラ上で作成し、ドラッグ&ドロップする。)
  2. ファイルを下記のように定義する。
MyUtility.cginc
#ifndef ANY_UNIQUE_NAME
#define ANY_UNIQUE_NAME
 共通化したい処理
#endif

3.利用する側は#includeを使用する。その際のパスは利用側シェーダファイルからの相対パスを設定する。

参考サイト

Unity 公式リファレンス
1. シェーダを書く
2. ShaderLabシンタックス
3. ShaderLab: Properties
5. 定義済みシェーダープリプロセッサーマクロ
6. Unity download archive
7. サーフェスシェーダーの記述
8. ShaderLab : SubShader 内の Tags
9. シェーダーコンパイルターゲットレベル
NVidea 公式リファレンス
4. Cg 3.1 Toolkit Documentation