Files
Fishing2/Packages/com.jbooth.microverse/Scripts/Shaders/Stamps/MeshStamp.shader
2025-06-09 23:23:13 +08:00

201 lines
7.7 KiB
Plaintext

Shader "Hidden/MicroVerse/MeshStamp"
{
Properties
{
[HideInInspector] _MainTex ("Heightmap Texture", 2D) = "white" {}
[HideInInspector] _StampTex("Stamp", 2D) = "black" {}
[HideInInspector] _FalloffTexture("Falloff", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local_fragment _ _USEFALLOFF _USEFALLOFFRANGE _USEFALLOFFTEXTURE _USEFALLOFFSPLINEAREA
#pragma shader_feature_local_fragment _ _USEFALLOFFPAINTAREA
#pragma shader_feature_local_fragment _ _FALLOFFSMOOTHSTEP _FALLOFFEASEIN _FALLOFFEASEOUT _FALLOFFEASEINOUT
#pragma shader_feature_local_fragment _ _FALLOFFNOISE _FALLOFFFBM _FALLOFFWORLEY _FALLOFFWORM _FALLOFFWORMFBM _FALLOFFNOISETEXTURE
#pragma shader_feature_local_fragment _ _SUBTRACT
#pragma shader_feature_local_fragment _ _CONNECT
#pragma shader_feature_local_fragment _ _FILLAROUND
// because unity's height format is stupid and only uses half the possible
// precision.
#define kMaxHeight (32766.0f/65535.0f)
#include_with_pragmas "UnityCG.cginc"
#include_with_pragmas "/../Noise.cginc"
#include_with_pragmas "/../HeightStampFiltering.cginc"
struct vertexInput
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float2 stampUV: TEXCOORD1;
};
Texture2D _MainTex;
float4 _MainTex_TexelSize;
SamplerState shared_point_clamp;
float3 _NoiseUV;
sampler2D _StampTex;
float4 _StampTex_TexelSize;
float4x4 _Transform;
float4 _YBounds;
float _AlphaMapSize;
float3 _RealSize;
sampler2D _OriginalHeights;
float _BlurSize;
float3 _HeightScaleClamp;
float _ConnectHeight;
v2f vert(vertexInput v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.stampUV = mul(_Transform, float4(v.uv, 0, 1)).xy;
return o;
}
float BlurSample(float2 stampUV, float height)
{
float col = 0;
float totalWeight = 0.0;
int blurSize = int(_BlurSize);
float blurSkip = 1 + _BlurSize / 4;
// Sum all pixels around the current pixel
float2 ybounds = _YBounds.xy;
ybounds.y -= ybounds.x;
ybounds.y *= _HeightScaleClamp.x;
ybounds.y += ybounds.x;
float2 uv = stampUV;
#if _SUBTRACT || _CONNECT || _FILLAROUND
uv.y = 1.0 - uv.y;
#endif
[loop]
for (int x = -blurSize; x <= blurSize; x += 1)
{
[loop]
for (int y = -blurSize; y <= blurSize; y += 1)
{
float hs = SAMPLE_DEPTH_TEXTURE(_StampTex, uv + float2(x, y) * _MainTex_TexelSize.xy * blurSkip).r;
// clip out taller points of the mesh
#if _CONNECT
if(hs < _ConnectHeight)
hs = 0.0;
#endif
float orig = hs;
#if _SUBTRACT || _FILLAROUND || _CONNECT
hs = 1 - hs;
#endif
hs = clamp(hs, _HeightScaleClamp.y, _HeightScaleClamp.z);
hs = (lerp(ybounds.x, ybounds.y, hs) + _YBounds.w) / _RealSize.y;
// clip out non-rendered pixels in the depth buffer. This is ok
// because we always render with an extra 0.5 meters of space on each end of
// the clipping area..
if (orig < 0.0001)
hs = height;
#if _SUBTRACT
hs = min(hs, height);
#else
hs = max(hs, height);
#endif
col += hs;
}
}
// Average the colors
int totalPixels = (2 * blurSize + 1) * (2 * blurSize + 1);
col /= totalPixels;
return col;
}
float4 frag(v2f i) : SV_Target
{
float4 heightSample = _MainTex.SampleLevel(shared_point_clamp, i.uv, 0);
bool cp = (i.stampUV.x < 0 || i.stampUV.x > 1 || i.stampUV.y < 0|| i.stampUV.y > 1);
if (cp)
return heightSample;
float height = UnpackHeightmap(heightSample);
float2 noiseUV = (i.uv * _NoiseUV.z) + _NoiseUV.xy;
float2 stampUV = i.stampUV;
float2 falloffuv = noiseUV;
if (_FalloffNoise2.x > 0)
falloffuv = stampUV;
float noise = 0;
float falloff = ComputeFalloff(i.uv, i.stampUV, noiseUV, 0);
#if _FALLOFFNOISE
noise = (Noise(falloffuv, _FalloffNoise)) / _RealSize.y;
#elif _FALLOFFFBM
noise = (NoiseFBM(falloffuv, _FalloffNoise)) / _RealSize.y;
#elif _FALLOFFWORLEY
noise = (NoiseWorley(falloffuv, _FalloffNoise)) / _RealSize.y;
#elif _FALLOFFWORM
noise = (NoiseWorm(falloffuv, _FalloffNoise)) / _RealSize.y;
#elif _FALLOFFWORMFBM
noise = (NoiseWormFBM(falloffuv, _FalloffNoise)) / _RealSize.y;
#elif _FALLOFFNOISETEXTURE
noise = (tex2D(_FalloffNoiseTexture, falloffuv * _FalloffNoiseTexture_ST.xy + _FalloffNoiseTexture_ST.zw)[_FalloffNoiseChannel] * 2.0 - 1.0) / _RealSize.y * _FalloffNoise.y + _FalloffNoise.w;
#endif
#if _FALLOFFNOISE || _FALLOFFFBM || _FALLOFFWORLEY || _FALLOFFWORM || _FALLOFFWORMFBM || _FALLOFFNOISETEXTURE
noise *= 1-falloff;
falloff = ComputeFalloff(i.uv, stampUV, noiseUV, noise);
#endif
float depthSample = BlurSample(stampUV, height);
#if _SUBTRACT
float blend = min(height, depthSample);
#else
float blend = max(height, depthSample);
#endif
#if _FILLAROUND
float newHeight = saturate(_YBounds.x) * depthSample;
blend = max(height, newHeight);
return PackHeightmap(clamp(lerp(height, blend, falloff), 0, kMaxHeight));
#elif _CONNECT
float newHeight = saturate(_YBounds.x) * depthSample;
float boundBottom = saturate((_YBounds.x + 0.5f) / _RealSize.y);
newHeight = min(newHeight, boundBottom);
blend = max(height, newHeight);
return PackHeightmap(clamp(lerp(height, blend, falloff), 0, kMaxHeight));
#endif
return PackHeightmap(clamp(lerp(height, blend, falloff), 0, kMaxHeight));
}
ENDCG
}
}
}