#version 330 core

#define P(z) vec3(cos((z)*.021)*64.,cos((z)*.016)*64., z)

// MENGERLAYER macro: multiple operations in sequence
#define m(f, h)\
    s /= (f), \
    p = abs(fract(q/s)*s - s*.5), \
    d = min(d, min(max(p.x * .8, p.y), min(max(p.y, p.z), max(p.x, p.z*.7))) - s/(h))

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

out vec4 FragColor;

void mainImage(out vec4 o, vec2 u) {
    float i, T = iTime * 6.0, d, s;
    vec3  c, r = iResolution;
    mat2 rot = mat2(cos(cos(T*.1)*.7+vec4(0,33,11,0)));

    u = (u + u - r.xy) / r.y;

    vec3  q, p = P(T*4.0),
          Z = normalize(P(T*4.0+2.0) - p),
          X = normalize(vec3(Z.z, 0.0, -Z.x)),
          D = vec3(rot*u, 1.0) * mat3(-X, cross(X, Z), Z);

    for(; i++ < 64.0;
        c += 3e1*d/s + 1e2*s
    )
        q = p += D * s * .5,
        d = .1, s = 8e1,
        m(2., 4.),
        m(cos(q.z*.3) > .3 ? 1. : 6., 3.),
        m(9., 4.),
        p = q - P(q.z),
        s = max(2e1 - length(p.xy), .05 + .6*abs(d)),
        p = q;

    o.rgb = tanh(c/1e4)
          + .2*dot(u,u)
          + abs(vec3(1,2,3) / dot(cos(.2*T+p*.1),vec3(4e1)));
    o.a = 1.0;
}

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