This commit is contained in:
2026-02-28 02:42:23 +08:00
parent edb25a75c3
commit 8a4058e7d1
14 changed files with 2360 additions and 2309 deletions

View File

@@ -1,149 +1,149 @@
#version 330 core
in vec2 vUV;
in vec3 vWorldPos;
out vec4 FragColor;
uniform sampler2D uHeightTex;
uniform float uMinV;
uniform float uMaxV;
uniform float uHeightScale;
uniform vec2 uTexelSize;
uniform vec2 uPlaneSize;
uniform vec3 uCameraPos;
uniform vec3 uLightDir;
uniform vec3 uColorZero;
uniform vec3 uColorLow;
uniform vec3 uColorMid;
uniform vec3 uColorHigh;
float saturate(float x) {
return clamp(x, 0.0, 1.0);
}
float value01(float v) {
return saturate((v - uMinV) / max(uMaxV - uMinV, 1e-6));
}
// 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));
}
ivec2 texSizeI(vec2 texelSize) {
vec2 texSizeF = 1.0 / texelSize;
ivec2 texSizeI = ivec2(max(vec2(1.0), floor(texSizeF + 0.5)));
return texSizeI;
}
ivec2 uvToTexel(vec2 uv, vec2 texelSize) {
ivec2 sizeI = texSizeI(texelSize);
ivec2 maxCoord = sizeI - ivec2(1);
vec2 texelF = clamp(uv * vec2(maxCoord), vec2(0.0), vec2(maxCoord));
return ivec2(floor(texelF));
}
float maxNeighborValueK(vec2 uv, int radius) {
radius = clamp(radius, 0, 4);
ivec2 sizeI = texSizeI(uTexelSize);
ivec2 maxCoord = sizeI - ivec2(1);
ivec2 p = uvToTexel(uv, uTexelSize);
float vmax = -1e30;
for (int i = -4; i <= 4; ++i) {
for (int j = -4; j <= 4; ++j) {
if (abs(i) > radius || abs(j) > radius) continue;
ivec2 c = clamp(p + ivec2(i, j), ivec2(0), maxCoord);
float v = texelFetch(uHeightTex, c, 0).r;
vmax = max(vmax, v);
}
}
return vmax;
}
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);
#version 330 core
in vec2 vUV;
in vec3 vWorldPos;
out vec4 FragColor;
uniform sampler2D uHeightTex;
uniform float uMinV;
uniform float uMaxV;
uniform float uHeightScale;
uniform vec2 uTexelSize;
uniform vec2 uPlaneSize;
uniform vec3 uCameraPos;
uniform vec3 uLightDir;
uniform vec3 uColorZero;
uniform vec3 uColorLow;
uniform vec3 uColorMid;
uniform vec3 uColorHigh;
float saturate(float x) {
return clamp(x, 0.0, 1.0);
}
float value01(float v) {
return saturate((v - uMinV) / max(uMaxV - uMinV, 1e-6));
}
// 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));
}
ivec2 texSizeI(vec2 texelSize) {
vec2 texSizeF = 1.0 / texelSize;
ivec2 texSizeI = ivec2(max(vec2(1.0), floor(texSizeF + 0.5)));
return texSizeI;
}
ivec2 uvToTexel(vec2 uv, vec2 texelSize) {
ivec2 sizeI = texSizeI(texelSize);
ivec2 maxCoord = sizeI - ivec2(1);
vec2 texelF = clamp(uv * vec2(maxCoord), vec2(0.0), vec2(maxCoord));
return ivec2(floor(texelF));
}
float maxNeighborValueK(vec2 uv, int radius) {
radius = clamp(radius, 0, 4);
ivec2 sizeI = texSizeI(uTexelSize);
ivec2 maxCoord = sizeI - ivec2(1);
ivec2 p = uvToTexel(uv, uTexelSize);
float vmax = -1e30;
for (int i = -4; i <= 4; ++i) {
for (int j = -4; j <= 4; ++j) {
if (abs(i) > radius || abs(j) > radius) continue;
ivec2 c = clamp(p + ivec2(i, j), ivec2(0), maxCoord);
float v = texelFetch(uHeightTex, c, 0).r;
vmax = max(vmax, v);
}
}
return vmax;
}
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);
}