#version 330 core

#define MAX_RADIUS 2
#define DOUBLE_HASH 1
#define HASHSCALE1 .1031
#define HASHSCALE3 vec3(.1031, .1030, .0973)

in vec2 vTex;
out vec4 FragColor;
uniform sampler2D iChannel0;
uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;
uniform float uStartDelay;

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

vec2 hash22(vec2 p)
{
	vec3 p3 = fract(vec3(p.xyx) * HASHSCALE3);
    p3 += dot(p3, p3.yzx+19.19);
    return fract((p3.xx+p3.yz)*p3.zy);

}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 fragSize = iResolution.xy;
    vec2 fragUV = fragCoord / fragSize;

    // passthrough before startDelay
    if (iTime < uStartDelay)
    {
        fragColor = texture(iChannel0, fragUV);
        return;
    }

    // use fixed processing resolution
    float resolution = 10.0;
	vec2 uv = fragCoord.xy / iResolution.y * resolution;
    vec2 p0 = floor(uv);

    vec2 circles = vec2(0.);
    for (int j = -MAX_RADIUS; j <= MAX_RADIUS; ++j)
    {
        for (int i = -MAX_RADIUS; i <= MAX_RADIUS; ++i)
        {
			vec2 pi = p0 + vec2(i, j);
            #if DOUBLE_HASH
            vec2 hsh = hash22(pi);
            #else
            vec2 hsh = pi;
            #endif
            vec2 p = pi + hash22(hsh);

            float t = fract(0.3*iTime + hash12(hsh));
            vec2 v = p - uv;
            float d = length(v) - (float(MAX_RADIUS) + 1.)*t;

            float h = 1e-3;
            float d1 = d - h;
            float d2 = d + h;
            float p1 = sin(31.*d1) * smoothstep(-0.6, -0.3, d1) * smoothstep(0., -0.3, d1);
            float p2 = sin(31.*d2) * smoothstep(-0.6, -0.3, d2) * smoothstep(0., -0.3, d2);
            circles += 0.5 * normalize(v) * ((p2 - p1) / (2. * h) * (1. - t) * (1. - t));
        }
    }
    circles /= float((MAX_RADIUS*2+1)*(MAX_RADIUS*2+1));

    float intensity = mix(0.01, 0.15, smoothstep(0.1, 0.6, abs(fract(0.05*iTime + 0.5)*2.-1.)));
    vec3 n = vec3(circles, sqrt(1. - dot(circles, circles)));

    vec3 orig = texture(iChannel0, fragUV).rgb;
    vec3 color = texture(iChannel0, fragUV - intensity * n.xy / iResolution.xy).rgb + 5.0 * pow(clamp(dot(n, normalize(vec3(1.0, 0.7, 0.5))), 0.0, 1.0), 6.0);

    // mix processed effect over original using uAlpha
    vec3 outcol = mix(orig, color, clamp(uAlpha, 0.0, 1.0));
    fragColor = vec4(outcol, 1.0);
}

void main(){ mainImage(FragColor, gl_FragCoord.xy); }