// Code by Flopine
// Thanks to wsmind, leon, lsdlive, XT95 and lamogui for teaching me and their help


#define ITER 60.

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

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 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.*3.141592*(c*t+d));
}

float cyl (vec2 p, float r)
{
return length(p)-r;
}


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


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


float prim1 (vec3 p)
{
p.xz *= rot(p.y+iTime);
p.xz = moda(p.xz, 2.*3.141592/6.);
p.x -= .4;
return stmin(cyl(p.xz,0.1),sphe(p,0.8),0.5,5.);
}

float shape1 (vec3 p)
{
p.xy = moda(p.xy, 2.*3.141592/7.);
p.x -=5.;
return prim1(p);
}

float prim2 (vec3 p)
{
p.xz *= rot(iTime);
p.xy *= rot(iTime);
float sp = 1.;
float steps = 3.;
float _od = od(vec3(p.x-sp,p.y,p.z),1.);
float _od1 = od(vec3(p.x+sp,p.y,p.z),1.);
float _od3 = od(vec3(p.x,p.y+sp,p.z),1.);
float _od2 = od(vec3(p.x,p.y-sp,p.z),1.);
return  stmin(_od3,stmin(_od2,stmin(_od,_od1,0.5,steps),0.5,steps),0.5,steps);
}

float sdf (vec3 p)
{
float _od = prim2(p);
float per = 2.;
p.xy *= rot(p.z*0.1);
p.z = mod(p.z-per/2.,per)-per/2.;
return min(shape1(p),_od);
}


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.01,0.01,-10.+exp(-fract(iTime))); vec3 p = ro;
    vec3 dir = normalize(vec3(uv,1.));
    float shad = 0.;
    float t = 0.;

    for (float i=0.; i<ITER; i++)
    {
    float d = sdf(p);
    if (d<0.01)
    {
    shad = i/ITER;
    break;
    }
    p+=d*dir*0.5;
    }

    t = length(ro-p);
    vec3 pal = palette(abs(uv.y),
                        vec3(0.5),
                        vec3(0.5),
                        vec3(0.4),
                        vec3(0.,0.2,0.5)
                    );
    vec3 color = vec3(1.-shad)/vec3(0.7,0.5,0.5);
    color = mix(color, pal,1.-exp(-0.008*t*t));

    // Output to screen
    fragColor = vec4(pow(color,vec3(0.45)),1.0);
}
