//CC0 1.0 Universal https://creativecommons.org/publicdomain/zero/1.0/
//To the extent possible under law, Blackle Mori has waived all copyright and related or neighboring rights to this work.

// polynomial smooth min (k = 0.1);
float sminCubic( float a, float b, float k )
{
    float h = max( k-abs(a-b), 0.0 )/k;
    return min( a, b ) - h*h*h*k*(1.0/6.0);
}

float torus(vec3 p, vec2 di) {
    vec2 crd = vec2(p.x, length(p.yz));
    return length(crd-vec2(0,di.x))-di.y;
}

float scene(vec3 p) {
    vec3 p1 = vec3(p.x, fract(p.yz+0.0)-0.5);
    vec3 p2 = vec3(p.x, fract(p.yz+0.5)-0.5);
    float ball = torus(p1, vec2(0.25,0.05));
    float dough = torus(p2, vec2(0.3,0.1));
    return sminCubic(sminCubic(dough,ball,0.15),-p.x,0.1);
}

#define AP(f,k) vec3(f(k[0]),f(k[1]),f(k[2]))
vec3 norm(vec3 p) {
    mat3 k = mat3(p,p,p)-mat3(0.001);
    return normalize(scene(p) - AP(scene,k));
}

float light(vec3 p, vec3 n, vec3 l) {
    float comp = dot(n,normalize(l-p));
    float power = mix(4.,9.,texture(iChannel0, mat2(cos(0.1),-sin(0.1),sin(0.1),cos(0.1))*p.yz*atan(-1.)).x);
    
    return pow(abs(comp),power)*sign(comp)*0.9+0.1;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = (fragCoord-0.5*iResolution.xy)/iResolution.y;

    vec3 cam = normalize(vec3(0.9,uv));
    vec3 init = vec3(-4.+sin(iTime/4.),0,iTime/3.);
    vec3 p = init;
    bool hit = false;
    
    for (int i = 0; i < 100; i++) {
        float dist = scene(p);
        if (abs(dist) < 0.001) { hit = true; break; }
        if (distance(init, p) > 100.) break;
        p += cam*dist;
    }
    vec3 l1 = init+vec3(2.2,cos(iTime*3.),sin(iTime*2.));
    vec3 l2 = init+vec3(2.1,cos(iTime*3.),sin(iTime*2.));
    vec3 l3 = init+vec3(2.0,cos(iTime*3.),sin(iTime*2.));
    vec3 n = norm(p);
    fragColor.xyz = hit ? vec3(light(p, n, l1), light(p, n, l2), light(p, n, l3)) : vec3(0.25);
}
