Unity3D 3.xテレインバンプスペキュラーシェーダー

Unity3Dは現在、統合された地形での鏡面オーバーレイをサポートしていません。 この機会にグーグルは、 このシェーダーとその修正のいくつかの形であまり印象的な結果をもたらしませんでした。 写真に触発され、アーカイブをダウンロードしたので、がっかりしました。 まず、シェーダーをランドスケープで機能させるには、シェーダーを制御するスクリプトをハングアップする必要があります(非常に不便です)。次に、この実装では、4つを超える法線マップを割り当てることができません。

この記事では、ランドスケープ用の独自のシェーダーを作成するプロセスを説明し、同時に標準シェーダーがどのように機能するかを説明します。



標準ユニットシェーダーのランドスケープレンダリングエンジン



ユニット内の風景をレンダリングするために使用される2つのシェーダーがあります。

非表示/ TerrainEngine / Splatmap / Lightmap-FirstPassおよびHidden / TerrainEngine / Splatmap / Lightmap-AddPassここからダウンロード



最初のシェーダーは、最初の4つの地形テクスチャを描画します。 2番目のシェーダーは、テクスチャが終了するまで、残りのテクスチャを一度に4つ連続して描画します。



エンジンからシェーダーに渡されるもの:



... struct Input { float2 uv_Control : TEXCOORD0; float2 uv_Splat0 : TEXCOORD1; float2 uv_Splat1 : TEXCOORD2; float2 uv_Splat2 : TEXCOORD3; float2 uv_Splat3 : TEXCOORD4; }; sampler2D _Control; sampler2D _Splat0,_Splat1,_Splat2,_Splat3; ...
      
      







_SplatX-マテリアルを使用したテクスチャ

_Control-コントロールカード。 これは、各チャネルが特定のポイントでマテリアルの1つの輝度を設定するテクスチャです。 コントロールマップは、エンジンの腸内の4つのマテリアルごとに、ランドスケープマテリアルマップ(アルファマップ)に基づいて作成されます。 コントロールテクスチャには4つのチャンネルがあるため、シェーダーは一度に4つ以下のマテリアルをレンダリングします。









シェーダーで次に何が起こるか見てみましょう:



現在のポイント(o.Albedo)の色が考慮される唯一の手順があり、RGBAコントロールカードからのポイントの明るさとマテリアルのテクスチャからの色の積の合計に等しくなります。



  ... void surf (Input IN, inout SurfaceOutput o) { half4 splat_control = tex2D (_Control, IN.uv_Control); half3 col; col = splat_control.r * tex2D (_Splat0, IN.uv_Splat0).rgb; col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1).rgb; col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2).rgb; col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3).rgb; o.Albedo = col; o.Alpha = 0.0; } ...
      
      







彼の仕事の結果は以下のとおりです。







この場合の暴露は、コントロールカード上のいくつかの材料(チャネル)の押し付けにより発生しました。 通常、ランドスケープ上の1つのマテリアルが別のマテリアルにスムーズに移行するため、1つのマテリアルを別のマテリアルに課す必要はほとんどありません。



2番目のシェーダーは考慮しません。 ほぼ同じで、インデックスが3を超えるテクスチャにのみ使用されます。



独自のシェーダーを作成する


1つのパスには4つのマテリアルしか存在できず、スクリプトを使用して法線をシェーダーに割り当てたくないため、下の図に示すように、風景を通して法線を押し出します。

これで、ランドスケープ上の1つおきのテクスチャは前のマテリアルに垂直になります。 検査官がこのタイプを通常に設定することが重要です。 さらに、マテリアルのテクスチャにスペキュラーマップに完全に適合する未使用のチャンネルAがあります。







新しいサーフィン手順:



 void surf (Input IN, inout SurfaceOutput o) { fixed4 splat_control = tex2D (_Control, IN.uv_Control); fixed3 col; fixed spec; // RGBA     fixed4 d1 = tex2D (_Splat0, IN.uv_Splat0); // RGBA     fixed4 d2 = tex2D (_Splat2, IN.uv_Splat2); //      fixed3 n1 = UnpackNormal( tex2D (_Splat1, IN.uv_Splat1) ); //      fixed3 n2 = UnpackNormal( tex2D (_Splat3, IN.uv_Splat3) ); //        col = splat_control.r * d1.rgb; //  (  ) o.Normal = normalize(lerp(fixed3(0.5,0.5,1), n1, clamp(splat_control.r + 0.3,0,1))); //        ,      . "0.1" -   ,    . spec = (1 - d1.a) * splat_control.r * 0.1; //        col += splat_control.b * d2.rgb; o.Normal += normalize(lerp(fixed3(0.5,0.5,1), n2, clamp(splat_control.b + 0.3,0,1))); spec += (1 - d2.a) * splat_control.b * 0.1; //  ,   basemap' o.Albedo = col * 0.5; //  o.Specular = spec; o.Gloss = spec; o.Alpha = 0.0; }
      
      







算術演算以外にはほとんど何もないので、手順のすべてを明確にする必要があります。 解析したいのはこの行だけです:

o.Normal = lerp(fixed3(0.5,0.5,1), n1, clamp(splat_control.r + 0.3,0,1));





法線は、表面に垂直な単位ベクトルです。 そして、それをスムーズに減らす必要があるため、何らかの要因を掛けることはできません。 この問題を解決するために、いわゆる法線で現在の法線を補間します。 「通常のゼロ」では、テクスチャにレリーフはありません。



法線マップを適用するには、ファー上で接線を計算する必要があります(法線に垂直で、表面に平行で、スキャンの座標Uを増加させる方向のベクトル)。 通常、それらはモデルが開発されるソフトウェアによって考慮されますが、ランドスケープは「オンザフライ」でユニット内に構築されるため、そこに接線はありません。

シェーダー内部の接線を自分で計算する必要があります。



 void vert (inout appdata_full v) { fixed3 T1 = float3(1, 0, 0); if (dot(T1,v.normal) > 0.99) { T1 = float3(0,1,0); //workaround } fixed3 Bi = cross(T1, v.normal); fixed3 newTangent = normalize(cross(v.normal, Bi)); v.tangent.xyz = newTangent.xyz; if (dot(cross(v.normal,newTangent),Bi) < 0) v.tangent.w = -1.0f; else v.tangent.w = 1.0f; }
      
      







後続のパスのシェーダーはほぼ同じです。



動的にランドスケープを作成する場合は、コード内のマテリアルのインデックスを修正することを忘れないでください。 それらは2倍する必要があります。なぜなら 奇数のインデックスは正常です。



materials[x, z, material_number*2] = 1;







この方法の短所:



簡単に言うと、読むのが面倒な人には:



標準のテクスチャを使用した結果、およびそこからカードが削除された(/になった):





シェーダーをダウンロード



All Articles