#version 330 core

in vec3 vNormal;
in vec3 vWorldPos;
in vec2 vUV;
out vec4 FragColor;

uniform vec3 uCameraPos;
uniform vec3 uLightDir;
uniform sampler2D uHeightTex;
uniform float uMinV;
uniform float uMaxV;
uniform vec2 uTexelSize;
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));
}

vec3 colorRamp(float t) {
    if (t < 0.5) {
        return mix(uColorLow, uColorMid, t / 0.5);
    }
    return mix(uColorMid, uColorHigh, (t - 0.5) / 0.5);
}

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));
}

void main() {
    vec3 N = normalize(vNormal);
    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);

    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 : colorRamp(t);

    vec3 col = base * (0.35 + 0.65 * diff);
    col += vec3(1.0) * spec * 0.10;
    FragColor = vec4(clamp(col, 0.0, 1.0), 1.0);
}
