Surface Shaderでは、同じCg / HLSLコードを使用して、照明、影、レンダリングパスを制御できます。
ゼロからシェーダーを作成する
ここにシェーダーのフルバージョンがあり、そこからレビューのためにピースを取ります
最初の行はシェーダーパスです
Shader "AgasperShaders/TestShader" {
この方法で、彼は検査官で利用可能になります。
物性
次はPropertiesです 。これらは、インスペクターで設定できるパラメーターです。 各パラメーターには、変数名、説明、タイプ、およびデフォルト値があります。
Properties { _Color ("Main Color", Color) = (1,1,1,1) _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1) _Shininess ("Shininess", Range (0.03, 1)) = 0.078125 _MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {} _BumpMap ("Normalmap", 2D) = "bump" {} _Amount ("Extrusion Amount", Range(-1,1)) = 0.5 }
データ型:
名前(「表示名」、範囲(最小、最大))=数値
最小値から最大値までのfloat型の値の範囲。インスペクターではスライダーとして表示されます
名前(「表示名」、色)=(数値、数値、数値、数値)
値のタイプは色です。デフォルト値は0〜1のRGBA floatです。インスペクターはカラーピッカーとして表示されます。
name( "表示名"、2D)= "def_col" {オプション}
テクスチャを説明します。 インスペクターはテクスチャのようになります
name( "表示名"、Rect)= "def_col" {オプション}
サイズが2 nではないテクスチャを記述します。 インスペクターはテクスチャのようになります
name( "表示名"、キューブ)= "def_col" {options}
キューブマップテクスチャについて説明します。 インスペクターはテクスチャのようになります
名前(「表示名」、フロート)=数値
ただのフロート、インスペクターでは、数値を持つ入力フィールドのようになります
名前(「表示名」、ベクター)=(数値、数値、数値、数値)
ベクターについて説明します
タイプRect、2D、およびCubemapのデフォルト値(def_col)は、空にするか、「白」、「黒」、「灰色」、「バンプ」にすることができます。 テクスチャ内のピクセルのデフォルトの色を示します。
インスペクターに表示される内容は次のとおりです。

サブシェーダー
次はSubShaderです。 ユニットがオブジェクトを描画しようとすると、このシェーダーのリストで最初の適切なSubShaderを検索します。 SubShaderが見つからない場合、エラーが発生します。 たとえば、Shader Model 3.0の機能を実現したいが、古いビデオカードを持っている人のためにプレイする機会を残したい状況で必要になる場合があります。
Surface SubShaderの内部には、SubShaderタグと実際のコード自体があります。
タグRenderType = "Opaque"は、不透明なオブジェクトを描画することを意味します。 タグの詳細については、 こちらとこちらをご覧ください。
SubShader { Tags { "RenderType" = "Opaque" } //code }
実際にはコード自体
SurfaceShaderコードでは、3つの機能を記述することができます(原則として、さらに多くの機能を実行できますが、ほとんど必要ありません)。
- 頂点計算機能
- 表面レンダリング機能
- 照明計算機能
たとえば、モーフィングを使用した拡散バンプスペキュラーシェーダーを作成してみましょう。 この記事では照明計算関数については説明しませんが、標準のBlinnPhongを受け入れます。
CGPROGRAM #pragma surface surf BlinnPhong vertex:vert
CGPROGRAMは、 Cgで記述する内容を宣言するディレクティブです( ENDCGディレクティブで終わります)。
2行目はそれを宣言しています:
- surfと呼ばれる表面レンダリング手順
- シェーダーはBlinnPhongのようなライトを使用します(Lambert、Unlit、または独自の手順もあります)
- 頂点を変更する手順はvertと呼ばれます
ここで、コードで使用される変数を宣言します。
sampler2D _MainTex; sampler2D _BumpMap; fixed4 _Color; half _Shininess; float _Amount;
Unityは、上部で宣言されたシェーダーパラメーターからのデータがこれらの変数に分類されるようにします。 シェーダーパラメーターと同じ方法で名前を付けることが重要です。
void vert (inout appdata_full v) { v.vertex.xyz += v.normal * v.vertex.xyz * _Amount ; }
そして、これがシェーダーの頂点部分の手順です。 たとえば、現在の頂点の座標を取得し、現在の座標とシェーダーパラメーターの係数を乗算した法線を追加します。 もちろん、一部のがらくたは判明しますが、例としてはそれで十分です。 [ 量]スライダーを使用すると、オブジェクトの歪みの度合いを調整できます。
例:

公式文書には兵士の腫れの例がある 。 彼らは法線に沿ってすべての頂点を持ち上げただけです:
v.vertex.xyz += v.normal * _Amount ;

他に何が入っていますか:
- float4頂点 -現在の頂点の座標
- float3 normal-現在の点での表面に垂直
- float4 texcoord-最初のテクスチャのUV座標
- float4 texcoord1-2番目のテクスチャのUV座標
- float4タンジェント -タンジェントベクトル
- float4カラー -頂点カラー
ここでは、頂点シェーダーに関する記事全体を読むことができます。
struct Input { float2 uv_MainTex; float2 uv_BumpMap; };
入力構造では、サーフェスプロシージャでの計算に必要な追加変数をシェーダーに要求できます。 両方のテクスチャのUV座標を求めました。 この変数は、最初のUV座標の場合はuv_TextureName、2番目の場合はuv2_TextureNameと呼ばれる必要があります。
ここで指定できるものの完全なリストを見つけることができます。
サーフェスレンダリング手順自体は次のとおりです。
void surf (Input IN, inout SurfaceOutput o) { // UV . fixed4 tex = tex2D(_MainTex, IN.uv_MainTex); // o.Albedo = tex.rgb * _Color.rgb; // o.Gloss = tex.rgb; // o.Specular = _Shininess; // o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); }
入力構造が渡され、内部で次の形式のSurfaceOutput構造に入力する必要があります。
struct SurfaceOutput { half3 Albedo; // () half3 Normal; // half3 Emission; // ( ) half Specular; //"" ( (dot(viewDir, Normal)) half Gloss; // half Alpha; // ( "RenderType" = "Opaque") };
シェーダーを線で終了します
FallBack "Specular"
これは、何らかの理由でシェーダーがクライアントマシンで動作しない場合、Specularシェーダーにロールバックする必要があることを意味します。
例のシェーダーのフルバージョン
記事の執筆に使用した資料:
http://unity3d.com/support/documentation/Components/SL-SurfaceShaders
http://unity3d.com/support/documentation/Components/SL-SurfaceShaderExamples.html
http://unity3d.com/support/documentation/Components/SL-SubShader
http://unity3d.com/support/documentation/Components/SL-SubshaderTags
http://unity3d.com/support/documentation/Components/SL-ShaderReplacement.html