#version 330 core
out vec4 FragColor;
in vec2 vUV;

uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;

#define P(z) vec3(sin((z) * .15) * 9., cos((z) * .25) * 7., (z))
#define R(a) mat2(cos((a) + vec4(0, 33, 11, 0)))

bool invalidFloat(float v)
{
    return isnan(v) || isinf(v);
}

bool invalidVec3(vec3 v)
{
    bvec3 bad = bvec3(isnan(v.x) || isinf(v.x), isnan(v.y) || isinf(v.y), isnan(v.z) || isinf(v.z));
    return any(bad);
}

void mainImage(out vec4 o, in vec2 u)
{
    vec3 r = iResolution;
    vec3 Z;
    vec3 X;
    vec3 D;
    vec3 p;
    vec3 q;
    vec3 ro = P(iTime * 3.08);

    float d = 0.0;
    float s = 0.0;
    float i = 0.0;
    float j;
    float l = 1.0;
    float w;
    float t = iTime;

    o = vec4(0.0);

    Z = normalize(P(t * 0.08 + 5.0) - ro);
    X = normalize(vec3(Z.z, 0.0, -Z.x));
    D = vec3(R(sin(t * 0.16) * 0.4) * ((u - r.xy * 0.5) / r.y), 1.2) * mat3(-X, cross(X, Z), Z);

    for (; i < 110.0; i += 1.0)
    {
        p = q = ro + D * d;
        p += cos(t + p.y * 0.8 + p.x + p.zxy) * 0.2;
        s = dot(abs(p - floor(p) - 0.5), vec3(0.4));

        p = q;
        p.xy += vec2(cos(t * 0.7 + p.z * 0.4), sin(t * 0.6 + p.z * 0.5));

        w = 1.0;
        for (j = 0.0; j < 8.0; j += 1.0)
        {
            p.xy *= R(t * 0.1);
            p = abs(p) - 0.4;
            p.xz *= R(t * 0.4);
            l = 2.4 / max(dot(p, p), 0.01);
            p *= l;
            w *= l;
        }

        float distFractale = length(p) / max(w, 0.0001);
        s = min(s, distFractale);

        float distTunnel = 0.15 - length(q.xy - P(q.z).xy);
        float stepSize = max(max(distTunnel, s), 0.001);
        d += stepSize;

        float denom = d * s;
        if (abs(denom) < 0.001)
        {
            denom = denom < 0.0 ? -0.001 : 0.001;
        }

        vec3 contrib = (cos(p.zxy * 0.5 + t) * 0.008) / denom;
        if (invalidFloat(d) || invalidFloat(s) || invalidVec3(p) || invalidVec3(q) || invalidVec3(contrib))
        {
            break;
        }

        o.rgb += clamp(contrib, vec3(-2.0), vec3(2.0));
    }

    if (invalidVec3(o.rgb))
    {
        o.rgb = vec3(0.0);
    }
    o = tanh(o * o);
}

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