#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));
}

mat2 rot(float a)
{
    float c = cos(a);
    float s = sin(a);
    return mat2(c, -s, s, c);
}

void mainImage(out vec4 O, vec2 I)
{
    vec3 p;
    vec3 q;
    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)
    {
        p = t * normalize(vec3(I + I, 0.0) - iResolution.xyy);
        p += sin(p * 9.0) / 9.0;
        p.z += exp(-3.0 - 3.0 * sin(T * 0.3)) / 2.0;
        p.xz *= rot(T * 0.5);
        p += vec3(0.2, -T / 3000.0, 0.6);

        v = 0.0;
        s = 1.0;

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

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

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

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