#define R(p,a,r) mix(a*dot(p,a),p,cos(r)) + sin(r)*cross(p,a)
#define H(h) (cos((h)*6.3+vec3(0,23,21))*.5+.5)

vec3 color(float t) {
  vec3 c1 = vec3(1.0, 0.0, 0.0);
  vec3 c2 = vec3(0.0, 1.0, 0.0);
  vec3 c3 = vec3(0.0, 0.0, 1.0);
  vec3 c4 = vec3(1.0, 1.0, 0.0);
  vec3 c5 = vec3(1.0, 0.0, 1.0);
  vec3 c6 = vec3(0.0, 1.0, 1.0);

  float r = sin(t) * 0.5 + 0.5;
  if (r < 0.2) return mix(c1, c2, r * 5.0);
  if (r < 0.4) return mix(c2, c3, (r - 0.2) * 5.0);
  if (r < 0.6) return mix(c3, c4, (r - 0.4) * 5.0);
  if (r < 0.8) return mix(c4, c5, (r - 0.6) * 5.0);
  return mix(c5, c6, (r - 0.8) * 5.0);
}

void mainImage(out vec4 fragColor, vec2 fragCoord)
{
    fragColor = vec4(0);
    vec3 p, r = iResolution, d = normalize(vec3((fragCoord-.65*r.xy)/r.y,0.5));
    for(float i = 0., g = 0., e, s; i < 99.; ++i)
    {
        p = g * d;
        p.z -= 0.6;
        p = R(p, normalize(vec3(1,2,3)), iTime * 0.6);
        s = 4.;

        for(int j = 0; j++ < 13;)
        {
            p = abs(p);
            p = p.x < p.y ? p.zxy : p.zyx;
            s *= e = 1.8 / min(dot(p, p), 1.3);
            p = p * e - vec3(15,3,2);
        }

        g += e = length(p.xz) / s;
        fragColor.rgb += color(iTime * 0.01 + i) * mix(r / r, H(log(s)), 0.7) * 0.08 * exp(-i * i * e);
    }

    fragColor = pow(fragColor, vec4(3));
}
