Version: 2020.3
言語: 日本語
シェーダーバリアント
C# スクリプトによるシェーダーキーワードの使用

シェーダーキーワード

ある共通のコードを持ちながら、特定の キーワード が有効または無効の場合に異なる機能を持つシェーダーを作成することができます。

内部的には、シェーダーキーワードは シェーダーバリアント を作成することによって機能します。シェーダーキーワードを使う前にシェーダーバリアントがどのように機能するか、そしてパフォーマンスやワークフローに与える潜在的な影響を理解することが重要です。このトピックに関する情報は、シェーダーバリアント を参照してください。

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

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

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

  • COLOR_RED
  • COLOR_GREEN
  • COLOR_BLUE

内部的には、シェーダーキーワードは #define プリプロセッサーディレクティブを使用します。シェーダーキーワードのセットを宣言すると、Unity は #define ディレクティブに合うシェーダーバリアントをコンパイルします。

ノート: Shader Graph では、用語が異なります。キーワードのセットを キーワード と呼び、セット内のキーワードを ステート と呼びます。Unity はこれらを同じようにコンパイルし、C# スクリプトなどと同じように扱うことができる、など内部的には機能は同じです。

宣言するキーワードの数とその方法は、Unity がコンパイルするシェーダーバリアントの数に大きな影響を与え、その結果、プロジェクトやアプリケーションのパフォーマンスに大きな影響を与えます。詳細については、シェーダーバリアント を参照してください。

ハンドコーディングされたシェーダーでこれをキーワードを宣言する方法については、HLSL でのシェーダーキーワードの宣言と使用 を参照してください。Shader Graph シェーダーでキーワードを宣言するには、キーワード を参照してください。

ローカルまたはグローバルなスコープを持つキーワードの宣言

キーワードのセットを宣言する際には、セットのキーワードの スコープ がローカルかグローバルかを選択します。

グローバルキーワードとローカルキーワードは別のものです。グローバルキーワードはプロジェクト全体に影響し、ローカルキーワードは個々のシェーダーに固有です。

複数のシェーダーに対して同時にキーワードを有効にする予定がない限り、一般的にはローカルスコープでキーワードを宣言します。

ハンドコーディングされたシェーダーでこの値を設定するには、HLSL でのシェーダーキーワードの宣言と使用 を参照してください。Shader Graph シェーダーでこの値を設定するには、キーワード を参照してください。ローカルおよびグローバルシェーダーのキーワードの有効化と無効化につ いては、C# スクリプトによるシェーダーキーワードの使用 を参照してください。

ノート: 同じ名前のグローバルキーワードとローカルキーワードがある場合、Unity はローカルキーワードを優先します。

定義タイプ: “マルチコンパイル” と “シェーダー機能”

キーワードのセットを宣言する場合、Unity がキーワードを定義する手法を選択します。これは、Unity がコンパイルするシェーダーバリアントの数に影響します。

  • “マルチコンパイル” はキーワードのセットを宣言します。

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

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

どのオプションが最適かは、キーワードの使用方法によって異なります。キーワードを使ってプロジェクトのマテリアルを構成し、ランタイムに C# スクリプトから値を変更しない場合は、“シェーダー機能” を使ってプロジェクトのシェーダーキーワードとバリアントの数を減らします。C# スクリプトを使用してランタイムにキーワードを有効または無効にする場合は、“マルチコンパイル” を使用してバリアントが誤って除去されるのを防ぐ必要があります。シェーダーのストリッピングについての詳細は、シェーダーバリアントのストリッピング を参照してください。

ハンドコーディングされたシェーダーでこの値を設定するには、HLSL でのシェーダーキーワードの宣言と使用 を参照してください。Shader Graph シェーダーでこの値を設定するには、キーワード を参照してください。

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

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

この問題を回避するために、ハンドコーディングされたシェーダーでキーワードのセットを宣言するときに、Unity に特定のシェーダーステージでのみコンパイルするように指示することができます。

ノート: キーワードが指定されたシェーダーステージでのみ使用されるように自身で管理する必要があります。

グラフィックス API サポート

Unity は、以下のグラフィックス API に対するステージ固有のキーワードディレクティブの使用を完全にはサポートしていません。

  • OpenGL と Vulkan: コンパイル時に、Unity はすべてのステージ固有のキーワードディレクティブを通常のキーワードディレクティブに自動的に変換します。
  • Metal: 頂点ステージを対象としたキーワードは、テッセレーションステージにも影響し、その逆も然りです。

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

シェーダーキーワードを使った条件付きコンパイル

シェーダーソースファイルのセクションをマークすることで、特定のキーワードが有効なときに使用されるバリアントにのみ、その機能を入れることができます。

これを行う方法は、ハンドコードのシェーダーと Shader Graph では異なります。ハンドコードシェーダーの手順については、シェーダーキーワードの定義と使用 を参照してください。Shader Graph の説明については、Shader Graph: Keyword Node を参照してください。

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

シェーダーキーワードを有効または無効にすることができます。シェーダーキーワードを有効または無効にすると、Unity はレンダリングに適切なシェーダーバリアントを使用します。

シェーダーキーワードの有効化無効化には 2 つの方法があります。

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 のキーワードのセットをすべてのグラフィックスシェーダーに加えます。詳細については、グラフィックスティア: グラフィックスティアとシェーダーバリアント を参照してください。

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

グローバルシェーダーキーワードは 384 個までと制限されていますが、Unity はそのうち約 60 個を内部で使用しているため、実際の利用可能数は減ってしまいます。個々のシェーダーには、ローカルキーワードが 64 個までという制限があります。

シェーダーのソースファイルで宣言されたすべてのキーワードとその依存関係は、これらの制限数に含まれます。依存関係には、Pass が含まれ、UsePassfallbacks を使用するシェーダーが含まれます。

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

シェーダーバリアント
C# スクリプトによるシェーダーキーワードの使用