#version 450

// Name: Just Another Cube
// Author: mrange
// URL: https://www.shadertoy.com/view/3XdXRr
// CC0: Just another cube

layout(location = 0) in  vec2 vUV;
layout(location = 0) out vec4 FragColor;

layout(set = 3, binding = 0) uniform ShadertoyUBO {
    float iTime;
    vec2  iResolution;
};

mat2 R;
float d = 1.;
float z = 0.;
float G = 9.;
float M = 1e-3;

float D(vec3 p) {
    p.xy *= R;
    p.xz *= R;

    vec3 S = sin(123. * p);

    G = min(
        G,
        max(
            abs(length(p) - .6),
            d = pow(dot(p *= p * p * p, p), .125) - .5
                - pow(1. + S.x * S.y * S.z, 8.) / 1e5
        )
    );

    return d;
}

void mainImage(out vec4 o, vec2 C) {
    vec3 p,
         O,
         r = vec3(iResolution.xy, iResolution.y),
         I = normalize(vec3(C - .5 * r.xy, r.y)),
         B = vec3(1, 2, 9) * M;

    for (
        R = mat2(cos(.3 * iTime + vec4(0, 11, 33, 0)));
        z < 9. && d > M;
        z += D(p)
    )
        p = z * I,
        p.z -= 2.;

    O = vec3(0.0);

    if (z < 9.) {
        for (int i = 0; i < 3; ) {
            r -= r;
            r[i] = M;
            O[i++] = D(p + r) - D(p - r);
        }

        z = 1. + dot(O = normalize(O), I);

        r = reflect(I, O);

        C = (p + r * (5. - p.y) / abs(r.y)).xz;

        O =
            z * z *
            (
                r.y > 0.
                ? 5e2 * smoothstep(5., 4., d = sqrt(length(C * C)) + 1.) * d * B
                : exp(-2. * length(C)) * (B / M - 1.)
            )
            + pow(1. + O.y, 5.) * B;
    }

    o = sqrt(O + B / G).xyzx;
}

void main() {
    vec2 fragCoordPixels = vUV * iResolution;
    vec4 outColor;
    mainImage(outColor, fragCoordPixels);
    FragColor = outColor;
}
