カスタムの Terrain ツールシェーダー
ビルトインのペインティングマテリアルを使用しない場合は、独自のシェーダーを作成する必要があります。作成後はそのシェーダーを使用してマテリアルを作成し、代わりにそのマテリアルを使用して Terrain (地形) テクスチャデータを変更できます。
以下は Terrain ツールシェーダーの例です。
Shader "TerrainTool/CustomTerrainTool"
{
Properties { _MainTex ("Texture", any) = "" {} }
SubShader
{
ZTest Always Cull Off ZWrite Off
HLSLINCLUDE
#include "UnityCG.cginc"
#include "Packages/com.unity.terrain-tools/Shaders/TerrainTools.hlsl"
sampler2D _MainTex;
float4 _MainTex_TexelSize; // 1/width、1/height、width、height
sampler2D _BrushTex;
float4 _BrushParams;
#define BRUSH_STRENGTH (_BrushParams[0])
#define BRUSH_TARGETHEIGHT (_BrushParams[1])
#define kMaxHeight (32766.0f/65535.0f)
struct appdata_t
{
float4 vertex : POSITION;
float2 pcUV : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 pcUV : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.pcUV = v.pcUV;
return o;
}
ENDHLSL
Pass
{
Name "CustomTerrainTool"
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 frag(v2f i) : SV_Target
{
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
// 境界外の乗数
float oob = all(saturate(brushUV) == brushUV) ? 1.0f : 0.0f;
// ソースのハイトマップテクスチャの領域となる MainTex をサンプリングし、指定された UV での現在の高さの値を取得します
// ここでは UnpackHeightmap が必要になります。UnpackHeightmap は、現在のプラットフォームやグラフィックスデバイスが R16_UNorm テクスチャフォーマットに対応していない場合に、高さの値を R および G チャンネルからアンパックするためです。R16_UNorm フォーマットに対応している場合は、R チャンネルのみから読み取りを行います
float height = UnpackHeightmap(tex2D(_MainTex, i.pcUV));
// このフラグメントでのブラシマスクの影響度を計算します
float brushShape = oob * UnpackHeightmap(tex2D(_BrushTex, brushUV));
// 新しい高さの値を計算します
height = height + BRUSH_STRENGTH * brushShape;
// 書き込み先の RenderTexture に新しい高さを格納します。ハイトマップ自体は符号付きですが、Terrain のレンダリング時に符号なしのテクスチャとして処理されるため、0.0f と 0.5f の間で固定します
// ここでは PackHeightmap が必要です。PackHeightmap は、現在のプラットフォームやグラフィックスデバイスが R16_UNorm テクスチャフォーマットに対応していない場合に、高さの値を R および G チャンネルにパックするためです。R16_UNorm フォーマットに対応している場合、R チャンネルのみに書き込みを行います
return PackHeightmap(clamp(height, 0, kMaxHeight));
}
ENDHLSL
}
}
}