Version: 2023.1
言語: 日本語
シェーダーバリアントの数の確認
C# スクリプトでのシェーダーキーワードの使用

シェーダーキーワード

シェーダーキーワードを使用すると、シェーダーコードで 条件付き動作 を使用できます。一部の共通のコードを共有する複数のシェーダーを作成し、特定の キーワード が有効または無効にされた時の機能をそれぞれ異なるものにすることができます。

シェーダーキーワードは 動的分岐シェーダーバリアント と一緒に使うことができます。シェーダーキーワードの使用を開始する前に、これらの技法がどのように機能するのか、またどれがプロジェクトに適しているのかを理解することが重要です。

このページには以下の情報が含まれています。

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

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

シェーダーのキーワードはセットで宣言します。セットには、互いに排他的なキーワードが含まれます。

例えば、以下のセットには 3 つのキーワードが含まれています。

  • COLOR_RED
  • COLOR_GREEN
  • COLOR_BLUE

ノート: Shader Graph では用語が異なり、キーワードのセットは キーワード と呼ばれ、セット内のキーワードは ステート と呼ばれます。内部的には機能は同じで、例えば、Unity はこれらを同じ方法でコンパイルし、これらの扱いは C# スクリプトの場合と同様です。

シェーダーキーワードの宣言方法は、様々なことに影響します。

  • タイプ は、Unity が、シェーダーバリアントの生成にキーワードを使用するかどうか (またどのように使用するか)、または動的分岐のためにキーワードを使用するかどうかに影響します。
  • スコープ は、キーワードがローカルとグローバルのどちらであるかに影響します。これによってランタイムの動作が決まります。
  • ステージ は、キーワードがどのシェーダーステージに影響を与えるかに影響します (該当する場合)。

定義タイプ: “multi compile”、“shader feature”、“dynamic branch”

キーワードのセットを宣言する際に、それらを シェーダーバリアント で使用するか、動的分岐 で使用するかを選択します。シェーダーバリアントを選択した場合は、Unity が内部的にキーワードをどのように定義するかも選択する必要があります (これは、Unity がコンパイルするバリアントの数に影響します)。

  • “dynamic branch”: 動的分岐で使用するキーワードのセットの作成に使用します。内部的には、Unity はこれらのキーワードを使って均一変数を作成します。
  • “multi compile” または “shader feature”: これを使用して、シェーダーバリアントで使用するキーワードのセットを作成します。内部的には、Unity はこれらのキーワードを使用して #define プリプロセッサーディレクティブを作成します。
    • “multi compile” は、シェーダーバリアントで使用するキーワードのセットを宣言します。

      Unity はセット内の全てのキーワードのシェーダーバリアントをコンパイルします。
    • “shader feature” は、シェーダーバリアントで使用するキーワードのセットを宣言し、また、これらのキーワードのいずれも有効になっていないバリアントをコンパイルするようにコンパイラーに指示します。

      Unity は、プロジェクトの状態をビルド時に調査し、使用されているキーワードのバリアントのみをコンパイルします。ビルドに含まれるマテリアルで有効になっているキーワードは、使用されています。

“multi compile” と “shader feature” のどちらを選択するかは、キーワードをどのように使用するかによって変わります。そのキーワードを使ってプロジェクトのマテリアルの設定を行い、ランタイムに C# スクリプトから値を変更しない場合は、“shader feature” を使用してプロジェクトのシェーダーキーワードとバリアントの数を減らしてください。ランタイムに C# スクリプトを使用してキーワードを有効化/無効化する場合は、“multi compile” を使用して、バリアントが誤ってストリッピングされるのを防いでください。シェーダーのストリッピングについての詳細は、シェーダーバリアントのストリッピング を参照してください。

ノート: Graphics 設定ウィンドウの Always Included Shaders のリストにシェーダーを追加すると、Unity は、ビルド内の全てのセットの全てのキーワードを (たとえそれが “shader feature” を使って宣言されていたとしても) 含めます。

この値を設定するには、以下のドキュメントを参照してください。

  • ハンドコーディングされたシェーダーでは、HLSL のシェーダーキーワードの宣言と使用 を参照してください。
  • Shader Graph では、Keyword (キーワード) を参照してください。ノート: Shader Graph では “dynamic branch” オプションは使用できません。Shader Graph ではシェーダーバリアントでしかシェーダーキーワードを使用できません。

ローカルスコープとグローバルスコープ

キーワードのセットを宣言する際に、セット内のキーワードがローカルとグローバルのどちらの スコープ を持つか選択します。これにより、ランタイムにグローバルシェーダーキーワードを使用してこのキーワードの状態をオーバーライドできるかどうかが決まります。

デフォルトでは、グローバルスコープでキーワードを宣言します。これは、ランタイムにグローバルシェーダーキーワードを使用してそのキーワードの状態をオーバーライドできることを意味します。ローカルスコープでキーワードを宣言すると、ランタイムにグローバルシェーダーキーワードを使用してキーワードの状態をオーバーライドできません。詳細およびコード例は、C# スクリプトでのシェーダーキーワードの使用 を参照してください。

ノート: 同じ名前のキーワードがシェーダーソースファイル内とその依存関係内に存在する場合、ソースファイル内のキーワードのスコープが、依存関係内のスコープを上書きします。依存関係は、Fallback コマンド を介して含まれている全てのシェーダーと、UsePass コマンド を介して含まれているパスで構成されます。

この値を設定するには、以下のドキュメントを参照してください。

ステージ固有のキーワード

デフォルトでは、Unity はシェーダーの各ステージに対してキーワードバリアントを生成します。例えば、シェーダーに頂点ステージとフラグメントステージが含まれている場合、頂点シェーダープログラムとフラグメントシェーダープログラムの両方に、キーワードの全ての組み合わせのバリアントが生成されます。また、あるキーワードセットがどちらか一方のステージでしか使われていない場合、もう一方のステージにも同じバリアントが生成されます。Unity は同じバリアントを自動的に識別して 複製しない ため、ビルドサイズは増加しませんが、それでもコンパイル時間が浪費され、シェーダーのロード時間が増加し、ランタイムのメモリ使用量が増加する結果となります。

この問題を回避するために、ハンドコーディングされたシェーダー内でキーワードのセットを宣言する際に、特定のシェーダーステージに関してのみコンパイルするように Unity に指示することができます。これを行った場合は、そのキーワードが指定のシェーダーステージでのみ使用されることを確認する必要があります。

ノート: 以下のグラフィックス API は、ステージ固有のキーワードを完全にはサポートしていません。OpenGL と Vulkan では、コンパイル時に、Unity が全てのステージ固有キーワードディレクティブを通常のキーワードディレクティブに自動的に変換します。Metal では、頂点ステージをターゲットとする全てのキーワードはテッセレーションステージにも影響し、逆もまた同様です。

この値を設定するには:

  • ハンドコーディングされたシェーダーでは、HLSL のシェーダーキーワードの宣言と使用 を参照してください。
  • Shader Graph では、この値を設定することはできません。デフォルトで、全てのキーワードが全てのステージに影響します。

シェーダーキーワードで動作を条件付きにする

シェーダーキーワードを使用してシェーダーの一部を条件付きにすることで、特定の動作を、特定のキーワードが特定の状態にある時にだけ実行されるようにすることができます。

これは以下の手順で行えます。

シェーダーキーワードの有効化と無効化

シェーダーキーワードは有効にも無効にもできます。シェーダーキーワードを有効または無効にすると、シェーダーは適切な条件付き動作を表示します。キーワードがシェーダーバリアントと動的分岐のどちらで動作するかによって、Unity が適切なシェーダーバリアントをレンダリングするか、GPU が適切なブランチを実行するかの、いずれかになります。

以下の 2 つの方法で、シェーダーキーワードを有効化/無効化できます。

Unity の定義済みシェーダーキーワード

Unity は、定義済みシェーダーキーワードのセットを使用して、共通の機能を実現するシェーダーバリアントを生成します。

Unity は、コンパイル時に以下のシェーダーバリアントキーワードのセットを追加します。

  • デフォルトでは、Unity は全てのグラフィックスシェーダープログラムに、STEREO_INSTANCING_ON, STEREO_MULTIVIEW_ON、STEREO_CUBEMAP_RENDER_ON、UNITY_SINGLE_PASS_STEREO のキーワードセットを加えます。これらのキーワードはエディタースクリプトを使ってストリッピングできます。詳しくは シェーダーバリアントのストリッピング を参照してください。
  • デフォルトでは、Unity はスタンダードシェーダーに LIGHTMAP_ON、DIRLIGHTMAP_COMBINED、 DYNAMICLIGHTMAP_ON、LIGHTMAP_SHADOW_MIXING、SHADOWS_SHADOWMASK のキーワードセットを加えます。これらのキーワードは、Graphics 設定 ウィンドウを使ってストリッピングできます。
  • ビルトインレンダーパイプラインで、互いに異なる ティア設定 をプロジェクトに使用している場合、Unity は、UNITY_HARDWARE_TIER1、UNITY_HARDWARE_TIER2、UNITY_HARDWARE_TIER3 のキーワードセットを全てのグラフィックスシェーダーに加えます。詳細は グラフィックスティア: グラフィックスティアとシェーダーバリアント を参照してください。

シェーダーキーワードの制限

Unity は最大 4,294,967,294 個のグローバルシェーダーキーワードを使用できます。個々のシェーダーとコンピュートシェーダーは最大 65,534 個のローカルシェーダーキーワードを使用できます。これらの合計数には、バリアントに使用されるキーワードと動的分岐に使用されるキーワードが含まれます。

この合計数には、シェーダーのソースファイル内で宣言された全てのキーワードとその依存関係が含まれます。依存関係には、シェーダーが UsePass で含める パス や、フォールバック が含まれます。

Unity が同じ名前のシェーダーキーワードに複数回遭遇する場合は、1 回だけカウントされます。

シェーダーが合計で 128 個より多い数のキーワードを使用する場合、小さなランタイムパフォーマンスペナルティが発生します。したがって、キーワードの数は少なくすることが推奨されます。Unity は常に 1 つのシェーダーにつき 4 つのキーワードを確保します。

シェーダーバリアントの数の確認
C# スクリプトでのシェーダーキーワードの使用