サーフェスシェーダの作成

ライティングとの対話シェーダを書くことは複雑です。そこに異なるライトの種類、異なるの影のオプション、異なるレンダリングパス(フォワードおよび遅延レンダリング)は、シェーダはすべてその複雑さを処理する必要があります。
unityのサーフェスシェーダでは、低レベルの頂点/ピクセルシェーダプログラムを使用するよりも点灯シェーダを作成することがはるかに容易にコードを生成するアプローチとなります
。サーフェスシェーダに独自の言語は使用しません。すべてのコード生成は手で書かなければいけません。CG / HLSLでシェーダコードを記述します。


いくつかの例については、サーフェスシェーダの例サーフェスシェーダのカスタムライティングの例を見てください。


どのように動作するのか


入力として必要なすべてのUVまたはデータを受け取り、 "サーフェス機能"を定義し、SurfaceOutput出力に必要な値を満たします。SurfaceOutputは、基本的にはサーフェスのプロパティ(アルベドカラー、法線、放射、スペキュラなどです)。Cg / HLSLでこのコードを記述します。
サーフェスシェーダコンパイラは、必要な値が入力されているか、出力の値は全て満たされているかを判別しその後に、
頂点とピクセルシェーダを生成します、同様にレンダリングパスがフォワードレンダリングとディファードレンダリングに値を渡します。



表面シェーダの標準出力の構造



struct SurfaceOutput {
half3 Albedo;
half3 Normal;
half3 Emission;
half Specular;
half Gloss;
half Alpha;
};


サーフェスシェーダの例


http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderExamples.html


カスタムライティングの例


http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderLightingExamples.html


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


サーフェスシェーダは他のシェーダと同じようにCGPROGRAM..ENDCG、の内部に配置されます。
相違点は次のとおりです。



  • SubShaderの内側に配置する必要がありますPassのブロックではありません。サーフェスシェーダは 複数のPassを含むようにコンパイルされます。

  • #pragma surface を用いて...ディレクティブはサーフェスシェーダを示しています。


#pragma surfaceディレクティブは、次のとおりです。


    #pragma surface surfaceFunction lightModel [optionalparams]

必要なパラメータ:



  • surfaceFunction -Cg関数はサーフェスシェーダコードで定義されます。

  • 関数は、void surf (Input IN, inout SurfaceOutput o) といったフォームが必要で入力はユーザが定義する構造体です。surfaceFunctionには任意のテクスチャ座標とサーフェス機能で必要とされる自動変数を含める必要があります。

  • lightModel -使用する照明モデル。内蔵のものはLambert(拡散)とBlinnPhong(鏡面)。

  • カスタムライティングモデル    を 参照してください。


             http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderLighting.html


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




  • alpha -アルファブレンドモード。半透明シェーダに使用します。

  • alphatest:VariableName -アルファテストモード。透明カットアウトシェーダに使用します。カットオフ値のVariableNameは、float変数になっています。

  • VertexVertexFunction -カスタム頂点変更機能。例:樹皮シェーダを参照してください。

  • finalcolor:ColorFunction -カスタム最終的な色の変更機能。サーフェスシェーダの例を参照してください。 http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderExamples.html

  • exclude_path:prepassまたはexclude_path:forward -指定された描画パスを生成しません。

  • addshadow -シャドウキャスターとコレクターのパスを追加します。一般的にカスタム頂点の変更で使用するので、その影のキャスティングは、任意の手続きの頂点アニメーションを取得します。

  • dualforward -dual lightmaps をフォワードレンダリングパスで使用します。

  • fullforwardshadows -フォワードレンダリングパスですべてのシャドウタイプのサポートをします。

  • decal:add- 加算デカールシェーダ(例えばterrain AddPass)。

  • decal:blend -半透明デカールシェーダ。

  • softvegetationは -ソフトベジテーションがオンになっている場合、サーフェスシェーダのみがレンダリングされるようにします。

  • noambientは、 -環境光や ​​球面調和ライトを適用しない。

  • novertexlightsは -フォワードレンダリングで任意の球面調和関数または頂点単位のライトを適用しない。

  • nolightmap -このシェーダでのライトマップのサポートを無効にします(シェーダは小さくなります)。

  • nodirlightmapは -このシェーダでのディレクションライトマップのサポートを無効にします(シェーダが小さくなります)

  • noforwardaddは -フォワードレンダリング添加パスを無効にします。

  • ひとつのディレクショナルライトを作成し他のすべてのライトを頂点単位でper-vertex/SH(頂点単位のSpherical Harmonics =球面調和関数を用いた環境光マッピング)に割り付けますたいへんシェーダが小さくなります)

  • approxviewは -正規化されたビューの方向をピクセル単位でなく頂点単位で計算します。これは高速ですが、カメラがサーフェス表面に近づくとビューの方向が完全には正しくなりません。

  • halfasviewは -ライティング機能の代わりに、ビュー方向にハーフベクトルを渡します。頂点ごとにハーフ方向が計算され正規化されます。これは速いですが完全に正しくはなりません。


追記:#pragma debugをCGPROGRAM 内部に書くことで、コンパイラは生成された多くのコメントコードを切り離します。シェーダインスペクタでコンパイルされた後シェーダを見ることができます。



サーフェスシェーダの入力構造



入力構造の入力部は一般的にシェーダが必要とするテクスチャ座標を持っています。テクスチャ座標は 名前を付ける必要があり、”UV”テクスチャ名(またはUV2を指定で2番目のテクスチャ座標セットを使用する)。



入力構造体に入れることができる追加の値:



  • float3 VIEWDIRは -リムライティング等、視差効果を計算するためのビューの方向が含まれています

  • float4 COLOR-頂点単位の色の補間が含まれています。

  • float4 screenPosは -反射効果のためのスクリーンスペース座標が含まれています。例えばWetStreetシェーダなど

  • float3 worldPosは -ワールド空間の位置座標が含まれています。

  • float3 worldReflは -ワールド空間の反射ベクトルが含まれます。これはサーフェスシェーダがo.Normalに書き込みをしていない場合です。例:リフレクト拡散シェーダを参照してください。

  • float3 worldNormalは -ワールド空間の法線ベクトルが含まれます。ただしサーフェスシェーダがo.Normalに書き込みをしていない場合

  • float3 worldRefl。INTERNAL_DATAは -ワールド空間の反射ベクトルが含まれます。これはサーフェスシェーダがo.Normalに書き込む場合です。ピクセル単位の法線マップに基づいて反射ベクトルを取得するには、(IN、o.Normal)WorldReflectionVector。例:リフレクト・バンプシェーダを参照してください。

  • float3 worldNormal。INTERNAL_DATAは -ワールド空間の法線ベクトルが含まれます。これはサーフェスシェーダがo.Normalに書き込む場合です。 ピクセル単位の法線マップに基づいて、法線ベクトルを取得するには、WorldNormalVectorを(IN、o.Normal)


サーフェスシェーダの例




サーフェスシェーダのカスタムライティングモデル


サーフェスシェーダ書き込み時に、サーフェスの性質を記述している(アルベド、色、法線、...)とライティングの相互作用はライティングモデルにより計算されます。ビルトインのライティングモデルはランバート(拡散照明)とBlinnPhong(スペキュラライティング)。


カスタムライティングモデルを使用するときにはサーフェスシェーダで行うことが可能ですライティングモデルは、いくつかのCG / HLSL関数の組み合わせ以上の何物でもありません。ビルトインランバートBlinnPhongのモデルは、Lighting.cgincで定義されています。


windowsの場合 (Unityインストールパス /Data/ CGIncludes / Lighting.cginc


Macの場合 /Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc


ライティングモデルの宣言


ライティングモデルは通常Lightingで始まる名前を持ついくつかの機能です。シェーダファイルまたはインクルードファイルのいずれかでどこでも宣言することができます。関数は次のとおりです。



  1. half4 Lighting名前(SurfaceOutput S、half3 lightDir、 harf atten) これは、

  2. ライトモデルのフォワードレンダリングパス使用時ビュー方向に依存しません。(例えば、拡散)。

  3. half4 Lighting名前(SurfaceOutput S、half3 lightDir、half3 ViewDir、harf atten) ライトモデルのフォワードレンダリングパス使用時ビュー方向に依存します。

  4. half4 Lighting名前 _PrePass(SurfaceOutput s、half4 light) これはディファードライティングパスで使用されます。


すべての関数を宣言する必要がないことに注意してください。照明モデルはビューの方向を使用してもしなくてもいいです。ライティングモデルは、ディファードライティングではライティングモデルが動作しない場合は_PrePass機能を宣言していないと思います  それを使用するすべてのシェーダはフォワードレンダリングのみを転送するようにコンパイルされています。


デコードの方向ライトマップは、フォワードおよびディファードのライティング機能と同様の方法でいくつかの状況でカスタマイズする必要があります。あなたのライティングモデルがビュー方向に依存しているかどうかに応じて以下の関数のいずれかを使用します。両関数は自動的にフォワードおよびディファードのレンダリングパスを処理します。



  1. half4 Lighting名前 _DirLightmap(SurfaceOutput S、fixed4 color、fixed4 scale、bool surfFuncWritesNormal) これはビュー方向に依存して表示(例えば、拡散)されないライティングモデルに使用されます。

  2. half4 Lighting名前 _DirLightmap(SurfaceOutput S、fixed4 color、fixed4 scale、half3 ViewDir、bool surfFuncWritesNormal、out half3 specColor) これは、ビューの方向依存しているライティングモデルに使用されます。



http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderLightingExamples.html




バーテックスシェーダおよびフラグメントシェーダを作成


ShaderLabのシェーダは別のグラフィックスハードウェアのための複数のシェーダの実装が含まれている固定機能ハードウェアの状態などを設定し、マテリアルのインスペクタに表示されるプロパティを記述します。実際のプログラマブルシェーダ-頂点プログラムとフラグメントプログラムなどが-全体のShaderLabの"シェーダ"というコンセプトのほんの一部です。
シェーダチュートリアル基本的な導入のために。ここでは、低レベルのハードウェアシェーダと呼ぶシェーダプログラムを見てください。


あなたがライティングとの対話シェーダを作成したい場合は、サーフェスシェーダのマニュアルを見てください。。このページの残りの部分(例えば、特殊効果、Unityのライトと相互作用しないシェーダを想定しています画像効果など)

シェーダプログラムは、どこかの内部に、シェーダテキストの"スニペット"を埋め込 ​​むことにより、CG / HLSL言語で書かれたパスのコマンドを実行します。それは通常、以下のようになります。


 Pass {
// ... the usual pass state setup ...
CGPROGRAM
// compilation directives for this snippet, e.g.:
#pragma vertex vert
#pragma fragment frag
// the Cg code itself
ENDCG
// ... the rest of pass setup ...
}

Cgのスニペット(挿入テキスト)


Cgプログラムのスニペットは、CGPROGRAMとENDCGの間に書かれます。


スニペットの開始時にコンパイル・ディレクティブ(指示)は#pragma文で与えることができます。Unityによって認識されるディレクティブは次のとおりです。



  • #pragma vertex name -nameはバーテックスプログラムを示します。

  • #pragma fragment name -nameはフラグメントプログラムを示します。

  • の#pragma fragmentoption option-追加オプションはOpenGLのフラグメントプログラムにコンパイルされます。ARBフラグメントプログラムの使用可能なオプションのリストの仕様を参照してください。http://www.opengl.org/registry/specs/ARB/fragment_program.txt

  • このディレクティブは非OpenGLをターゲットにコンパイルされたプログラムまたは頂点プログラムには影響を与えません。

  • #pragma target name -シェーダターゲットにコンパイルする。シェーダターゲット詳細を参照してください。

  • #pragma only_renderers space sepatratesd names-のみ与えられたレンダラのためにシェーダをコンパイルします。デフォルトでは、シェーダは、すべてのレンダラー用にコンパイルされています。レンダラ詳細を参照してください。

  • の#pragma exclude_renderers space separated names -指定されたレンダラのためにシェーダをコンパイルしないでください。デフォルトでは、シェーダは、すべてのレンダラー用にコンパイルされています。レンダラー詳細を参照してください。

  • http://docs.unity3d.com/Documentation/Components/SL-ShaderPrograms.html#renderers

  • #pragma glsl -デスクトップOpenGLのプラットフォーム用のシェーダをコンパイルするとき、(代わりに、ARB頂点/フラグメントプログラムでのデフォルト設定の)GLSLにCg / HLSLに変換する


各スニペットは、バーテックスプログラム、フラグメントプログラム、またはその両方を含める必要があります。したがって、#pragma vertexまたは#pragma fragment またはその両方は必要に応じて指示されます。