#version 450
layout(location = 0) in vec2 vUV;
layout(location = 1) flat in float vLayer;
layout(location = 2) in float vShade;
layout(location = 3) in float vDist;
layout(location = 4) in vec3 vWorld;
layout(location = 5) flat in float vLiquid;

layout(std140, binding = 0) uniform Globals {
    mat4  uMVP;
    vec3  uChunkOrigin;
    float uDayLight;
    float uAmbient;
    float uAlphaCutoff;
    vec3  uFogColor;
    float uFogStart;
    float uFogEnd;
    int   uDynLightCount;
    vec4  uDynLightPosRadius0;
    vec4  uDynLightPosRadius1;
    vec4  uDynLightPosRadius2;
    vec4  uDynLightPosRadius3;
    vec4  uDynLightColor0;
    vec4  uDynLightColor1;
    vec4  uDynLightColor2;
    vec4  uDynLightColor3;
    int   uFogMode;
    float uFogDensity;
    float uFogHeightFalloff;
    float uTime;
    float uWaveAmp;
    vec3  uCamPos;
};
layout(binding = 1) uniform sampler2DArray uAtlas;

layout(location = 0) out vec4 FragColor;

vec3 pointLight(vec3 p, vec4 posRadius, vec4 colorIntensity) {
    vec3 d = p - posRadius.xyz;
    float a = max(0.0, 1.0 - dot(d, d) / max(posRadius.w * posRadius.w, 0.001));
    return colorIntensity.rgb * (colorIntensity.a * a * a);
}

vec3 dynamicLighting(vec3 p) {
    vec3 l = vec3(0.0);
    if (uDynLightCount > 0) l += pointLight(p, uDynLightPosRadius0, uDynLightColor0);
    if (uDynLightCount > 1) l += pointLight(p, uDynLightPosRadius1, uDynLightColor1);
    if (uDynLightCount > 2) l += pointLight(p, uDynLightPosRadius2, uDynLightColor2);
    if (uDynLightCount > 3) l += pointLight(p, uDynLightPosRadius3, uDynLightColor3);
    return min(l, vec3(2.0));
}

void main() {
    vec2 uv = vUV;
    if (vLiquid > 0.5 && uWaveAmp > 0.0)
        uv += vec2(uTime * 0.02, uTime * 0.013);
    vec4 tex = texture(uAtlas, vec3(uv, vLayer));
    if (tex.a < uAlphaCutoff) discard;
    vec3 color = tex.rgb * vShade;
    if (vLiquid > 0.5 && uWaveAmp > 0.0) {
        vec3 toCam = normalize(uCamPos - vWorld);
        float grazing = 1.0 - clamp(abs(toCam.y), 0.0, 1.0);
        color *= 1.0 - 0.30 * grazing * grazing;
    }

    if (uDynLightCount > 0) {
        vec3 dyn = dynamicLighting(vWorld);
        color = max(color, tex.rgb * dyn);
        color += tex.rgb * dyn * 0.10;
    }

    float fog;
    if (uFogMode == 1) {
        float hf = exp2(-min(max(vWorld.y - 62.0, 0.0) * uFogHeightFalloff, 1.2));
        float d = max(vDist - uFogEnd * 0.5, 0.0) * uFogDensity * hf;
        fog = 1.0 - exp2(-d * d);
        fog = max(fog, clamp((vDist - uFogEnd * 0.85) / (uFogEnd * 0.15), 0.0, 1.0));
    } else {
        fog = clamp((vDist - uFogStart) / max(uFogEnd - uFogStart, 0.001), 0.0, 1.0);
    }
    color = mix(color, uFogColor, fog);

    FragColor = vec4(color, tex.a);
}
