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

// "Revive" by @XorDev - adapted fragment

void mainImage(out vec4 O, vec2 I)
{
    // initialize accumulators to avoid NaNs
    float z = 0.0;
    float d = 1.0;
    float t = iTime;
    O = vec4(0.0);

    // precompute ray direction from frag coord
    vec3 dir = normalize(vec3(I + I, 0.0) - iResolution.xyx);

    // iterate a fixed number of steps (100)
    for (int iter = 0; iter < 100; iter++)
    {
        // sample point (from ray direction)
        vec3 p = z * dir;

        // polar coordinates and offset
        float py = p.y - 7.0;
        p = vec3(atan(py, p.x) * 3.0, p.z * 0.3, length(p.xy) - 11.0);

        // apply turbulence
        for (int k = 1; k < 9; k++)
        {
            float fk = float(k);
            p += sin(p.yzx * fk + 0.1 * z - t) / fk;
        }

        // compute distance increment
        d = length(vec4(p.z * 5.0, cos(p) - 1.0)) / 20.0;
        // guard d to avoid division by zero
        d = max(d, 1e-5);
        z += d;

        // accumulate color/brightness (use vec4 operations to match original intent)
        O += (vec4(1.2) - sin(vec4(t) + vec4(z) / vec4(8.0, 7.0, 6.0, 0.0))) / d;
    }

    // tanh tone map
    O = tanh(O / 1000.0);
}

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