#version 330 core
out vec4 FragColor;
in vec2 vUV;
uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;

vec4 tanh4(vec4 x)
{
    vec4 e = exp(clamp(2.0 * x, vec4(-20.0), vec4(20.0)));
    return (e - vec4(1.0)) / (e + vec4(1.0));
}

void mainImage(out vec4 O, vec2 I)
{
    float i = 0.0;
    float j = 0.0;
    float t = 0.0;
    float v = 0.0;
    float s = 1.0;
    float T = iTime;

    O = vec4(0.0);

    for (; i++ < 40.0; t += v * 0.5)
    {
        vec3 q;
        vec3 p = t * normalize(vec3(I + I, 0.0) - iResolution.xyy);

        p *= 0.7 + 0.3 * fract(dot(I, sin(I.yx + T)));
        p = reflect(p, normalize(sin(T * 0.2 + vec3(0.0, 1.0, 2.0))));
        p += sin(p * 3.0 + ceil(p.x * p.y * 5.0)) / 3.0;
        p.z -= T;

        v = 0.0;
        j = 0.0;
        s = 1.0;

        for (; j++ < 10.0;)
        {
            p *= sqrt(j);
            s *= sqrt(j);
            q = abs(mod(p - 1.0, 2.0) - 1.0);
            v = max(v, (0.8 - max(max(q.x, q.y), q.z)) / s);
        }

        O += exp(sin(t * vec4(1.0, 2.0, 3.0, 0.0))) / (sqrt(max(v, 0.0)) + 0.01);
    }

    O = tanh4(O / 600.0);
    O *= O;
    O.a = 1.0;
}

void main()
{
    mainImage(FragColor, gl_FragCoord.xy);
    FragColor.a *= uAlpha;
}
