Version: 2021.3
言語: 日本語
ビルトインのシェーダー include ファイル
ビルトインシェーダーヘルパー機能

ビルトインのマクロ

Unity は、シェーダープログラム をコンパイルするときに、プリプロセッサーマクロをいくつか定義します。

ターゲットプラットフォーム

マクロ: ターゲットプラットフォーム:
SHADER_API_D3D11 Direct3D 11
SHADER_API_GLCORE デスクトップ向け OpenGL “core” (GL 3/4)
SHADER_API_GLES OpenGL ES 2.0
SHADER_API_GLES3 OpenGL ES 3.0/3.1
SHADER_API_METAL iOS/Mac Metal
SHADER_API_VULKAN Vulkan
SHADER_API_D3D11_9X ユニバーサル Windows プラットフォームをターゲットとする Direct3D 11 “Feature level 9.x”

SHADER_API_MOBILE は、すべての一般的なモバイルプラットフォーム (GLES、GLES3、METAL) のために定義されます。

追加で、シェーダー言語のターゲットが GLSL の場合に、SHADER_TARGET_GLSL が定義されます。(OpenGL/GLES では常に true)

シェーダーターゲットモデル

SHADER_TARGETマクロは、シェーダーターゲットのコンパイルのモデルにマッチする数値に定義されます (すなわち、#pragma target ディレクティブにマッチ)。例えば、shader model 3.0 にコンパイルするとき、SHADER_TARGET30 になります。以下の例に示すように、条件のチェックを行うための値をシェーダーコードで使用可能です。

# if SHADER_TARGET < 30
    // Shader model 3.0 より劣る。
    // かなり制限されたシェーダー能力。いくらかの近似を行います
#else
    // 適切な能力。より良い処理を行います
#endif

Unity バージョン

UNITY_VERSION は、Unity バージョンの数値を含みます。例えば、UNITY_VERSION は Unity 5.0.1 では 501 になります。これは、ビルトインシェーダーの異なる機能を使うシェーダーを記述する必要がある場合、バージョン比較用に使われます。例えば、#if UNITY_VERSION >= 500 でプリプロセッサをチェックすると、バージョン 5.0.0 もしくはそれ以降のバージョンのみが条件を満たします。

コンパイルされるシェーダーステージ

プリプロセッサーマクロの SHADER_STAGE_VERTEX, SHADER_STAGE_FRAGMENT, SHADER_STAGE_DOMAIN, SHADER_STAGE_HULL, SHADER_STAGE_GEOMETRY, SHADER_STAGE_COMPUTE は各シェーダーステージをコンパイルするときに定義されます。一般的に、プリプロセッサーマクロは、ピクセルシェーダーとコンピュートシェーダー間でシェーダーコードを共有するときに、何か微妙に異なるように処理したい場合に役立ちます。

マルチプラットフォーム対応のヘルパー

プラットフォームマクロを直接使用することは、コードの将来性を十分考慮してないため、推奨されません。例えば、D3D11 をチェックするシェーダーを記述した場合、将来的にはチェックの範囲を広げ Vulkan も確認する必要があるかもしれません。代わりの方法として Unity では複数のヘルパーマクロを HLSLSupport.cginc で定義しています。

マクロ: 用途:
UNITY_BRANCH 条件文の前に加え、実際のブランチの内部にコンパイルされることをコンパイラに示唆します。HLSL プラットフォーム上の場合は、[branch] に展開します。
UNITY_FLATTEN 条件文の前にこれを追加し、実際の分岐命令を回避するのに平坦化する必要があるということをコンパイラに示唆します。HLSL プラットフォーム上では、[flatten] に展開します。
UNITY_NO_SCREENSPACE_SHADOWS プラットフォームでカスケード式スクリーン空間シャドウマップを使用しないように定義します (モバイルプラットフォーム)。
UNITY_NO_LINEAR_COLORSPACE プラットフォームでリニアカラー空間をサポートしないように定義します (モバイルプラットフォーム)。
UNITY_NO_RGBM プラットフォームでライトマップのための RGBM 圧縮が使用されないように定義します (モバイルプラットフォーム)。
UNITY_NO_DXT5nm プラットフォームで DXT5nm の法線マップの圧縮を使用しないように定義します (モバイルプラットフォーム)。
UNITY_FRAMEBUFFER_FETCH_AVAILABLE framebuffer color fetch 機能が利用できる (一般的に iOS プラットフォーム - OpenGL ES 2.0, 3.0 と Metal) プラットフォームで定義します。
UNITY_USE_RGBA_FOR_POINT_SHADOWS ポイントライトのシャドウマップが、エンコードされた深度が含まれる RGBA テクスチャを使用するプラットフォーム上で定義されます (他のプラットフォームでは、シングルチャンネルの浮動小数点テクスチャが使用されます) 。
UNITY_ATTEN_CHANNEL ライト減衰テクスチャの、どのチャネルがデータを保有するかを定義し、ピクセルごとのライティングコードで使用されます。‘r’ または ‘a’ のいずれかに定義されます。
UNITY_HALF_TEXEL_OFFSET プラットフォームで、ピクセル (Direct3D 9 など) に対してマッピングテクセルで 1/2 テクセルのオフセット調整が必要なことを定義します。
UNITY_UV_STARTS_AT_TOP 常に 1 または 0 で定義されます。1 の値は、「テクスチャの一番上」で、テクスチャの V 座標が 0 であるプラットフォームで使用します。Direct3D のようなプラットフォームでは 1 を使用し、Open-GL のようなプラットフォームでは 0 を使用します。
UNITY_MIGHT_NOT_HAVE_DEPTH_Texture 手動で深度をテクスチャにレンダリングして、プラットフォームがシャドウマップか深度テクスチャをエミュレートするか定義します。
UNITY_PROJ_COORD(a) 4 次元ベクトルを渡すと、投影されたテクスチャ読み込みに適切なテクスチャ座標を戻します。ほとんどのプラットフォームでは渡された値そのものを戻します。
UNITY_NEAR_CLIP_VALUE ニアクリッピングプレーンの値として定義されます。Direct3D のようなプラットフォームでは 0.0 が使用され、OpenGL のようなプラットフォームでは –1.0 を使用します。
UNITY_VPOS_TYPE データ型はピクセル位置の入力 (VPOS) に必要なデータ型を定義します。D3D9には float2 、その他は float4
UNITY_CAN_COMPILE_TESSELLATION シェーダーコンパイラが、テッセレーションシェーダーの HLSL 文法 (現時点では D3D11 のみ) を “理解できる” 場合に定義されます。
UNITY_INITIALIZE_OUTPUT(type,name) 指定された の変数 name を 0 に初期化します。
UNITY_COMPILER_HLSL, UNITY_COMPILER_HLSL2GLSL, UNITY_COMPILER_CG シェーダーのコンパイルにどのシェーダーコンパイラーが使用されるかを示します。詳細については、シェーダーのコンパイル のドキュメントを参照してください。コンパイラー間で非常に特殊なシェーダー構文処理の違いに遭遇し、各コンパイラーごとに異なるコードを書きたい場合に使用してください。
  • UNITY_REVERSED_Z - リバース Z バッファを使って、プラットフォーム上で定義されます。格納した Z 値は、 0 - 1 ではなく、 1 - 0 の間です。

シャドウマッピングマクロ

シャドウマップの宣言およびサンプリングはプラットフォームにより大きくことなる場合があるため、Unity にはこれをサポートするマクロが複数あります。

マクロ: 用途:
UNITY_DECLARE_SHADOWMAP(tex) tex という名前のシャドウマップテクスチャ変数を宣言します。
UNITY_SAMPLE_SHADOW(tex,uv) tex という名前のシャドウマップテクスチャを特定の uv 座標にサンプリングします (XY コンポーネントはテクスチャの場所、Z コンポーネントは相対的な深度)。0 - 1 の範囲でシャドウとしてひとつの float 変数を戻します。
UNITY_SAMPLE_SHADOW_PROJ(tex,uv) 上記と同様ですが、投影法のシャドウマップ読み込みを行います。uv は float4 であり、他のすべてのコンポーネントはルックアップをするために .w で除算します。

注意 すべてのグラフィックカードがシャドウマップをサポートしているわけではありません。サポートの有無を確認するには SystemInfo.SupportsRenderTextureFormat を使用してください。

定数バッファマクロ

Direct3D 11 はすべてのシェーダー変数を “constant buffer” (定数バッファ) にグループ分けします。Unity ビルトインの変数のほとんどはすでにグループ分けされてますが、自身で作成するシェーダーの変数については、予想される更新頻度に応じて、別の constant buffer に格納することが最適です。

CBUFFER_START(name)CBUFFER_END マクロをその場合に使用します。

CBUFFER_START(MyRarelyUpdatedVariables)
    float4 _SomeGlobalValue;
CBUFFER_END

テクスチャ/サンプラーの変数を宣言するマクロ

テクスチャとサンプラーペアを宣言する場合、通常、シェーダーコードに texture2D を使用します。 しかし、いくつかのプラットフォーム(DX11 など)では、テクスチャとサンプラーは別々のオブジェクトで、 最大可能サンプラー数はきわめて限られています。Unity はサンプラーなしでテクスチャを宣言するマクロをいくつか有しています。 また、それらのマクロで別のテクスチャからサンプラーを使用してテクスチャをサンプリングすることもできます。 サンプラーの限界に達してしまい、いくつかのテクスチャが、 実際、サンプラーを共有できる場合 (サンプラーによってテクスチャフィルタリングとラッピングモードが決定されます)、このマクロを使用できます。

マクロ: 用途:
UNITY_DECLARE_TEX2D(name) テクスチャとサンプラーのペアを宣言します。
UNITY_DECLARE_TEX2D_NOSAMPLER(name) サンプラーなしでテクスチャを宣言します。
UNITY_DECLARE_TEX2DARRAY(name) テクスチャ配列のサンプラー変数を宣言します。
UNITY_SAMPLE_TEX2D(name,uv) 指定されたテクスチャ座標を使用してテクスチャとサンプラーのペアからサンプリングします。
UNITY_SAMPLE_TEX2D_SAMPLER( name,samplername,uv) 別のテクスチャ (samplername) からサンプラーを使用してテクスチャ (name) からサンプリングします。
UNITY_SAMPLE_TEX2DARRAY(name,uv) float3 UV のテクスチャ配列からサンプリングします。座標の z コンポーネントは配列のインデックスです。
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) 明白なミップマップレベルが設定されたテクスチャ配列からサンプリングします。

詳細は、サンプラーの状態 を参照してください。

サーフェイスシェーダーパスインジケーター

サーフェスシェーダー がコンパイルされるとき、ライティングをするために、さまざまなパス向けに大量のコードを生成することになります。各パスをコンパイルするとき、次のうちのいずれかのマクロが定義されます。

マクロ: 用途:
UNITY_PASS_FORWARDBASE フォワードレンダリングのベースパス (メインの指向性ライト、ライトマップ、SH)
UNITY_PASS_FORWARDADD フォワードレンダリングの追加パス (パスごとにひとつのライト)
UNITY_PASS_DEFERRED ディファードシェーディングパス (G バッファをレンダリング)
UNITY_PASS_SHADOWCASTER シャドウキャスターと深度テクスチャレンダリングパス
UNITY_PASS_PREPASSBASE 古いデファードライティングのベースパス (法線や鏡面反射指数をレンダリング)
UNITY_PASS_PREPASSFINAL 古いデファード ライティングの最終的なパス (ライティングとテクスチャに適用)

自動アップグレードを無効にする

UNITY_SHADER_NO_UPGRADE を使うと、Unity が自動的にシェーダーファイルをアップグレードするのを無効にすることができます。

深度テクスチャのヘルパーマクロ

ほとんどの場合深度テクスチャはカメラからの深度をレンダリングするのに使用されます。内蔵のシェーダー include ファイル には上記の複雑さに対応するためのマクロが含まれています。

  • UNITY_TRANSFER_DEPTH(o): これは頂点の Eye Space Depth (視点空間深度)を計算し、o ( float2 であることが必須) に出力します。深度テクスチャに対してレンダリングするときに頂点プログラムで使用してください。ネイティブ深度テクスチャのあるプラットフォームでは、Z バッファの値は暗黙的にレンダリングされるため、このマクロは何もしません。
  • UNITY_OUTPUT_DEPTH(i): これは頂点の Eye Space Depth を i (float2 であることが必須)から戻します。深度テクスチャに対してレンダリングするときに、フラグメントプログラムで使用してください。ネイティブ深度テクスチャのあるプラットフォームではこのマクロは、Z バッファ値が暗黙的にレンダリングされるため、常に 0 を戻します。
  • COMPUTE_EYEDEPTH(i): これは頂点の Eye Space Depth を計算し、o に出力します。頂点プログラムで、深度テクスチャに レンダリングしない ときに、使用します。
  • DECODE_EYEDEPTH(i)/LinearEyeDepth(i): 深度テクスチャ i の高精度値を指定すると、対応する Eye Space Depth を返します。
  • Linear01Depth(i): 深度テクスチャ i の高精度値を指定すると、対応する 0 と 1 の間の範囲の直線深度を返します。

ノート: DX11/12 と Metal では、Z バッファの範囲は 1 から 0、UNITY_REVERSED_Z は定義されます。他のプラットフォームでは、範囲は 0 から 1 です。

例えば、このシェーダーはオブジェクトの深度をレンダリングします。

Shader "Render Depth" {
    SubShader {
        Tags { "RenderType"="Opaque" }
        Pass {
            CGPROGRAM

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

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

            v2f vert (appdata_base v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                UNITY_TRANSFER_DEPTH(o.depth);
                return o;
            }

            half4 frag(v2f i) : SV_Target {
                UNITY_OUTPUT_DEPTH(i.depth);
            }
            ENDCG
        }
    }
}
ビルトインのシェーダー include ファイル
ビルトインシェーダーヘルパー機能