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

#define T (iTime*6.0 + 2.0 * sin(0.6 * iTime))

#define P(z) vec3(cos((z) *  0.03) * 16.0, \
                 cos((z) *  0.1) * 2.0, (z))

float lights;

float light(vec3 p) {
    return length(p - vec3(
            p.x + (sin(p.z * 0.3) * 0.2),
            p.y,
            2.0 + T));
}

#define MENGERLAYER(scale, minmax, hole) \
    s /= (scale), \
    p = abs(fract(q/s)*s - s*0.5), \
    d = minmax(d, min(max(p.x, p.y), min(max(p.y, p.z), max(p.x, p.z))) - s/(hole))

float fractal(vec3 q) {
    vec3 p;
    float s = 4.0;
    float d = 9e9;
    MENGERLAYER(1.0, min, 4.0);
    MENGERLAYER(4.0, max, 3.5);
    return d;
}

float map(vec3 p) {
    float s, l;
    l = light(p) - 0.01;
    s = max(1.0 - abs(p.x), 1.0 - abs(p.y));
    s = min(s, fractal(p));
    lights += 0.1 / max(l, 0.001);
    return s;
}

void mainImage(out vec4 o, in vec2 u) {
    float s = 0.0;
    float d = 0.0;
    float i = 0.0;

    vec3 c = vec3(0.0);
    vec3 r = iResolution;
    u = (u - r.xy / 2.0) / r.y;

    // cinema bars
    //if (abs(u.y) > 0.375) { o = vec4(0.0); return; }

    // camera movement
    u += vec2(cos(T * 0.2) * 0.1, cos(T * 0.1) * 0.05);

    vec3 ro = P(T);
    vec3 p, D = vec3(u, 1.0);

    for (; i++ < 24.0 && d < 2e1; c += vec3(2.0, 1e1, 4.0) / s + 6e1 * vec3(2.0, 1.0, 8.0) * lights / d)
    {
        p = ro + D * d;
        p.xy -= P(p.z).xy;
        d += s = 0.03 + abs(map(p));
    }

    o.rgb = tanh(c * c / 2e7);
}

void main() {
    vec2 fragCoord = vUV * iResolution.xy;
    mainImage(FragColor, fragCoord);
    FragColor.a *= uAlpha;
}
