#version 330 core

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

in vec2 vTex;
out vec4 FragColor;

vec4 tanh_vec4(vec4 x)
{
    vec4 e = exp(2.0 * x);
    return (e - vec4(1.0)) / (e + vec4(1.0));
}

void mainImage(out vec4 O, in vec2 I)
{
    float t = 0.0;
    float v = 0.0;
    vec3 p;
    vec3 r = iResolution;
    // normalize ray using provided I (pixel coordinates)
    r = normalize(vec3(I + I - r.xy, r.y));

    O = vec4(0.0);

    // iterate 100 steps as in original shader
    for (int k = 0; k < 100; k++)
    {
        float ang = t * 0.1 + 11.0;
        mat2 rot = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));

        // use row-vector multiply to match `t*r.xy*mat2(...)` from original
        vec2 rotated = (t * r.xy) * rot;
        p = vec3(rotated, iTime + t * r.z);

        float a1 = abs(length(mod(p, 4.0) - 2.0) - 1.0);
        float a2 = abs(length(mod(p, 2.0) - 1.0) - 1.0);
        v = a1 + a2 + 1e-6;

        vec4 col = 2.0 * (1.0 + cos(vec4(p.x, p.y, p.z, p.z))) / v;
        O += col;

        t += v * 0.1;
    }

    // apply original dynamic range
    O = tanh_vec4(O / 1000.0);
}

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