Version: 2023.1
言語: 日本語
シェーダーの例
サーフェスシェーダーとレンダリングパス

サーフェスシェーダーの記述

ビルトインレンダーパイプラインでは、サーフェスシェーダーは、ライティングと連動するシェーダを効率的に記述する方法です。

レンダーパイプラインの互換性

機能名 ビルトインレンダーパイプライン ユニバーサルレンダーパイプライン (URP) HD レンダーパイプライン (HDRP) カスタム SRP
サーフェスシェーダー 不可

URP で Shader オブジェクトを効率的に作成する方法については、Shader Graph を参照してください。
不可

HDRP で Shader オブジェクトを効率的に作成する方法については、Shader Graph を参照してください。
なし

概要

ライティングと相互作用するシェーダーの記述は複雑です。各種ライト、各種の影のオプション、各種レンダリングパス (フォワードやデファードレンダリング) があり、シェーダーはその複雑さを処理する必要があります。

サーフェスシェーダーは、低レベルの 頂点/ピクセルシェーダープログラム を使用するよりもはるかに簡単に lit シェーダーを作成できるコードの生成方法です。

サンプルが必要な場合は、サーフェスシェーダーの例サーフェスシェーダーライティングの例 を参照してください。

どのように機能するか

入力として必要な UV やデータを取得し、出力構造体の SurfaceOutput に注入する「サーフェス関数」を定義します。SurfaceOutput は、基本的に サーフェスのプロパティ (アルべド、法線、エミッション、スペキュラーなど) を表します。 このコードは HLSL で作成します。

サーフェスシェーダーコンパイラーは、どんな入力が必要で、なにを出力するかなどを決定し、実際に 頂点シェーダーとピクセルシェーダー を生成します。もちろん、フォワードレンダリングやデファードレンダリングを処理するレンダリングパスもここで生成します。

サーフェスシェーダーが出力する標準的な構造体は次のようになります。

struct SurfaceOutput
{
    fixed3 Albedo;  // ディフューズ色
    fixed3 Normal;  // 書き込まれる場合は、接線空間法線
    fixed3 Emission;
    half Specular;  //  0..1 の範囲のスペキュラーパワー
    fixed Gloss;    // スペキュラー強度
    fixed Alpha;    // 透明度のアルファ
};

Unity 5 では、サーフェスシェーダーは物理ベースのライティングモデルも使えます。組み込まれた Standard や StandardSpecular のライティングモデル(以下参照)では、それぞれ、これらの出力構造を使えます。

struct SurfaceOutputStandard
{
    fixed3 Albedo;      // ベース (ディフューズかスペキュラー) カラー
    fixed3 Normal;      // 書き込まれる場合は、接線空間法線
    half3 Emission;
    half Metallic;      // 0=非メタル, 1=メタル
    half Smoothness;    // 0=粗い, 1=滑らか
    half Occlusion;     // オクルージョン (デフォルト 1)
    fixed Alpha;        // 透明度のアルファ
};
struct SurfaceOutputStandardSpecular
{
    fixed3 Albedo;      // ディフューズ色
    fixed3 Specular;    // スペキュラー色
    fixed3 Normal;      // 書き込まれる場合は、接線空間法線
    half3 Emission;
    half Smoothness;    // 0=粗い, 1=滑らか
    half Occlusion;     // オクルージョン (デフォルト 1)
    fixed Alpha;        // 透明度のアルファ
};

サンプル

サーフェスシェーダーの例 サーフェスシェーダーのカスタムライティングのサンプル DX11 / OpenGL コアテッセレーションのサーフェスシェーダー のページを参照してください .

サーフェスシェーダーコンパイルディレクティブ

その他のシェーダー同様、サーフェスシェーダーは CGPROGRAM..ENDCG ブロック内に置かれます。違いは以下のようになります。

  • Pass ではなく、SubShader ブロック内に配置される必要があります。サーフェスシェーダーは複数のパスでコンパイルされます。
  • #pragma surface ... ディレクティブを使用して、これがサーフェスシェーダーであることを示しています。

#pragma surface ディレクティブは次のようになります。

# pragma surface surfaceFunction lightModel [optionalparams]

必要なパラメーター

  • surfaceFunction - Cg 関数にはサーフェスシェーダーコードがあります。その関数にはvoid surf (Input IN, inout SurfaceOutput o) の形式があり、Input は自分で定義した構造体です。Input には、サーフェス関数に必要な任意のテクスチャ座標と追加の自動変数が含まれます。
  • lightModel - 使用するライティングモード。ビルトインのものは、物理ベースの StandardStandardSpecular です。簡易な、物理ベースでない Lambert (拡散) と BlinnPhong (スペキュラー) も同様です。独自のものを作成する方法については、カスタムライティングモデル のページを参照してください。
    • ライティングモデル Standard は出力構造体 SurfaceOutputStandard を使用し、 Unity の Standard (Metallic ワークフロー)シェーダーにマッチします。
    • ライティングモデル StandardSpecular は出力構造体 SurfaceOutputStandardSpecular を使用し、Unity の スタンダード(Specular 設定) シェーダーにマッチします。
    • ライティングモデル LambertBlinnPhong は物理ベースではありません(Unity 4.x に由来しています)が、これらを使用したシェーダーは、低性能ハードウェアでより高速にレンダリングできることがあります。

オプションのパラメーター

透明度とアルファテストalphaalphatest ディレクティブによって制御されます。透明度には通常 2 種類で、従来のアルファブレンディング (オブジェクトをフェードアウトするために使用) または、物理的にもっともらしい「事前乗算ブレンド」 (半透明のサーフェスで適切なスペキュラー反射の保持が可能) です。半透明を有効にすると、生成されたサーフェスシェーダーコードに blending コマンドを含有できます。アルファカットアウトを有効にすると、指定された変数に基づいて、生成されたピクセルシェーダーのフラグメントの破棄を行います。

  • alphaalpha:auto - 単純なライティング機能のために透明度のフェードイン/アウトを選択し (alpha:fade と同様)、物理基盤のライティング関数のために前もって乗算された透明度を選択します (alpha:premul と同様)。
  • alpha:blend - アルファブレンディングを可能にします。
  • alpha:fade - 従来の透過性のフェードイン/アウトを可能にします。
  • alpha:premul - プレマルチプライドアルファ透明度を可能にします。
  • alphatest:VariableName - アルファカットアウト透明度を有効にします。カットオフ値は VariableName をともなう float 変数で示されます。たいてい、addshadow ディレクティブを使用して、適切なシャドウキャスターパスの生成も必用になります。
  • keepalpha - デフォルトでは、出力構造体の Alpha が何であろうと、ライティング関数で何か戻り値であろうと、不透明サーフェスシェーダーは、1.0 (白) をアルファチャネルに書き込みます。このオプションを選択することにより、ライティング関数のアルファ値を不透明サーフェスシェーダーのために、一定に保つことができます。
  • decal:add - 追加的なデカールシェーダー (terrain AddPass など)。他のサーフェスの一番上にあるオブジェクトに有用で、追加的ブレンディングに使用します。サーフェスシェーダーの例 を参照してください。
  • decal:blend - 半透明デカールシェーダー。これは、他のサーフェスの一番上にあるオブジェクトに有用で、アルファブレンディングに使用します。サーフェスシェーダーの例 を参照してください。

カスタムモディファイア関数 は、入ってくる頂点データを変更、または、計算するために使用されます。または、計算された最終的なフラグメント色を変更するために使用されます。

  • vertex:VertexFunction - カスタム頂点修正関数。この関数は、頂点シェーダーの作成の開始時に呼び出され、頂点データごとに修正や計算を行うことができます。サーフェスシェーダーの例 を参照してください。
  • finalcolor:ColorFunction - カスタムの最終色モディファイア。詳しくは サーフェスシェーダーの例 を参照してください。
  • finalgbuffer:ColorFunction - G バッファのコンテンツを変更するカスタムディファードパス。

シャドウとテッセレーション - シャドウとテッセレーションの取り扱いを制御する追加ディレクティブ。

  • addshadow - シャドウキャスタやコレクタパスを追加します。通常、カスタム頂点編集で使用されるので、シャドウキャスティングも手続き的頂点アニメーションを取得します。多くの場合、シェーダーはフォールバックからシャドウキャスターパスを使用することができるため、特別なシャドウの処理を行う必要はありません。
  • fullforwardshadows - フォワード レンダリングパスで、すべてのライトシャドウをサポートします。デフォルトでは、フォワードレンダリングで、シェーダーは一方向からのシャドウしかサポートしません (内部シェーダー変数の数を節約するため)。フォワードレンダリングでポイントかスポットライトが必要な場合は、このディレクティブを使用します。
  • tessellate:TessFunction - DX11 GPU テッセレーションを使います。詳しくは DX11 / OpenGL コアテッセレーションのサーフェスシェーダーを参照してください。

コード生成オプション - デフォルトでは、生成されたサーフェスシェーダーコードは、すべての可能なライト/影/ライトマップのシナリオを処理しようとします。ただし、ある場合は、それらの一部は不要な場合もあります。生成されたコードを調整してそれらを飛ばすことが可能です。この結果、より早く起動できる小さなシェーダーになります。

  • exclude_path:deferredexclude_path:forward - 指定されたレンダリングパスのパスを生成しません (それぞれ、Deferred Shading レンダリングパスForward Rendering パスの詳細 を参照してください)。
  • noshadow - このシェーダーでシャドウのサポートを無効にします。
  • noambient - アンビエントライトやライトプローブを適用しません。
  • novertexlights - Forward レンダリングで、ライトプローブや頂点ごとのライトを適用しません。
  • nolightmap - このシェーダーでライトマップのサポートを無効にします。
  • nodynlightmap - このシェーダーでランタイムのダイナミックなグローバルイルミネーションのサポートを無効にします。
  • nodirlightmap - このシェーダーでディレクショナルライトマップを無効にします。
  • nofog - このシェーダーで、すべてのビルトインフォグのサポートを無効にします。
  • nometa - 「メタ」パスを生成しないようにします。 (サーフェス情報を取り出すために、ライトマッピングと動的グローバルイルミネーションに使用します)。
  • noforwardadd - Forward レンダリング追加パスを無効にします。これにより、シェーダーは完全なディレクショナルライトサポートし、その他すべてのライトは、頂点ごと/SH で計算されます。シェーダーもより小さくなります。
  • nolppv - シェーダーのライトプローブプロキシボリュームを無効にします。
  • noshadowmask - シェーダーのシャドウマスクサポートを無効にします (シャドウマスク距離シャドウマスク の両方)。

その他のオプション

  • softvegetation - Soft Vegetation をオンにすると、サーフェスシェーダーのみがレンダリングされます。
  • interpolateview - ビュー方向をピクセルシェーダーで計算する代わりに、頂点シェーダーで計算して補間します。これにより、ピクセルシェーダーがより早くなりますが、テクスチャ Interpolator を 1つ使用してしまいます。
  • halfasview - 半分方向のベクトルを、ビュー方向ではなく m ライティング関数に渡します。半距離は頂点ごとに計算、標準化されます。これはより高速ですが、全体的に正しくりません。
  • approxview - Unity 5.0 で廃止されました。interpolateview を代わりに使用してください。
  • dualforward - フォワード レンダリングパスで、2 重ライトマップ を使用します。
  • dithercrossfade - サーフェスシェーダーがディザリングエフェクトをサポートするようにします。そうすると、クロスフェーディング遷移モードに設定された LOD Group コンポーネントを使うゲームオブジェクトにこのシェーダーを適用できます。

上記のさまざまなオプションが実際、それぞれどのように違うのかを見るには、Shader Inspectorの “Show Generated Code” ボタンを使用すると便利です。

サーフェスシェーダーの input 構造体

入力の構造体 Input には一般に、シェーダーによって必要とされるテクスチャ座標があります。テクスチャ座標の名前は、uv の後にテクスチャ名が来る形にする必要があります (第 2 のテクスチャ座標セットを使用するには、uv2 で始めます)。

以下の値が入力構造に入力できます。

  • float3 viewDir - ビュー方向を含みます。視差効果、リムライティングなどの計算に使用されます。
  • float4 with COLOR セマンティック - 補間された頂点ごとの色を含みます。
  • float4 screenPos - 反射、または、スクリーンスペースエフェクトのためのスクリーンスペース位置を含みます。これは、GrabPass には適していないので注意してください。GrabPass のためにはComputeGrabScreenPos 関数でカスタム UV を算出する必要があります。
  • float3 worldPos - ワールド空間の位置を含みます。
  • float3 worldRefl - サーフェスシェーダーが o.Normal に書き込まない場合 のワールドの反射ベクトルを含みます。例については、反射―デフューズシェーダーを参照してください。
  • float3 worldNormal - サーフェスシェーダーが o.Normal に書き込まない場合 のワールドの法線ベクトルを含みます。
  • float3 worldRefl; INTERNAL_DATA - サーフェスシェーダーが o.Normal に書き込む場合 のワールドの反射ベクトルを含みます。ピクセル法線マップに基づいて反射ベクトルを取得するには、WorldReflectionVector (IN, o.Normal) を使用します。例については、反射-Bumped シェーダーを参照してください。
  • float3 worldNormal; INTERNAL_DATA - サーフェスシェーダーが o.Normal に書き込む場合 のワールドの反射ベクトルを含みます。ピクセル法線マップに基づいて法線ベクトルを取得するには、WorldNormalVector (IN, o.Normal) を使用します。

サーフェスシェーダーと DirectX 11 HLSL 構文

現在サーフェスシェーダーの一部のコンパイルパイプラインは DirectX 11 特有の HLSL 文法を解釈できないため、もし StructuredBuffers、RWTextures およびその他の非 DX9 文法といった HLSL 機能を使用する場合は、DX11 のみのプリプロセッサーマクロでラッピングする必要があります。

詳しくは、様々なグラフィックス API のシェーダーの作成HLSL の使用 を参照してください。

シェーダーの例
サーフェスシェーダーとレンダリングパス