#version 330 core
// FX V2 `zoomBlur` kernel -- ported from Android
// EditorImageZoomBlurFilter (ZOOM_BLUR_FRAGMENT_SHADER). Radial streaks
// towards a center point: 41 taps march from the pixel towards the center,
// weighted by a 4*(p - p*p) parabola so the ends contribute least.
//
// The per-pixel `rand` jitter on the march offset is Android's, and it is
// what keeps 41 taps from banding into visible rings. It is a pure
// function of the texture coordinate, so it stays stable frame to frame
// and identical between preview and export.
//
// The caller passes blurSize already divided by 200 (the data.json value
// is in a 0..~100 authoring scale, see runFxV2Kernel's ZoomBlur case).
in  vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D u_src;
uniform vec2      u_texScale;
uniform float     u_blurSize;
uniform vec2      u_center;

float rand(vec2 co) {
    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}

void main() {
    vec2 uv = vec2(TexCoord.x, 1.0 - TexCoord.y);
    if (abs(u_blurSize) < 0.001) {
        FragColor = texture(u_src, clamp(uv, 0.0, 1.0) * u_texScale);
        return;
    }

    vec2  toCenter = u_center - uv;
    float offset   = rand(uv);
    vec4  color    = vec4(0.0);
    float total    = 0.0;
    for (float t = 0.0; t <= 40.0; t++) {
        float percent = (t + offset) / 40.0;
        float weight  = 4.0 * (percent - percent * percent);
        // Clamp before applying u_texScale -- the scratch texture can be
        // larger than this frame's extent (never-shrink), so sampling past
        // the logical edge would read last frame's residue.
        vec2  s       = clamp(uv + toCenter * percent * u_blurSize, 0.0, 1.0);
        color += texture(u_src, s * u_texScale) * weight;
        total += weight;
    }
    FragColor = color / total;
}
