forked from BilalY/Rasagar
3.1 KiB
3.1 KiB
Custom Terrain Tool shaders
If you don't want to use the built-in painting Material, you need to create your own shader. You can then use that shader to create a Material, and use that Material instead to modify Terrain Texture data.
Here is an example Terrain Tool shader.
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);
// out of bounds multiplier
float oob = all(saturate(brushUV) == brushUV) ? 1.0f : 0.0f;
// Sample the MainTex, which should be a region of the source Heightmap texture, to get the current height value at the provided UV
// UnpackHeightmap is necessary here because it unpacks the height value from R and G channels if the current platform/graphics device does not support R16_UNorm texture formats. If R16_UNorm formats are supported, UnpackHeightmap just reads from the R channel.
float height = UnpackHeightmap(tex2D(_MainTex, i.pcUV));
// Calculate the influence from the brush mask at this fragment
float brushShape = oob * UnpackHeightmap(tex2D(_BrushTex, brushUV));
// Calculate the new height value
height = height + BRUSH_STRENGTH * brushShape;
// Store the new height into the destination RenderTexture. Clamp between 0.0f and 0.5f because the Heightmap itself is signed but is treated as an unsigned texture when rendering the Terrain
// PackHeightmap is necessary here because it packs the height value into R and G channels if the current platform/graphics device does not support R16_UNorm texture formats. If R16_UNorm formats are supported, PackHeightmap just writes to the R channel.
return PackHeightmap(clamp(height, 0, kMaxHeight));
}
ENDHLSL
}
}
}