#define time iTime

// #define SPEED 15.
#define SPEED 15.
#define FLOOR 0
#define SPH 1
#define CAP 2
#define EXTR 3
#define INF 4

int hit = FLOOR;

mat2 rot2d(float a) {
    float c = cos(a), s = sin(a);

    return mat2(c, s, -s, c);
}

vec3 kifs(vec3 p) {
    float r = .7;
    float s = 2.;

    for (float i = 0.; i < 4.; i++) {
        p.xy *= rot2d(time * .7);
        p.yz *= rot2d(time * .5 - i);
        p = abs(p);
        p -= s;
        s *= r;
    }

    return p;
}

float sph(vec3 p, float r) {
    return length(p) - r;
}

float tube(vec3 p, vec3 a, vec3 b, float r) {
	vec3 ab = b - a;
	vec3 ap = p - a;
	float t = dot(ab, ap) / dot(ab, ab);
	vec3 c = a + ab * t;

	return length(p - c) - r;
}

float cap(vec3 p, vec3 a, vec3 b, float r) {
	vec3 ab = b - a;
	vec3 ap = p - a;
	float t = dot(ab, ap) / dot(ab, ab);
	t = clamp(t, 0., 1.);
	vec3 c = a + ab * t;

	return length(p - c) - r;
}


vec3 rep(vec3 p, vec3 r) {
    return mod(p, r) - .5 * r;
}

float map(vec3 p) {
    p.xy *= rot2d(p.z / 70.);
//    p = rep(p, vec3(0., 0, 100.));
    p = rep(p, vec3(0., 0, 40.));
    vec3 pkifs = kifs(p);
    float d = 5000.;

    hit = FLOOR;
  	float dsph = sph(pkifs - vec3(2, 0, 0), 1.);
    d = min(d, dsph);
    hit = (d == dsph) ? SPH : hit;
    float dtube = tube(pkifs, vec3(0, 1, 0), vec3(2, 1, 0), .5);
    d = min(d, dtube);
    hit = (d == dtube) ? CAP : hit;
    float dextr = -tube(p, vec3(0, 0, -1), vec3(0, 0, 0), 2.);
    d = max(d, dextr);
    hit = (d == dextr) ? EXTR : hit;

    return d;
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = vec2(fragCoord.x / iResolution.x, fragCoord.y / iResolution.y);
    uv -= 0.5;
    uv /= vec2(iResolution.y / iResolution.x, 1);

    vec3 col = vec3(0);

    vec3 ro = vec3(0, 0, -30. + time * SPEED);
    vec3 rd = normalize(vec3(uv.x, uv.y, 1));

    vec3 p = ro;
    float d = 0.;
    for (int i = 0; i < 100; i++) {
		float ds = map(p);

        if (ds < .01 || ds > 100.) {
            break;
        }
        if (ds > 100.) {
            hit = INF;
        }
        p += .7 * ds * rd;
    }

    col = vec3(length(p - ro) * .1);
    vec2 e = vec2(0.01, 0);

    vec3 n = normalize(map(p) - vec3(
        map(p - e.xyy),
        map(p - e.yxy),
        map(p - e.yyx)
	));

    vec3 lp = vec3(0, 0, -30. + time * SPEED);
    float dif = dot(n, normalize(lp - p));

//    map(p);
    col = vec3(0, 0, 1);
    if (hit == SPH) {
        col = vec3(0.306, 0.21 + .3 * (.5 * sin(3. * time) + 0.5), .43);
    }
    if (hit == CAP) {
//        col = vec3(201. /255., 122. / 255., 30. / 255.);
        col = vec3(1);
    }
    if (hit == EXTR) {
//        255, 182, 71
		col = vec3(255. / 255., 182. / 255., 71. / 255.);
//        col = vec3(1., 0., 0.);
    }
    if (hit == INF) {
        col = vec3(1);
    }
    col *= dif;

    fragColor = vec4(col,1.0);
}
