#define M_PI 3.1415926535897932384626433832795
#define M_E 2.71828182846

uniform sampler2DArray u_textures;
uniform vec4 u_color;
uniform float u_blur_radius;

in vec2 v_uv;
flat in vec4 v_texture_info;
flat in int v_atlas;
out vec4 frag_color;

float lookup_font(ivec3 texture_size, vec2 uv) {
    float col = texture(u_textures, vec3(
        (vec2(v_texture_info.xy) + vec2(v_texture_info.zw) * uv) / vec2(texture_size.xy),
        float(v_atlas))
    ).r;
    col *= float(all(greaterThan(uv, vec2(0.0, 0.0))));
    col *= float(all(lessThan(uv, vec2(1.0, 1.0))));
    return col;
}

void main() {
    ivec3 texture_size = textureSize(u_textures, 0);
    float alpha = 0.0;
    vec2 pixel = 1.0 / v_texture_info.zw;

    float total = 0.0;
    float blur_div = pow(u_blur_radius, 4);
    for (float x = -u_blur_radius; x <= u_blur_radius; x += 1.0) {
        for (float y = -u_blur_radius; y <= u_blur_radius; y += 1.0) {
            float bx = u_blur_radius - abs(x);
            float by = u_blur_radius - abs(y);
            float weight = (bx * by) / blur_div;
            total += weight;
        }
    }

    for (float x = -u_blur_radius; x <= u_blur_radius; x += 1.0) {
        for (float y = -u_blur_radius; y <= u_blur_radius; y += 1.0) {
            float bx = u_blur_radius - abs(x);
            float by = u_blur_radius - abs(y);
            float weight = ((bx * by) / blur_div) / total;
            alpha += lookup_font(texture_size, v_uv + vec2(x, y) * pixel) * weight;
        }
    }

    frag_color = u_color * vec4(1.0, 1.0, 1.0, alpha);
}
