// Code by Flopine

// Thanks to wsmind, leon, XT95, lsdlive, lamogui,
// Coyhot, Alkama,YX, NuSan and slerpy 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


// References used for this isometric shader:
// https://en.wikipedia.org/wiki/Isometric_projection
// https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/orthographic-projection-matrix

#define PI 3.141592
#define TAU (2.*PI)
#define time iTime

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)));
}

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

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

float sc(vec3 p, float s)
{
    vec3 pp = p;
    p = abs(p);
    p = max(p, p.yzx);
    float d = min(p.x, min(p.y, p.z)) - s;
    return d;
    return max(d,-(abs(pp.x)-0.2));
}

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

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.));
}

float g1=0.;
float SDF (vec3 p)
{
    float dt = ((2.*PI)/4.)*(floor(time) + (pow(fract(time)+1., 6.)-1.)*exp(-15.*fract(time)));
    p.yz *= rot(-atan(1./sqrt(2.)));
    p.xz *= rot(TAU/8.);

    float per = 10.;
    p.xz = mod(p.xz, per)-per*.5;
    mo(p.xz, vec2(1.5, 2.));
    p.x -= 1.;
    mo(p.yz, vec2(1.));
    p.z += 1.;
    mo(p.xy, vec2(0.8));
    p.x -= 0.5;
    p.xz += vec2(cos(dt),sin(dt));
    float d = od(p,0.5);
    g1 += 0.01/(0.01+d*d);
    return stmin(od(p, 0.5),max(-sc(p,0.85),box (p, vec3(1.))), 0.5, 4.);
}

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

vec3 rm (inout bool hit, inout vec3 p, vec3 ro, vec3 rd)
{
    vec3 col = vec3(0.);
    float shad=0., d=0.;

    for (float i=0.; i<64.; i++)
    {
        d = SDF(p);
        if (d<0.001)
        {
            hit = true;
            shad = i/64.;
            break;
        }
        p += d*rd;
    }
    if (hit)
    {
        col = vec3(0.4,0.5,0.6);
        col *= (1.-shad);
    }
    return col;
}

void mainImage (out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = vec2(fragCoord.x / iResolution.x, fragCoord.y / iResolution.y);
    uv -= 0.5;
    uv /= vec2(iResolution.y / iResolution.x, 1);

    bool hit =  false;

	// Isometric definition of camera, thanks to moringox! <3
    vec3 ro = vec3(uv*10.,-50.),
        rd = normalize(vec3(0.,0.,1.)),
        p = ro;
    vec3 col = rm(hit,p,ro,rd);
    vec3 n = getnorm(p);

    if (hit)
    {
        p += 0.01*n;
        float fre = pow(clamp(dot(-rd,n),0.,1.),2.);
        col += rm(hit,p,ro,reflect(rd,n))*fre;
    }
    col += g1*vec3(0.8,0.1,0.01)*0.05;

    fragColor = vec4(clamp(sqrt(col),0.,1.),1.);
}
