// Code by Flopine

// Thanks to wsmind, leon, XT95, lsdlive, lamogui, 
// Coyhot, Alkama,YX, NuSan, slerpy, wwrighter 
// BigWings, FabriceNeyret and Blackle for teaching me

// Thanks LJ for giving me the spark :3

// Thanks to the Cookie Collective, which build a cozy and safe environment for me 
// and other to sprout :)  
// https://twitter.com/CookieDemoparty


#define PI acos(-1.)
#define TAU (2.*PI)

#define rot(a) mat2(cos(a),sin(a),-sin(a),cos(a))
#define crep(p,c,l) p-=c*clamp(round(p/c),-l,l)
#define pal(c,t,d) (vec3(.5)+vec3(.5)*cos(TAU*(c*t+d)))

#define t (iTime*2.)


struct obj{
    float d;
    vec3 c;
};

void mo(inout vec2 p, vec2 d)
{
    p = abs(p)-d;
    if (p.y>p.x) p=p.yx;
}

obj minobj (obj a, obj b)
{
    if (a.d<b.d) return a;
    else return b;
}

float box (vec3 p, vec3 c)
{
    vec3 q = abs(p)-c;
    return min(0., max(q.x, max(q.y, q.z)))+length(max(q,0.));
}

obj prim1 (vec3 p, float variation, bool inver)
{
    float per = 0.7;
    mo(p.xz, vec2(variation));
    p.z -= inver ? t : -t;   
    float id = floor(p.z/per);
    p.z = mod(p.z,per)-per*.5;
    float d = box(p,vec3(1.,0.05,0.3));
    
    return obj(d, pal(vec3(0.1), id, vec3(0.8,0.2,0.65)));
}

obj SDF (vec3 p)
{
    p.yz *= rot(-atan(1./sqrt(2.)));
    p.xz *= rot(PI/4.);
    
    crep(p.y, 18., 1.);   
    mo(p.xy,vec2(2.));
    obj B = obj(box(p-vec3(0.19),vec3(0.05,0.1,1e10)), vec3(1.));
    
    obj O = obj(1e10, vec3(0.));
    float var = 0.3;
    bool inv = false;
    for (int i=0; i<3; i++)
    {
        O = minobj(O, prim1(p, var, inv));
        var += 5.; 
        inv = inv ? false : true;
    }
    
    return minobj(O, B);
}

vec3 getnorm (vec3 p)
{
    vec2 eps = vec2(0.001,0.);
    return normalize(SDF(p).d-vec3(SDF(p-eps.xyy).d,SDF(p-eps.yxy).d,SDF(p-eps.yyx).d));
}

float ao (float e, vec3 p, vec3 n)
{return clamp(SDF(p+e*n).d/e,0.,1.);}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (2.*fragCoord-iResolution.xy)/iResolution.y;
  
    vec3 ro=vec3(uv*6.,-50.), rd=vec3(0.,0.,1.),p=ro,
    col=vec3(0.), l=normalize(vec3(1.,3.,-1.));
    
    bool hit=false; obj O;
    
    for(float i=0.;i<64.;i++)
    {
        O = SDF(p);
        if(O.d<0.001)
        {
            hit=true; break;
        }
        p += O.d*rd;
    }

    if (hit)
    {
        vec3 n = getnorm(p);
        float light = dot(n,l)*.5+.5; 
        float AO = ao(0.1, p, n)+ao(0.25, p, n)+ao(0.4, p, n);
        col = O.c*light*AO/3.;
    }
    
    fragColor = vec4(sqrt(col),1.0);
}
