シェーダーリファレンス
サーフェイスシェーダーの例

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

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

Unity の サーフェスシェーダー は、リットシェーダーを記述するために、低いレベルの 頂点シェーダーと Fragment シェーダーのプログラミング を使用するよりも、はるかに簡単なコード生成方法です。サーフェスシェーダーにカスタム言語はなく、魔法や忍術を使うわけでもありません。手動で記述しなければならない繰り返しのコードをすべて生成してくれるだけです。ユーザーは、Cg/HLSL でシェーダーコードを書く必要があります。

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

どのように機能するか

まずは入力用の UV や他の必要なデータと、出力用の構造体 SurfaceOutput が記述されている surface 関数 を定義します。SurfaceOutput は基本的に、表面のプロパティー を記述します (アルベド、色、法線など)。Cg/HLSL で、このコードを記述します。

サーフェスシェーダーコンパイラは、どんな入力が必要で、どんな出力を出すかということを決定し、頂点シェーダーとフラグメントシェーダー を生成します。もちろん、Forward レンダリングや Deferred レンダリングを処理するレンダリングパスもここで生成します。

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

struct SurfaceOutput
{
    fixed3 Albedo;  // diffuse color
    fixed3 Normal;  // tangent space normal, if written
    fixed3 Emission;
    half Specular;  // specular power in 0..1 range
    fixed Gloss;    // specular intensity
    fixed Alpha;    // alpha for transparencies
};

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

struct SurfaceOutputStandard
{
    fixed3 Albedo;      // base (diffuse or specular) color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Metallic;      // 0=non-metal, 1=metal
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};
struct SurfaceOutputStandardSpecular
{
    fixed3 Albedo;      // diffuse color
    fixed3 Specular;    // specular color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};

サンプル

サーフェイスシェーダーの例 サーフェースシェーダーのカスタムライティングのサンプル 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 は、surface 関数が必要とするテクスチャ座標と追加の自動変数を含む必要があります。
  • lightModel - 使用するライティングモデル。組み込みライティングモデルは、Lambert (デフューズ) と BlinnPhong (スペキュラ) です。自前のライティングモデルを記述する方法に関しては、サーフェイスシェーダーでのカスタムライティングモデル ページを参照してください。
    • Standard lighting model uses SurfaceOutputStandard output struct, and matches the Standard (metallic workflow) shader in Unity.
    • StandardSpecular lighting model uses SurfaceOutputStandardSpecular output struct, and matches the Standard (specular setup) shader in Unity.
    • Lambert and BlinnPhong lighting models are not physically based (coming from Unity 4.x), but the shaders using them can be faster to render on low-end hardware.

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

透明度とアルファテスト は、ディレクティブ alphaalphatest によって制御されます。 透明度には通常、二種類あります。ひとつは従来型のアルファ ブレンディング(オブジェクトのフェードアウトに使われる)。 もうひとつは、より物理的に説得力のある「プレマルチプライド ブレンディング」(半透明のサーフェースが適切な鏡面反射を保てるようにする)です。 半透明性を有効にすると、生成されたサーフェスシェーダーコードに 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 - GBuffer コンテンツを変更するカスタム deferred パス。
  • finalprepass:ColorFunction - カスタム Prepass Base パス。

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

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

コード生成オプション - デフォルトでは、生成されたサーフェスシェーダーコードは、すべての使用可能なライティング、シャドウイング、ライトマップのシナリオを可能な限り扱おうとします。 ただし、明らかに不要と分かっているものが含まれることもあります。その場合は生成されたコードを調整し、不要なものを省くことができます。 こうすることによりシェーダーのサイズが小さくなり、読み込みが早くなります。

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

その他のオプション

  • softvegetation - Soft Vegetation をオンにすると、サーフェスシェーダーのみがレンダリングされます。
  • interpolateview - ビュー方向をピクセルシェーダーで計算する代わりに、頂点シェーダーで計算して補間します。これにより、ピクセルシェーダーがより早くなりますが、テクスチャ Interpolator を 1つ使用してしまいます。
  • halfasview - 半分方向のベクトルを、ビュー方向ではなく m ライティング関数に渡します。半距離は頂点ごとに計算、標準化されます。これはより高速ですが、全体的に正しくりません。
  • approxview - Unity 5.0 で廃止されました。interpolateview を代わりに使用してください。
  • dualforward - Forward レンダリングパスで、グローバルイルミネーション を使用します。

上記のさまざまなオプションが実際、それぞれどのように違うのかを見るには、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 のみのプリプロセッサーマクロでラッピングする必要があります。

詳しくは、プラットフォーム別のレンダリングの違いUnityで使用するシェーダー言語を参照してください。

必要なパラメーター

シェーダーリファレンス
サーフェイスシェーダーの例