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

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

このページでは、HLSL コードでシェーダーキーワードを使用する際の情報を提供します。シェーダーキーワードの一般的な導入は、シェーダーキーワード を参照してください。Shader Graph でのシェーダーキーワードの宣言と使用については、Keywords を参照してください。

HLSL コードでは、#pragma ディレクティブを使って、シェーダーキーワードと #if ディレクティブを宣言し、コードがシェーダーキーワードの状態に依存することを示します。シェーダーキーワードは、通常のグラフィックシェーダー (サーフェスシェーダー を含む) と コンピュートシェーダー で使用できます。

シェーダーキーワードの宣言

シェーダーキーワードを宣言するには、HLSL コードの中で次の #pragma ディレクティブのいずれかを使用します。

ディレクティブ 説明 
#pragma multi_compile 一群のキーワードを宣言します。

デフォルトでは、これらのキーワードはグローバルスコープを持ち、すべてのシェーダーステージに影響を与えます。

ビルドプロセスは、このセットのすべてのキーワードを含みます。
#pragma shader_feature 一群のキーワードを宣言します。また、これらのキーワードのがひとつも有効になっていないバリアントをコンパイルするようにコンパイラーに指示します。

デフォルトでは、これらのキーワードはグローバルスコープを持ち、すべてのシェーダーステージに影響を与えます。

ビルドプロセスは、ビルド時に使用されているこの一群のキーワードを含みます。

#pragma multi_compile#pragma shader_feature の違いと、いつどちらを使うべきかのガイダンスについては、シェーダーキーワード を参照してください。

また、これらのディレクティブにサフィックスを追加して、その動作を変更することもできます。

  • _vertex_fragment_hull_domain_geometry_raytracing を加えて、この一群のキーワードが特定のシェーダーステージにのみ影響することを示します。これにより、必要のないシェーダーバリアントの数を減らすことができます。詳細については、シェーダーキーワード: ステージ固有のキーワード を参照してください。

    これらのサフィックスを #pragma multi_compile または #pragma shader_feature ディレクティブに加えることができます。例えば、#pragma multi_compile_vertex#pragma shader_feature fragment はどちらも有効です。
  • _ local を追加して、このキーワードのセットがローカルスコープであることを示します。キーワードのローカルスコープとグローバルスコープの詳細については、シェーダーキーワード: ローカルまたはグローバルスコープ を参照してください。

    このサフィックスを、#pragma multi_compile#pragma shader_feature ディレクティブや、すでにステージ固有のサフィックスを持っているすべてのバリエーションに加えることができます。例えば、#pragma multi_compile_local#pragma multi_compile_vertex_local#pragma shader_feature_local#pragma shader_feature_fragment_local はすべて有効です。

さらに、#pragma multi_compile には、あらかじめ定義されたキーワード群を追加する “ショートカット” があります。これらの詳細については、multi_compile shortcuts を参照してください。

キーワード群の宣言

一群のキーワードをまとめて宣言します。群には、相互に排他的なキーワードが含まれます。

一群のキーワードを宣言するには、#pragma multi_compile または #pragma_shader_feature ディレクティブの後に、スペースで区切られたキーワードのリストを使用します。

この例では、4 つのキーワードをまとめて宣言する方法を示します。

# pragma multi_compile QUALITY_LOW QUALITY_MEDIUM QUALITY_HIGH QUALITY_ULTRA

内部的には、#define ディレクティブを使うことで動作します。Unity がシェーダーをコンパイルするとき、QUALITY_LOW 定義されているもの、QUALITY_MEDIUM が定義されているもの、QUALITY_HIGH が定義されているもの、QUALITY_ULTRA が定義されているもの、の 4 つのバリアントが生成されます。ランタイムには、どのキーワードが有効になっているかに基づいて、適切なバリアントを使用します。

#pragma shader_feature を使って一群のキーワードを宣言すると、Unity はそれらのキーワードが一切定義されていないバリアントもコンパイルします。これにより、追加のキーワードを使わずに動作を定義することができます。キーワードの数を減らすことにはいくつかの利点があります。Unity がコンパイルするバリアントの総数を減らすことができ、これによってビルド時間とランタイムパフォーマンスの両方が改善されます。シェーダーが使用するキーワードの総数を減らし、これによって シェーダーキーワードの制限 に達するのを防ぐことができます。また、有効/無効にするキーワードの数が減るため、C# スクリプトからキーワードの状態を管理するのが簡単になります

この例では、1 つのキーワードのみを含む群を宣言する方法を示します。

# pragma shader_feature EXAMPLE_ON

また、#pragma multi_compile を使用する際に、このように Unity に指示することもできます。そのためには、空白のキーワードと、1 つ以上のアンダースコア (_) を持つ名前をを群に追加します。

# pragma multi_compile __ EXAMPLE_ON

複数のキーワード群の宣言

異なる機能を表現するために、複数のキーワード群を宣言することができます。これを行うには、複数の #pragma multi_compile または #pragma_shader_feature ディレクティブを使用します。

この例では、4 つのキーワードから成る 1 群と、3 つのキーワードから成る 1 群を宣言する方法を示しています。

# pragma multi_compile QUALITY_LOW QUALITY_MEDIUM QUALITY_HIGH QUALITY_ULTRA
# pragma multi_compile COLOR_RED COLOR_GREEN COLOR_BLUE

制限

キーワード群を宣言する方法にはいくつかの制限があります。

  • 同じ群に同じキーワードを複数回入れることはできませんが、同じキーワードを異なる群で宣言することは可能です。
  • シェーダープログラムでは、同じキーワードから成る群を複数回宣言することはできません。
  • シェーダーが使用できるキーワードの数には制限があります。シェーダーのソースファイルで宣言されたすべてのキーワードとその依存関係は、この制限に数えられます。詳細については、シェーダーキーワードの制限 を参照してください。

シェーダーキーワードの使用

特定のシェーダーキーワードが有効なときにのみ使用されるコードをコンパイルするには、次のように #if ディレクティブを使用します。

// キーワード群を宣言
# pragma multi_compile QUALITY_LOW QUALITY_MEDIUM QUALITY_HIGH QUALITY_ULTRA


# if QUALITY_ULTRA
// ここのコードは、キーワード QUALITY_ULTRA が有効であるときに使用されるバリアント用にコンパイルされます
# endif

Unity では、通常の #if ディレクティブは、標準の HLSL 内にあるときと同じように動作します。通常の #if ディレクティブの詳細については、HLSL のドキュメント if、elif、else、endif ディレクティブ を参照してください。

さらに、#pragma require および #pragma target ディレクティブは、パラメーターとしてキーワードを取ることができます。これにより、与えられたキーワードが有効になっているバリアントにのみ適用されます。詳細については、HLSLの適用シェーダーモデルと GPU 機能 を参照してください。

multi_compile ショートカット

Unity では、シェーダーのキーワードを宣言するために、いくつかの “ショートカット” 表記が用意されています。

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

  • 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 設定 ウィンドウ で制御できます。

これらのショートカットのほとんどは、複数のキーワードを含んでいます。プロジェクトに必要がないことがわかっている場合は、#pragma skip_variants を使って、一部のキーワードを削除することができます。例えば、以下のようになります。

# pragma multi_compile_fwdadd
# pragma skip_variants POINT POINT_COOKIE

これは、キーワード POINT または POINT_COOKIE を他のディレクティブから削除するようにコンパイラーに指示します。

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