#version 330 core
out vec4 FragColor;

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

mat2 shadertoyMat(float a)
{
    return mat2(cos(a + vec4(0.0, 11.0, 33.0, 0.0)));
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 R = iResolution.xy;
    float T = iTime;
    float t = 0.0;
    float v = 1.0;
    vec3 p = vec3(0.0);
    vec3 r = normalize(vec3(fragCoord * 2.0 - R.xy, R.x));
    vec4 O = vec4(0.0);

    r.xy *= shadertoyMat(T * 0.2);

    for (int i = 0; i < 100; i++)
    {
        p = t * r;
        p.xy *= shadertoyMat(p.z * 2.0 - T * 0.1);

        p += vec3(
            vec2(0.1, sin(0.0) * 0.1) *
            shadertoyMat(15.0 * sin(T * 0.02 + sin(p.x * 0.1)) * 0.5),
            T * 0.02);

        p = fract(p.zxy - 0.5) - 0.5;

        for (int j = 0; j < 10; j++)
        {
            p = abs(p.yzx);
            p *= 1.55;
            p.x -= 1.5;
        }

        v = abs(min(length(p.xz * 0.5 + p.y * 0.75), length(p.zy * 0.1 + p.y * 0.5)) + 0.01) / 500.0;
        v = max(v, 0.00001);
        t += v;

        vec3 palette = vec3(0.5, 0.4, 0.5) + vec3(0.9, 0.2, 1.5) * cos(6.2831853 * (sin(length(p * 0.030 + T)) + p.z * 0.9 + r * 0.5));
        O.rgb += exp(2.0 * palette) / v;
    }

    fragColor = tanh(O / 4e7) * 30.0;
    fragColor.a = uAlpha;
}

void main()
{
    mainImage(FragColor, gl_FragCoord.xy);
}
