ライティングと相互作用するシェーダの記述は複雑です。 各種ライト,各種シャドウ オプション,各種レンダリング パス (フォワードおよび遅延レンダリング) があり,シェーダはその複雑さを処理する必要があります。
Unity の Surface Shaders は,低いレベルの vertex/pixel shader programs を使用した場合よりも,lit シェーダの記述を,コード生成によって遥かに簡単にする手法です。 Surface Shadersにはカスタム言語はありませんし,魔法や忍術というわけでもありません。手動で記述する必要なる繰り返しコードをすべて生成しているだけです。 それでも,Cg/HLSL でシェーダ コードを記述します。
サンプルが必要な場合は,Surface Shader Examples および Surface Shader Custom Lighting Examples を参照してください。
まずは入力用のUVや他の必要なデータと,出力用の構造体 SurfaceOutput
が記述されている surface function を定義します。 SurfaceOutput は基本的に, 表面のプロパティ を記述します (アルベド,色,法線など)。 Cg/HLSL で,このコードを記述します。
Surface Shaders コンパイラは,どんな入力が必要で,どんな出力を出すかということを決定し,vertex&pixel shaders を生成します。もちろん,Forward レンダリングやDeferred レンダリングを処理するレンダリングパスもここで生成します。
Surface Shadersが出力する標準的な構造体は次のようになります。
struct SurfaceOutput {
half3 Albedo;
half3 Normal;
half3 Emission;
half Specular;
half Gloss;
half Alpha;
};
Surface Shader Examples , Surface Shader Custom Lighting Examples , Surface Shader Tessellation ページを参照して下さい.
その他のシェーダ同様,Surface Shadersは CGPROGRAM..ENDCG
ブロック内に置かれます。 違いは以下のようになります。
#pragma surface ...
命令を使用して,これがSurface Shadersであることを示しています。
#pragma surface
命令は次のようになります。
#pragma surface surfaceFunction lightModel [optionalparams]
必要なパラメータ:
void surf (Input IN,inout SurfaceOutput o)
という関数を持つことを意味します。ここのInputは前もって定義した構造体になります。 Inputは,surface 関数が必要とするテクスチャ座標と追加の自動変数を含む必要があります。Lambert
(デフューズ) と BlinnPhong
(スペキュラ) です。 自前のライティング モデルを記述する方法に関しては,Custom Lighting Models ページを参照してください。オプションのパラメータ:
alpha
- アルファ ブレンディング モード。 半透明のシェーダに使用します。alphatest:VariableName
- アルファ テスト モード。 透明カットアウトシェーダに使用します。 カットオフ値は,変数名がVariableName のfloat 値になります。vertex:VertexFunction
- カスタムの頂点編集関数。 例については,Tree Barkシェーダを参照。finalcolor:ColorFunction
- カスタムの最終色モディファイア。詳しくは Surface Shader Examples を参照して下さい。exclude_path:prepass
や exclude_path:forward
- 所定のレンダリング パスにパスを生成しません。addshadow
- シャドウ キャスタおよびコレクタ パスを追加します。 通常,カスタム頂点編集で使用されるので,シャドウ キャスティングも手続き的頂点アニメーションを取得します。dualforward
- forward レンダリング パスで,dual lightmaps を使用します。fullforwardshadows
- Forward レンダリング パスで,すべてのタイプのシャドウをサポートします。decal:add
- 追加のデカール シェーダ (例: 地形 AddPass)。decal:blend
- 半透明のデカール シェーダ。softvegetation
- Soft Vegetation をオンにすると,Surface Shadersのみレンダリングするようにします。noambient
- アンビエントや球面調和関数ライトを適用しません。novertexlights
- Forward レンダリングで,球面調和関数または頂点ごとのライトを適用しません。nolightmap
- このシェーダでライトマップのサポートを無効にします(シェーダをより小さくします)。nodirlightmap
- このシェーダでディレクショナルライトマップを向こうにします(シェーダをより小さくします)。noforwardadd
- Forward レンダリング追加パスを無効にします。 これにより,シェーダは完全なディレクショナル ライトサポートし,その他すべてのライトは,頂点ごと/SH で計算されます。シェーダもより小さくなります。approxview
- 標準化されたビュー方向をピクセルごとではなく,頂点ごとに計算します。これを必要としているシェーダに行われます。 これは,より速いですが,カメラが表面に近づくと,ビュー方向は全体的に正しくありません。halfasview
- 半分方向のベクトルを,ビュー方向ではなくmライティング関数に渡します。 半距離は頂点ごとに計算および標準化されます。 これはより高速ですが,全体的に正しくりません。tessellate:TessFunction
- DX11 GPUテッセレーションを使います。詳しくは Surface Shader Tessellation をご覧ください。また,CGPROGRAM ブロック内に #pragma debug
を記述することで,Surface コンパイラは,生成されたコードの中に多くのコメントを付加できます。 シェーダのインスペクタで「Open Compiled Shader」をすることで閲覧できます。
入力の構造体 Input
には一般に,シェーダによって必要とされるテクスチャ座標があります。 テクスチャ座標の名前は,uv
の後にテクスチャ名が来る形にする必要があります (第 2 のテクスチャ座標セットを使用するには,uv2
で始めます)。
以下の値が入力構造に入力できます。
float3 viewDir
- ビュー方向を含みます。視差効果,リム ライティングなどの計算に使用されます。float4
with COLOR
セマンティック - 補間された頂点ごとの色を含みます。float4 screenPos
- 反射効果の画面空間位置を含みます。 例えば,Dark Unity では,WetStreet シェーダによって使用されます。float3 worldPos
- 世界空間の位置を含みます。float3 worldRefl
- _Surface Shadersが o.Normal に書き込まない場合_の世界反射ベクトルを含みます。 例については,反射 - デフューズ シェーダを参照。float3 worldNormal
- _Surface Shadersが o.Normal に書き込まない場合_の世界法線ベクトルを含みます。float3 worldRefl; INTERNAL_DATA
- _Surface Shadersが o.Normal に書き込む場合_の世界反射ベクトルを含みます。 ピクセルごとの法線マップに基づいて,反射ベクトルを取得するには,WorldReflectionVector (IN, o.Normal)
を使用します。 例については,反射 - バンプ型 シェーダを参照。float3 worldNormal; INTERNAL_DATA
- _Surface Shadersが o.Normal に書き込む場合_の世界反射ベクトルを含みます。 ピクセルごとの法線マップに基づいて,法線ベクトルを取得するには,WorldNormalVector (IN, o.Normal)
を使用します。現在サーフェイスシェーダの一部のコンパイルパイプラインは DirectX 11 特有のHLSL 文法を解釈できないため,もし StructuredBuffers, RWTextures およびその他の 非 DX9 文法といった HLSL 機能を使用する場合は, DX11 のみのプリプロセッサマクロでラッピングする必要があります。詳細については プラットフォーム固有の違い を参照して下さい。