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_DESKTOP |
Windows, Mac and Linux desktop platforms, WebGL, Stadia |
SHADER_API_MOBILE |
iOS and Android mobile platforms, tvOS |
追加で、シェーダー言語のターゲットが GLSL の場合に、SHADER_TARGET_GLSL
が定義されます。(OpenGL/GLES では常に true)
SHADER_TARGET
マクロは、シェーダーターゲットのコンパイルのモデルにマッチする数値に定義されます (すなわち、#pragma target
ディレクティブにマッチ)。例えば、shader model 3.0 にコンパイルするとき、SHADER_TARGET
は 30
になります。以下の例に示すように、条件のチェックを行うための値をシェーダーコードで使用可能です。
# if SHADER_TARGET < 30
// Shader model 3.0 より劣る。
// かなり制限されたシェーダー能力。いくらかの近似を行います
#else
// 適切な能力。より良い処理を行います
#endif
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 |
Defined on platforms that need a half-texel offset adjustment in mapping texels to pixels. |
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 ファイル には上記の複雑さに対応するためのマクロが含まれています。
ノート: 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
}
}
}