in vec2 texCoord;
out vec4 fragColor;

uniform sampler2D texture0;
uniform float threshold;
uniform float amount;
uniform float radius;

float hash12(vec2 p) {
    vec3 p3 = fract(vec3(p.xyx) * 0.1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

vec2 vogelDiskSample(int i, int n, float angleOffset) {
    float fi = float(i);
    float fn = float(n);
    float r = sqrt((fi + 0.5) / fn);
    float theta = fi * 2.39996323 + angleOffset;
    return r * vec2(cos(theta), sin(theta));
}

vec4 blur(sampler2D tex, vec2 uv, vec2 texelSize, float radiusPx, float angleJitter) {
    const int TAP_COUNT = 32;
    vec4 sum = vec4(0.0);
    float wsum = 0.0;

    float sigma = max(radiusPx * 0.45, 1.0);
    float invSigma2 = 1.0 / (sigma * sigma);

    for (int i = 0; i < TAP_COUNT; i++) {
        vec2 d = vogelDiskSample(i, TAP_COUNT, angleJitter) * radiusPx;
        float r2 = dot(d, d);
        float w = exp(-0.5 * r2 * invSigma2);
        sum += texture(tex, uv + d * texelSize) * w;
        wsum += w;
    }

    return sum / max(wsum, 1e-6);
}

void main() {
    vec2 uv = texCoord.st;
    vec2 texelSize = vec2(1.0 / 1920.0, 1.0 / 1080.0);

    vec4 original = texture(texture0, uv);

    float safeRadius = max(radius, 0.0);
    float jitter = 6.2831853 * hash12(floor(texCoord.st * vec2(1920.0, 1080.0)));
    vec4 blurred = blur(texture0, uv, texelSize, safeRadius, jitter);

    vec3 high = original.rgb - blurred.rgb;
    float detail = max(max(abs(high.r), abs(high.g)), abs(high.b));
    float edgeMask = smoothstep(threshold, threshold + 0.03, detail);

    fragColor = vec4(original.rgb + amount * high * edgeMask, original.a);
}
