From 12b37a7de3546d142851c08e4fdd1ebd040e696b Mon Sep 17 00:00:00 2001 From: lenn Date: Wed, 25 Feb 2026 16:51:44 +0800 Subject: [PATCH] update --- shader/heatmap.frag | 128 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/shader/heatmap.frag b/shader/heatmap.frag index 6853c38..c35525d 100644 --- a/shader/heatmap.frag +++ b/shader/heatmap.frag @@ -24,4 +24,130 @@ float value01(float v) { return saturate((v - uMinV) / max(uMaxV - uMinV, 1e-6)); } -float maxNeighborValue(vec2 uv) \ No newline at end of file +// float maxNeighborValue(vec2 uv) { +// vec2 texSizeF = 1.0 / uTexelSize; +// ivec2 texSizeI = ivec2(max(vec2(1.0), floor(texSizeF + 0.5))); +// ivec2 maxCoord = texSizeI - ivec2(1); + +// vec2 texelF = clamp(uv * texSizeF, vec2(0.0), vec2(maxCoord)); +// ivec2 base = ivec2(floor(texelF)); +// ivec2 base10 = min(base + ivec2(1, 0), maxCoord); +// ivec2 base01 = min(base + ivec2(0, 1), maxCoord); +// ivec2 base11 = min(base + ivec2(1, 1), maxCoord); + +// float v00 = texelFetch(uHeightTex, base, 0).r; +// float v10 = texelFetch(uHeightTex, base10, 0).r; +// float v01 = texelFetch(uHeightTex, base01, 0).r; +// float v11 = texelFetch(uHeightTex, base11, 0).r; + +// return max(max(v00, v10), max(v01, v11)); +// } + +float maxNeighborValue(vec2 uv) { + vec2 texSizeF = 1.0 / uTexelSize; + ivec2 texSizeI = ivec2(max(vec2(1.0), floor(texSizeF + 0.5))); + ivec2 maxCoord = texSizeI - ivec2(1); + + vec2 texelF = clamp(uv * texSizeF, vec2(0.0), vec2(maxCoord)); + ivec2 base = ivec2(floor(texelF)); + ivec2 base10 = min(base + ivec2(1, 0), maxCoord); + ivec2 base01 = min(base + ivec2(0, 1), maxCoord); + ivec2 base11 = min(base + ivec2(1, 1), maxCoord); + + float v00 = texelFetch(uHeightTex, base, 0).r; + float v10 = texelFetch(uHeightTex, base10, 0).r; + float v01 = texelFetch(uHeightTex, base01, 0).r; + float v11 = texelFetch(uHeightTex, base11, 0).r; + + return max(max(v00, v10), max(v01, v11)); +} + +float maxNeighborValue3(vec2 uv) { + vec2 texSizeF = 1.0 / uTexelSize; + ivec2 texSizeI = ivec2(max(vec2(1.0), floor(texSizeF + 0.5))); + ivec2 maxCoord = texSizeI - ivec2(1); + + vec2 texelF = clamp(uv * texSizeF, vec2(0.0), vec2(maxCoord)); + ivec2 base = ivec2(floor(texelF)); + ivec2 base10 = min(base + ivec2(1, 0), maxCoord); + ivec2 base20 = min(base + ivec2(2, 0), maxCoord); + ivec2 base01 = min(base + ivec2(0, 1), maxCoord); + ivec2 base11 = min(base + ivec2(1, 1), maxCoord); + ivec2 base21 = min(base + ivec2(2, 1), maxCoord); + ivec2 base02 = min(base + ivec2(0, 2), maxCoord); + ivec2 base12 = min(base + ivec2(1, 2), maxCoord); + ivec2 base22 = min(base + ivec2(2, 2), maxCoord); + + float v00 = texelFetch(uHeightTex, base, 0).r; + float v10 = texelFetch(uHeightTex, base10, 0).r; + float v20 = texelFetch(uHeightTex, base20, 0).r; + float v01 = texelFetch(uHeightTex, base01, 0).r; + float v11 = texelFetch(uHeightTex, base11, 0).r; + float v21 = texelFetch(uHeightTex, base21, 0).r; + float v02 = texelFetch(uHeightTex, base02, 0).r; + float v12 = texelFetch(uHeightTex, base12, 0).r; + float v22 = texelFetch(uHeightTex, base22, 0).r; + + float max1020 = max(v10, v20); + float max0111 = max(v01, v11); + float max2102 = max(v21, v02); + float max1222 = max(v12, v22); + + float fmax1 = max(max1020, max0111); + float fmax2 = max(max2102, max1222); + + return max(v00, max(fmax1, fmax2)); +} + +vec3 colorRamp(float t) { + if (t < 0.5) { + return mix(uColorLow, uColorMid, t / 0.5); + } + return mix(uColorMid, uColorHigh, (t - 0.5) / 0.5); +} + +vec3 colorRampWithZero(float t) { + const float zeroW = 0.005; + float blend = smoothstep(0.0, zeroW, t); + float tRamp = saturate((t - zeroW) / max(1.0 - zeroW, 1e-6)); + vec3 ramp = colorRamp(tRamp); + return mix(uColorZero, ramp, blend); +} + +void main() { + float vC = texture(uHeightTex, vUV).r; + bool isZero = abs(vC) <= 1e-6; + float t = value01(vC); + float m = maxNeighborValue(vUV); + float eps = max(1e-4, 0.001 * (uMaxV - uMinV)); + float force = smoothstep(uMaxV - eps, uMaxV, m); + t = max(t, force); + vec3 base = isZero ? uColorZero : colorRampWithZero(t); + + float vL = texture(uHeightTex, vUV - vec2(uTexelSize.x, 0.0)).r; + float vR = texture(uHeightTex, vUV + vec2(uTexelSize.x, 0.0)).r; + float vD = texture(uHeightTex, vUV - vec2(0.0, uTexelSize.y)).r; + float vU = texture(uHeightTex, vUV + vec2(0.0, uTexelSize.y)).r; + + float hL = value01(vL) * uHeightScale; + float hR = value01(vR) * uHeightScale; + float hD = value01(vD) * uHeightScale; + float hU = value01(vU) * uHeightScale; + + float dx = max(1e-6, uPlaneSize.x * uTexelSize.x); + float dy = max(1e-6, uPlaneSize.y * uTexelSize.y); + float dHx = (hR - hL) / (2.0 * dx); + float dHy = (hU - hD) / (2.0 * dy); + + vec3 N = normalize(vec3(-dHx, -dHy, -1.0)); + vec3 L = normalize(uLightDir); + vec3 V = normalize(uCameraPos - vWorldPos); + vec3 H = normalize(L + V); + + float diff = saturate(dot(N, L)); + float spec = pow(saturate(dot(N, H)), 24.0); + + vec3 col = base * (0.50 + 0.50 * diff); + col += vec3(1.0) * spec * 0.18; + FragColor = vec4(clamp(col, 0.0, 1.0), 1.0); +} \ No newline at end of file