/* Creative Commons Licence Attribution-NonCommercial-ShareAlike
   phreax 2021
*/

#define PI 3.141592
#define SIN(x) (sin(x)*.5+.5)
#define PHI 1.618033988749895


float tt, g_mat;
float g_gl = 0.;


// from https://mercury.sexy/hg_sdf/
#define GDFVector3 normalize(vec3(1, 1, 1 ))
#define GDFVector4 normalize(vec3(-1, 1, 1))
#define GDFVector5 normalize(vec3(1, -1, 1))
#define GDFVector6 normalize(vec3(1, 1, -1))

#define GDFVector7 normalize(vec3(0, 1, PHI+1.))
#define GDFVector8 normalize(vec3(0, -1, PHI+1.))
#define GDFVector9 normalize(vec3(PHI+1., 0, 1))
#define GDFVector10 normalize(vec3(-PHI-1., 0, 1))
#define GDFVector11 normalize(vec3(1, PHI+1., 0))
#define GDFVector12 normalize(vec3(-1, PHI+1., 0))

#define GDFVector13 normalize(vec3(0, PHI, 1))
#define GDFVector14 normalize(vec3(0, -PHI, 1))
#define GDFVector15 normalize(vec3(1, 0, PHI))
#define GDFVector16 normalize(vec3(-1, 0, PHI))
#define GDFVector17 normalize(vec3(PHI, 1, 0))
#define GDFVector18 normalize(vec3(-PHI, 1, 0))

#define fGDFBegin float d = 0.;
#define fGDF(v) d = max(d, abs(dot(p, v)));
#define fGDFEnd return d - r;


float icosahedron(vec3 p, float r) {
    fGDFBegin
    fGDF(GDFVector3) fGDF(GDFVector4) fGDF(GDFVector5) fGDF(GDFVector6)
    fGDF(GDFVector7) fGDF(GDFVector8) fGDF(GDFVector9) fGDF(GDFVector10)
    fGDF(GDFVector11) fGDF(GDFVector12)
    fGDFEnd
}

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


// by Nusan
float curve(float t, float d) {
  t/=d;
  return mix(floor(t), floor(t)+1., pow(smoothstep(0.,1.,fract(t)), 10.));
}

float box(vec3 p, vec3 r) {
    vec3 d = abs(p) - r;
    return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}

float rect( vec2 p, vec2 b, float r ) {
    vec2 d = abs(p) - (b - r);
    return length(max(d, 0.)) + min(max(d.x, d.y), 0.) - r;
}

vec3 transform(vec3 p) {

    float a = PI*.5 + iTime;
    p.xz *= rot2(a);
    p.xy *= rot2(a);

    return p;
}


float map(vec3 p) {

    vec3 bp = p;

    // rotate
    float b = PI*.5;
    p.xz *= rot2(b);
    p.xy *= rot2(b);

    // torus
    float r1 = mix(1.0, 2., SIN(tt));

    vec2 cp = vec2(length(p.xz) - r1, p.y);

    float rev = 2.5;

    // torus knots by BigWings
    float a = atan(p.z, p.x);

  cp.x -= .5;

    cp *= rot2(rev*a);
    cp = abs(cp) -.2;

    cp = abs(cp) - mix(.2, .4, SIN(tt));
    cp *= rot2(-rev*a-tt);

    cp = abs(cp) - .33*SIN(-tt*.25);

    float kn = rect(cp, vec2(mix(.07, .12, SIN(.5*tt))), .02);

    float pl = box(bp-vec3(0, 0, 1.), vec3(10, 10, .1));

    g_gl += .018/(.1+pow(abs(kn), 8.));  // glow

    p = transform(p);

    float ic = icosahedron(p, .33);

    g_mat = kn < ic ? 0. : 1.;

    float d = min(ic, kn);

    g_mat = d <  pl ? g_mat : 2.;

    d = min (d, pl);
    return .8*d;
}

// from iq
float softshadow( in vec3 ro, in vec3 rd, float mint, float maxt, float k )
{
    float res = 1.0;
    float ph = 1e20;
    for( float t=mint; t<maxt; )
    {
        float h = map(ro + rd*t);
        if( h<0.001 )
            return 0.0;
        float y = h*h/(2.0*ph);
        float d = sqrt(h*h-y*y);
        res = min( res, k*d/max(0.0,t-y) );
        ph = h;
        t += h;
    }
    return res;
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;


    vec3 ro = vec3(0, .0, -5),
         rd = normalize(vec3(uv, .7)),
         lp = vec3(-1., 4., -10);

    vec3 p = ro;
    vec3 col;

    float t, d = 0.1;

    tt = (iTime + 7.4)*.5 ;
    tt = tt+2.*curve(tt, 2.);

    float mat = 0.,
          gl  = 0.;

    for(float i=.0; i<200.; i++) {

        d = map(p);
        mat = g_mat;
        gl = g_gl;

        if(d < 0.0001 || t > 100.) break;

        t += d;
        p += rd*d;
    }
    vec2 e = vec2(0.0035, -0.0035);

    vec3 al = vec3(0.949,0.620,0.510);
    if(d < 0.001) {
         vec3 n = normalize( e.xyy*map(p+e.xyy) + e.yyx*map(p+e.yyx) +
                            e.yxy*map(p+e.yxy) + e.xxx*map(p+e.xxx));


        vec3 l = normalize(lp-p);
        float dif = max(dot(n, l), .0);
        float spe = pow(max(dot(reflect(-rd, n), -l), .0),40.);

        float sss = smoothstep(0., 1., map(p + l * .4)) / .4;
        float shd = softshadow(p, l, 0.01, 2., 15.0);

        if(mat != 2.) {
            col +=  al*mix(1., dif, .8) + .2*spe +  + .2*al*sss;
        } else {
            col = vec3(0.702,0.796,0.820);
        }
        col *= mix(.8, 1., shd);

    }


    if(mat != 1.) {
      col += (.1-.18*pow(dot(uv, uv), .2))*gl*vec3(1.000,0.714,0.522);
      col += (.08-.22*pow(dot(uv, uv), .57))*gl*vec3(1.000,0.714,0.522);
    }
    col *= mix(.1, .9, (1.5-pow(dot(uv, uv), .8)));
    col = pow(col, vec3(.6));


    // Output to screen
    fragColor = vec4(col, 1.0 - t * 0.3);
}