// Code by Flopine
// Thanks to wsmind, leon, lsdlive, lamogui, XT95 and Coyhot for teaching me <3
// cookie collective rulz!

#define ITER (64.)
#define PI (3.141592)
#define time (iTime*0.5)


mat2 rot(float a)
{return mat2(cos(a),sin(a),-sin(a),cos(a));}

vec2 moda (vec2 p, float per)
{
    float a = atan(p.y,p.x);
    float l = length(p);
    a = mod(a-per/2.,per)-per/2.;
    return vec2(cos(a),sin(a))*l;
}

float smin( float a, float b, float k )
{
    float res = exp( -k*a ) + exp( -k*b );
    return -log( res )/k;
}

float stmin(float a, float b, float k, float n)
{
    float st = k/n;
    float u = b-k;
    return min(min(a,b), 0.5 *(u+a+abs(mod(u-a+st,2.*st)-st)));
}

vec3 palette (float t, vec3 a, vec3 b, vec3 c, vec3 d)
{return a+b*cos(2.*PI*(c*t+d));}

float odile (vec3 p, float d)
{return dot(p, normalize(sign(p)))-d;}

float torus (vec3 p, vec2 d)
{
    vec2 q = vec2(length(p.xz)-d.x,p.y);
  	return length(q)-d.y;
}

float prim1 (vec3 p)
{
    float steps = 3.;
	float t1 = torus(p, vec2(1.5,.15));
    float od = odile(p,.8);
    p.yz *= rot(PI/2.);
    float t2 = torus(p,vec2(1.6,0.15));
    return stmin(od,stmin(t1,t2, 0.5, steps),0.5,steps);
}

float fractal(vec3 p)
{
    float prim = prim1(p);
    float prout = .3;
    for (int i = 0; i<5; i++)
    {
        prout += .4;
        p.xz *= rot(sin(iTime*prout));
        p.xy = moda(p.xy, 2.*PI/5.);
        p.x -= 4.;
      	prim = smin(prim, prim1(vec3(p.x, p.yz*rot(PI/4.))), 2.);  
    }
    return prim;
}


vec4 SDF(vec3 p)
{
  	p.xz *= rot(time);
    p.yz *= rot(time);
    p.y += sin(p.x+iTime*3.)*length(p)*0.1;
    float d = fractal(p);
    return vec4(d, p);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = 2.*(fragCoord/iResolution.xy)-1.;
	uv.x *= iResolution.x/iResolution.y;
    
    vec3 ro = vec3(0.001,0.001,-15.); vec3 p = ro;
    vec3 dir = normalize(vec3(uv,1));
    
    float shad = 0.;
    float t = 0.;
    float tmax = 100.;
    vec3 c = vec3(0.);
    
    for (float i = 0.; i<ITER; i++)
    {
        float d = SDF(p).x;
        t += d;
        if (d<0.001 || t>tmax)
        {
            shad = i/ITER;
            break;
        }
        p+= d*dir*0.8;
    }                 
    vec3 pal = palette (length(SDF(p).yzw),
                        vec3(0.2,0.6,0.3),
                        vec3(0.5,0.1,0.5),
                        vec3(.08),
                        vec3(0.,0.5,0.1));
    if (t<tmax) c = vec3(1.-shad)*pal*1.5;
	c = mix(c, vec3(0.5,0.4,0.2)*0.35, 1.-(exp(-.002*t*t)));
    
    // Output to screen
    fragColor = vec4(c,1.0);
}
