#version 330 core

#define SOFTNESS 0.001
#define PASSTHROUGH 5.0
#define STEPS 100.0
#define BRIGHTNESS 15.0

uniform vec3 iResolution;
uniform float iTime;
uniform vec2 iMouse;
uniform float uAlpha;

out vec4 FragColor;

mat2 rot2D(float angle) {
    float c = cos(angle);
    float s = sin(angle);
    return mat2(c, -s, s, c);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
    vec2 m = (iMouse.xy * 2. - iResolution.xy) / iResolution.y;

    float z = 0.0; // raymarch depth
    float d = 0.0; // step dist
    float s = 0.0; // signed dist
    
    vec3 ro = vec3(0, 1.5, iTime);
    vec3 rd = normalize(vec3(uv, 1.0));
    rd.yz *= rot2D(0.8);
    rd.xy *= rot2D(sin(iTime / 2.) / 8.);
    vec3 col = vec3(0.0);
    vec3 hue = vec3(1.0, 0.6, 0.0);
    
    
    for (float i = 0.0; i < STEPS; i++) {
        vec3 p = rd * z + ro;
        
        vec3 q = p;
        
        s = 0.0 - p.y;
        
        for (float j=7.0; j > 0.001; j*= 0.4) {
            q.xz *= rot2D(2.0);
            s = max(s, j - length(mod(q, j * 2.0) - j) - 0.005);
        
        }
        
        s = max(s, -(0.8 - p.y));
        
        d = SOFTNESS + max(s, -s*PASSTHROUGH) / 4.0;
        
        z += d * 2.0;
        
        if (i == 50.0 * (STEPS / 100.)) {
           
            rd = normalize(vec3(1.0, 1.0, 1.0));
            ro = p;
            z = 0.001;
            hue = 1.0 * vec3(0.0, 0.0, 1.0);
        }
        
        if (i == 95.0 * (STEPS / 100.)) {
            rd = normalize(vec3(-1.0, -1.0, -1.0));
            ro = p;
            z = 0.001;
            hue =  vec3(1.0, 1.0, 0.0);
        }
        
        col += (1.0 / d * 0.2) * (1.0 - hue);
        
    }
    
    col *= SOFTNESS / STEPS * BRIGHTNESS;
    
    vec3 x = 1.0 - col;

    // Output to screen
    fragColor = vec4(tanh(x * x),1.0);
}

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