Rasagar/Assets/ProceduralTerrainPainter/Editor/Heatmap.shader

133 lines
4.5 KiB
Plaintext
Raw Permalink Normal View History

2024-08-26 13:07:20 -07:00
Shader "Hidden/TerrainPainter/Heatmap"
{
SubShader
{
Cull Back ZWrite On
Blend SrcAlpha OneMinusSrcAlpha
HLSLINCLUDE
#include "UnityCG.cginc"
#include "TerrainPreview.cginc"
sampler2D _LayerMaskTex;
sampler2D _NormalMap;
float4 _Heightmap_TexelSize;
float4 _LayerTiling; //XY: Tling //ZW: Resolution
float _ContourOn;
float _TilingOn;
ENDHLSL
Pass
{
Name "Terrain layer heatmap"
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
struct Varyings {
float4 positionCS : SV_POSITION;
float3 positionWorld : TEXCOORD0;
float3 positionWorldOrig : TEXCOORD1;
float2 pcPixels : TEXCOORD2;
float2 uv : TEXCOORD3;
};
Varyings vert(uint vid : SV_VertexID)
{
Varyings o;
// build a quad mesh, with one vertex per paint context pixel (pcPixel)
float2 pcPixels = BuildProceduralQuadMeshVertex(vid);
// compute heightmap UV and sample heightmap
float2 heightmapUV = PaintContextPixelsToHeightmapUV(pcPixels);
float heightmapSample = UnpackHeightmap(tex2Dlod(_Heightmap, float4(heightmapUV, 0, 0)));
// compute brush UV
float2 brushUV = PaintContextPixelsToBrushUV(pcPixels);
// compute object position (in terrain space) and world position
float3 positionObject = PaintContextPixelsToObjectPosition(pcPixels, heightmapSample);
float3 positionWorld = TerrainObjectToWorldPosition(positionObject);
o.pcPixels = pcPixels;
o.positionWorld = positionWorld;
o.positionWorldOrig = positionWorld;
o.positionCS = UnityWorldToClipPos(positionWorld);
o.uv = brushUV;
return o;
}
float Contours(sampler2D heightmap, float2 uv)
{
float contourLineFactor = 512;
float majorLineSteps = contourLineFactor / (contourLineFactor/8);
float thickness = _Heightmap_TexelSize.x * 0.5;
uint mip = 0;
//White base
float lines = 1;
//Cross-kernel sampling
float corner0 = tex2Dlod(heightmap, float4(uv.x - thickness, uv.y, 0, mip)).r;
float corner1 = tex2Dlod(heightmap, float4(uv.x + thickness, uv.y, 0, mip)).r;
float corner2 = tex2Dlod(heightmap, float4(uv.x, uv.y + thickness, 0, mip)).r;
float corner3 = tex2Dlod(heightmap, float4(uv.x + thickness, uv.y + thickness, 0, mip)).r;
//Elevation range of the pixel's area
float minHeight = min(min(corner0, corner1), min(corner2, corner3));
float maxHeight = max(max(corner0, corner1), max(corner2, corner3));
//Check if the pixel's area crosses at least one contour line, creating a secondary line
if (floor(minHeight * contourLineFactor) != floor(maxHeight * contourLineFactor))
{
lines = 0.75;
}
//Major lines
if (floor(minHeight * contourLineFactor / majorLineSteps) != floor(maxHeight * contourLineFactor / majorLineSteps))
{
lines = 0.5;
}
return 1-lines;
}
inline float mod(float a, float b) { return a - (b * floor(a / b)); }
float Checker(float2 uv)
{
float fmodResult = mod(floor(uv.x) + floor(uv.y), 2.0);
return max(sign(fmodResult), 0.0);
}
float4 frag(Varyings i) : SV_Target
{
float layerAlpha = UnpackHeightmap(tex2D(_LayerMaskTex, i.uv)).r;
float lines = lerp(0, Contours(_Heightmap, i.uv), _ContourOn);
float texelChecker = Checker(i.positionWorld.xz * _LayerTiling.xy * 2.0);
texelChecker = lerp(1, saturate(texelChecker + 0.75), _TilingOn);
//return float4(texelChecker.xxx, 0.7);
float3 normal = tex2D(_NormalMap, i.uv);
float3 lightDir = UnityWorldSpaceLightDir(i.positionWorld.xyz);
//lightDir = normalize(_WorldSpaceCameraPos - i.positionWorld);
//Add some diffuse shading to visualize the contour of the terrain
float diffuse = saturate(dot(lightDir, normal) + 0.66);
float3 color = float3(layerAlpha, 0.0, 0.0) - lines;
return float4(color * diffuse * texelChecker, layerAlpha);
}
ENDHLSL
}
}
Fallback Off
}