#version 330 core

out vec4 FragColor;

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

// stable tanh for vec3 (tone mapping)
vec3 tanh3(vec3 x) {
    vec3 e = exp(clamp(2.0 * x, vec3(-20.0), vec3(20.0)));
    return (e - vec3(1.0)) / (e + vec3(1.0));
}

// menger helper (mirrors macro m(f,h))
void menger(inout float s, inout vec3 ptmp, inout float d, vec3 q, float f, float h) {
    // avoid division by zero
    float safeS = max(s, 1e-6);
    s = safeS / f;
    ptmp = abs(fract(q / s) * s - s * 0.1);
    float m1 = min(max(ptmp.x, ptmp.y), min(max(ptmp.y, ptmp.z), max(ptmp.x, ptmp.z)));
    d = min(d, m1 - s / h);
}

void mainImage(out vec4 o, in vec2 u) {
    float i = 0.0;
    float T = iTime;
    float d;
    float s = 1.275;
    float j = (.05 * dot(fract(sin(.7 * T + u)), sin(u)));
    float f;
    vec3 c = vec3(0.0);
    vec3 r = iResolution;
    vec4 rotc = cos(cos(T * .06) * 4.0 + vec4(0.0, 33.0, 11.0, 0.0));
    mat2 rot = mat2(rotc.x, rotc.y, rotc.z, rotc.w);

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

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

    // look around
    u += vec2(sin(iTime) * .5, sin(iTime * .5) * .5);

    // on-off frequency, changes color, too (use safe tanh via sinh/cosh identity approximation)
    f = (1.0 + tanh(cos(sin(T * T) * .05 + T * .3) * 3.0) * 13.0);

    // set up ray origin, dir, look-at
    vec3 q;
    vec3 p = vec3(sin((T * 32.0) * .01) * 164.0, cos((T * 32.0) * .012) * 164.0, T * 32.0);
    vec3 Z = normalize(vec3(sin((T * 32.0 + 4.0) * .01) * 164.0, cos((T * 32.0 + 4.0) * .012) * 164.0, T * 32.0 + 4.0) - p);
    vec3 X = normalize(vec3(Z.z, 0.0, -Z.x));
    vec3 D = mat3(-X, cross(X, Z), Z) * vec3(rot * u, 1.0);

    // loop
    for (int it = 0; it < 64; ++it) {
        // raymarch position: p = p + j + D * s ; q = p
        p += j + D * s;
        q = p;

        // can play with initial dist (d) and scale (s)
        d = 9e9;
        s = 2e2;

        // apply some menger layers
        vec3 ptmp = vec3(0.0);
        menger(s, ptmp, d, q, 1.0, 3.0);
        menger(s, ptmp, d, q, 2.0, 4.0);
        menger(s, ptmp, d, q, 9.0, 4.0);

        p += cos(p.yzx) * 2000.0;

        // -1 to 1 + min(gyroid, menger);
        float gy = dot(sin(q / 236.0), cos(q.yzx / 166.0));
        s = .02 + .5 * abs(sin(p.z * .2) + min(gy * 5.0, d));

        // restore p (in original macro p was modified)
        p = q;

        // add grayscale color and foggy border
        c += vec3(s + .4 * dot(u, u) - f / max(s, 1e-6));
    }

    // tanh tone map, colorize, divide brightness
    vec3 col = tanh3(vec3(f, 2.0, 0.0) * c / 1e4);
    o = vec4(col, 1.0);
}

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