#version 330 core

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

out vec4 FragColor;

void mainImage(out vec4 O, in vec2 fragCoord)
{
    // Initialize
    O = vec4(0.0);
    float t = 0.0;
    float v = 0.0;

    // iterate 50 steps
    for (int ii = 0; ii < 50; ++ii)
    {
        float i = float(ii);

        // Ray position: note fragCoord passed in pixels
        vec3 p = t * normalize(vec3(fragCoord + fragCoord, 1.0) - iResolution.xyy);

        // Rotation of xy coordinates based on distance travelled
        // original used mat2(cos(t*.15+vec4(0,11,33,0))) - approximate with four cos values
        float c0 = cos(t * 0.15 + 0.0);
        float c1 = cos(t * 0.15 + 11.0);
        float c2 = cos(t * 0.15 + 33.0);
        float c3 = cos(t * 0.15 + 0.0);
        mat2 m = mat2(c0, -c1, c2, c3);
        p.xy *= m;

        // Move forward
        p.z -= iTime;

        // Coordinate repetition
        p = mod(p, 4.0) - 2.0;

        // Density from mix between sphere and line sdf based on distance travelled
        v = mix(abs(length(p) - 1.0), length(p.xz), 0.5 - 0.5 * cos(t)) + 0.01;

        // Travel forwards based on density
        t += v * 0.3;

        // Color accumulation based on density and distance travelled
        O += exp(sin(t + vec4(0.0, 2.0, 4.0, 0.0))) / v;
    }

    // Tone mapping
    O = tanh(O / 200.0);
}

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