#define AA 4.
#define NUM_STRIPES 10.
#define PERIOD 10.
#define COLOR vec3(1., .9, .75)

#define MAX_STEPS 100
#define NEAR .001
#define FAR 5.
#define PI 3.14159265359

vec3 hash(float p) {
    return fract(cos(p) * vec3(12345.6, 23456.7, 34567.8));
}

void tRotate(inout vec2 p, float angle) {
    float s = sin(angle), c = cos(angle);
	p *= mat2(c, -s, s, c);
}

float sdTorus(vec3 p, float r1, float r2) {
    return length(vec2(length(p.xz) - r1, p.y)) - r2;
}

float map(vec3 p) {
    return sdTorus(p.xzy, 1., .2);
}

float trace(vec3 o, vec3 r) {

    float t = 0.;
    for (int i = 0; i < MAX_STEPS; ++i) {
        float d = map(o + r * t);
        t += d;
        if (d < NEAR || t > FAR) break;
    }

    return t;
}

float render(vec2 fragCoord) {
	vec2 uv = (fragCoord.xy * 2. - iResolution.xy) / min(iResolution.y, iResolution.x);

    vec3 r = normalize(vec3(uv, 1.5));
    vec3 o = vec3(.1, -.1, -3);

    vec2 rot = iMouse.z > 0. ? iMouse.xy / iResolution.xy * 2. : vec2(-.2, .2);
    rot *= PI;
    tRotate(r.yz, -rot.y);
    tRotate(r.xz, -rot.x);
    tRotate(o.yz, -rot.y);
    tRotate(o.xz, -rot.x);

    float f = trace(o, r);

    if (f > FAR) return 1.;

    vec3 p = o + f * r;

    vec2 tp = atan(vec2(p.x, length(p.xy)-1.), p.yz) / PI / 2. + .5;
    tp.y = fract(tp.y + tp.x + iTime / PERIOD);
    vec3 h = hash(floor(tp.y * NUM_STRIPES));
    float offset = h.x,
          speed = ceil(h.y * PERIOD) / PERIOD,
          size = h.z * .25 + .125;

    tp.y = mod(tp.y, 1. / NUM_STRIPES) - .5 / NUM_STRIPES;
    tp.x = fract(tp.x + offset + speed * iTime) - .5;
    tp = abs(tp);

   	return step(smoothstep(size, 0., tp.x), tp.y / .4 * NUM_STRIPES);
}

void mainImage(out vec4 fragColor, vec2 fragCoord) {
    float color = 0.;

    vec2 uv = abs(fragCoord - iResolution.xy / 2.) / min(iResolution.y, iResolution.x);

    if (uv.x > .45 || uv.y > .45) {
        color = 0.;
    } else {
        for (float x = 0.; x < AA; ++x) {
            for (float y = 0.; y < AA; ++y) {
                color += render(fragCoord + vec2(x, y) / AA);
            }
        }
    	color /= AA * AA;
    }


	fragColor = vec4(mix(vec3(0), COLOR, color), 1);
}