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

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

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

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

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

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

#pragma shader_feature REFLECTION_TYPE1 REFLECTION_TYPE2 REFLECTION_TYPE3

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

シェーダーディレクティブ Branching type Unityが作成するシェーダーバリアント
shader_feature Static branching Variants for keyword combinations you enable at build time
multi_compile Static branching Variants for every possible combination of keywords
dynamic_branch Dynamic branching No variants

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

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

How sets of keywords work

The keywords in a single #pragma statement are together called a ‘set’. You can enable or disable multiple keywords in a set at the same time.

For example, to declare a set of three keywords:

#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

You can’t do the following:

  • Include two keywords with the same name in one set.
  • 1 つのシェーダーに重複するキーワードセットを加える。
  • Declare a keyword as both dynamic_branch and shader_feature or multi_compile - Unity uses dynamic_branch if you do this.

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

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

例:

#pragma multi_compile QUALITY_LOW QUALITY_MED QUALITY_HIGH

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

You can enable and disable keywords using the Inspector or C# scripting.

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

If you use dynamic_branch, Unity creates a uniform Boolean variable for each keyword. When you enable a keyword, Unity sets the Boolean for that variable to true, and your GPU switches to using the code in the if statement for that keyword. This is dynamic branching.

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

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

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

You can also use the following HLSL statements to create conditional code:

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

Make keywords local

Keywords are global by default.

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

例:

#pragma shader_feature_local QUALITY_LOW QUALITY_MED QUALITY_HIGH

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

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

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

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

For example, use #pragma shader_feature_fragment RED GREEN BLUE to indicate that you use the 3 keywords to create conditional code in the fragment stage only.

You can’t add these suffixes to #pragma dynamic_branch because dynamic_branch doesn’t create variants.

These suffixes may behave differently or have no effect depending on the graphics API:

  • The suffixes have no effect on OpenGL, OpenGL ES or Vulkan.
  • The _geometry and _raytracing suffixes have no effect on Metal, and Metal treats _vertex, _hull and _domain as a single stage.

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

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

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

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

If you use shader_feature to create a single keyword, Unity automatically creates a second variant for when the feature is disabled. This helps reduce the number of keywords you need to enable and disable. For example, the following code creates 2 variants:

# pragma shader_feature EXAMPLE_ON

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

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

Use shortcuts to create keyword sets

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

#pragma multi_compile_shadowcaster

You can remove keywords you don’t need using skip_variants. For example, use the following to remove POINT and POINT_COOKIES variants when Unity generates variants from multi_compile_fwdadd.

# 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.LightPrePassFinalPassType.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 とプラットフォームを対象にする方法
シェーダーセマンティクス