Version: 2023.1
言語: 日本語
HLSLで特定のグラフィックス API とプラットフォームを対象にする方法
シェーダーセマンティクス

HLSL のシェーダーキーワードの宣言と使用

シェーダーキーワードを宣言すると、キーワードを有効または無効にしたときにシェーダーに異なる動作を行わせることが可能です。

シェーダーキーワードは、サーフェスシェーダーコンピュートシェーダー などの通常のグラフィックスシェーダーで宣言できます。

プラグマを使ってシェーダーキーワードを宣言する

シェーダーキーワードを宣言するには、HLSL コードの中で以下のような #pragma ディレクティブを使用します。

# pragma shader_feature REFLECTION_TYPE1 REFLECTION_TYPE2 REFLECTION_TYPE3

以下のシェーダーディレクティブのいずれかを使用できます。

シェーダーディレクティブ バッチ処理タイプ Unityが作成するシェーダーバリアント
shader_feature 静的分岐 ビルド時に有効にしたキーワードの組み合わせのバリアント
multi_compile 静的分岐 キーワードのあらゆる組み合わせに対応するバリアント
dynamic_branch 動的分岐 バリアントなし

いつ、どのシェーダーディレクティブを使うか について詳しくは、こちらを参照してください。

シェーダーキーワードの制限 に関しては、こちらを参照してください。

キーワードセットの仕組み

1 つの #pragma ステートメントに含まれるキーワードは、まとめて ‘セット’ と呼ばれます。セット内の複数のキーワードを同時に有効にしたり無効にしたりできます。

例えば、3 つのキーワードのセットは以下のように宣言します。

# pragma shader_feature REFLECTION_TYPE1 REFLECTION_TYPE2 REFLECTION_TYPE3

1 つのシェーダーで複数のキーワードセットを宣言できます。例えば、2 つのセットを作成します。

# pragma shader_feature REFLECTION_TYPE1 REFLECTION_TYPE2 REFLECTION_TYPE3
# pragma shader_feature RED GREEN BLUE WHITE

以下のことはできません。

  • 1 つのセットに同じ名前の 2 つのキーワードを加える。
  • 1 つのシェーダーに重複するキーワードセットを加える。
  • キーワードを dynamic_branchshader_feature/multi_compile 両方で宣言する。(これを行うと Unity は dynamic_branch を使用します。)

シェーダーの動作を条件付きにする

シェーダーキーワードを有効にするか無効にするかに基づいて、シェーダーコードの一部を条件付きでマークするには、HLSL if ステートメント を使用します。

例:

# pragma multi_compile QUALITY_LOW QUALITY_MED QUALITY_HIGH

if (QUALITY_LOW)
{
    // code for low quality setting
}

Inspector、または C# スクリプト を使って、キーワードを有効または無効にできます。

Unity がシェーダーコードで何をするかは、どのシェーダーディレクティブを使うかによります。

dynamic_branch を使用する場合、Unity はキーワードごとに統一されたブーリアン変数を作成します。キーワードを有効にすると、Unity はその変数のブール値をtrue に設定し、GPU はそのキーワードの if ステートメントのコードを使用するように切り替えます。これが動的分岐です。

shader_feature または multi_compile を使用すると、Unity はキーワードの状態ごとに別々の シェーダバリアント を作成します。各バリアントには、そのキーワードの if ブランチのコードが含まれます。キーワードを有効にすると、Unity は一致するバリアントを GPU に送ります。これが静的分岐です。

いつ、どのシェーダーディレクティブを使うか について詳しくは、こちらを参照してください。

他のステートメントを使用してシェーダーの動作を条件付きにする

以下の HLSL ステートメントを使って条件付きコードを作成することもできます。

if の代わりにこれらを使うと、#pragmaキーワードディレクティブを後で変更するのがより難しくなります。例えば、シェーダーバリアントの数を減らす必要がある場合、multi_compileshader_feature に変更するのが難しくなります。

キーワードをローカルにする

キーワードはデフォルトでグローバルです。

キーワードをローカルにするには、シェーダーディレクティブに _local を加えます。グローバルキーワードを有効または無効にする場合、同じ名前のローカルキーワードの状態には影響しません。

例:

# pragma shader_feature_local QUALITY_LOW QUALITY_MED QUALITY_HIGH

キーワードをシェーダーステージに制限する

キーワードを宣言すると、Unity はシェーダーのすべてのステージにそのキーワードの条件コードが含まれていると仮定します。

以下のサフィックスを追加して、特定のステージだけがキーワードの条件付きコードを含むことを示すことができます。これは Unity が不要なシェーダーバリアントを取り除くのに役立ちます。

  • _vertex
  • _fragment
  • _hull
  • _domain
  • _geometry
  • _raytracing

例えば、#pragma shader_feature_fragment RED GREEN BLUE を使うと、3 つのキーワードを使ってフラグメントステージでのみ条件付きコードを作成することを示します。

dynamic_branchはバリアントを作らないので、#pragma dynamic_branchにこれらのサフィックスをつけることはできません。

これらのサフィックスは、グラフィックス API によって動作が異なったり、効果がなかったりします。

  • サフィックスは OpenGL、OpenGL ES、Vulkan には効果がありません。
  • サフィックス _geometry_raytracing はMetal には効果がなく、Metal は _vertex_hull_domain を 1 つのステージとして扱います。

キーワードをシェーダーモデルと GPU 機能に制限する

pragma require ディレクティブと #pragma target ディレクティブにキーワードを加えられます。これにより、現在のハードウェアが特定のシェーダーモデルや GPU 機能を使用している場合にのみ、条件付きコードが実行されるようになります。

詳細については、HLSL でシェーダーモデルと GPU 機能をターゲットにする を参照してください。

無効にしたキーワードのシェーダーバリアントを作成する

shader_feature を使用して 1 つのキーワードを作成すると、Unity はその機能が無効になっているときのために 2 つ目のバリアントを自動的に作成します。これは、有効にしたり無効にしたりするキーワードの数を減らすのに役立ちます。例えば、以下のコードは 2 つのバリアントを作成します。

# pragma shader_feature EXAMPLE_ON

multi_compile を使用する場合、または shader_feature を使用して 2 つ以上のキーワードのセットを作成する場合、キーワードセットを宣言するときに _ を使用できます。Unity は、そのセット内のすべてのキーワードが無効な場合のために、シェーダーのバリアントを作成します。

# pragma multi_compile _ EXAMPLE_ON
# pragma shader_feature _ RED GREEN BLUE WHITE

ショートカットを使ってキーワードセットを作成する

Unity シェーダーディレクティブのショートカットを使用して、シェーダーバリアントのセットを作成できます。以下の例では、SHADOWS_DEPTHSHADOWS_CUBE バリアントを加える方法を説明します。

# pragma multi_compile_shadowcaster

skip_variants を使って不要なキーワードを削除できます。例えば、Unity が multi_compile_fwdadd からバリアントを生成するときに POINTPOINT_COOKIES バリアントを削除するには以下を使います。

# pragma multi_compile_fwdadd
# pragma skip_variants POINT POINT_COOKIE

以下のショートカットは、ビルトインレンダーパイプラインのライト、影、ライトマッピングに関するものです。

  • multi_compile_fwdbase は、このキーワードセットを加えます。DIRECTIONAL LIGHTMAP_ON DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON SHADOWS_SCREEN SHADOWS_SHADOWMASK LIGHTMAP_SHADOW_MIXING LIGHTPROBE_SH。これらのバリアントは、PassType.ForwardBase で必要となります。
  • multi_compile_fwdbasealpha は、以下のキーワードセットを追加します。DIRECTIONAL LIGHTMAP_ON DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON LIGHTMAP_SHADOW_MIXING VERTEXLIGHT_ON LIGHTPROBE_SH。これらのバリアントは、PassType.ForwardBase で必要となります。
  • multi_compile_fwdadd は、以下のキーワードセットを追加します。POINT DIRECTIONAL SPOT POINT_COOKIE DIRECTIONAL_COOKIE。これらのバリアントは、PassType.ForwardAdd で必要となります。
  • multi_compile_fwdadd_fullshadows は、以下のキーワードセットを追加します。POINT DIRECTIONAL SPOT POINT_COOKIE DIRECTIONAL_COOKIE SHADOWS_DEPTH SHADOWS_SCREEN SHADOWS_CUBE SHADOWS_SOFT SHADOWS_SHADOWMASK LIGHTMAP_SHADOW_MIXING。これは multi_compile_fwdadd と同じですが、ライトがリアルタイムの影を作れるようになります。
  • multi_compile_lightpass は、以下のキーワードセットを追加します。POINT DIRECTIONAL SPOT POINT_COOKIE DIRECTIONAL_COOKIE SHADOWS_DEPTH SHADOWS_SCREEN SHADOWS_CUBE SHADOWS_SOFT SHADOWS_SHADOWMASK LIGHTMAP_SHADOW_MIXING。これは事実上、ライトプローブ以外に、リアルタイムのライトと影に関連するすべての機能の包括的なショートカットです。
  • multi_compile_shadowcaster は、以下のキーワードセットを追加します。SHADOWS_DEPTH SHADOWS_CUBE。これらのバリアントは、PassType.ShadowCaster に必要です。
  • multi_compile_shadowcollector は、以下のキーワードセットを追加します。SHADOWS_SPLIT_SPHERES SHADOWS_SINGLE_CASCADE。multi_compile_shadowcollector は、これらのキーワードをまったく含まないバリアントもコンパイルします。 これらのバリアントは、スクリーンスペースシャドウに必要です。
  • multi_compile_prepassfinal は、以下のキーワードセットを加えます。LIGHTMAP_ON DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON UNITY_HDR_ON SHADOWS_SHADOWMASK LIGHTPROBE_SH。multi_compile_prepassfinal は、これらのキーワードをまったく含まないバリアントもコンパイルします。 これらのバリアントは PassType.Deferred に必要です。

以下のショートカットは、他の設定と関連しています。

  • multi_compile_particles は、ビルトインのパーティクルシステムに関連する以下のキーワードを追加します: SOFTPARTICLES_ON。multi_compile_particles は、このキーワードを含まないバリアントもコンパイルします。詳しくは、Built-in Particle System を参照してください。
  • multi_compile_fog は、フォグに関連する以下のキーワードを追加します: FOG_LINEAR, FOG_EXP, FOG_EXP2。multi_compile_fog は、このキーワードを含まないバリアントもコンパイルします。この動作は、Graphics 設定 ウィンドウ で制御できます。
  • multi_compile_instancing は、インスタンシングに関連するキーワードを追加します。シェーダーがプロシージャルなインスタンシングを使用する場合、以下の一連のキーワードを追加します: INSTANCING_ON PROCEDURAL_ON。そうでない場合は、INSTANCING_ON を追加します。また、multi_compile_instancing は、これらのキーワードを含まないバリアントもコンパイルします。この動作は Graphics 設定 ウィンドウ で制御できます。
HLSLで特定のグラフィックス API とプラットフォームを対象にする方法
シェーダーセマンティクス