// right-click: pause/start animation
// drag: rotate viewport

// fragment shader
// original: https://www.shadertoy.com/view/3dXfDr

float F(in vec3 p) {
    p *= 0.5*(max(1.,10.*sin(4.0*iTime)-8.5)-max(0.,10.*cos(4.0*iTime-2.)-9.7))+0.5;
    vec3 u = p*p;
    float d = u.x+2.*u.y+u.z-1.;
    if (d>3.0) return d;
    return 4.*d*d-p.z*(5.*u.x*u.x-10.*u.x*u.z+u.z*u.z)-1.;
}
vec3 nGrad(vec3 p) {
    const float e = 1e-5;
    float a = F(p+vec3(e,e,e));
    float b = F(p+vec3(e,-e,-e));
    float c = F(p+vec3(-e,e,-e));
    float d = F(p+vec3(-e,-e,e));
    return vec3(a+b-c-d,a-b+c-d,a-b-c+d)*(.25/e);
}

const vec3 light = normalize(vec3(-0.3, 0.1, 1));

vec3 castRay(vec3 p, vec3 d) {
    float t = 8., dt;
    for (int i = 0; i < 128; i++) {
        vec3 q = p+t*d;
        dt = F(q) / length(nGrad(q));
        t += 0.5*dt;
        if (dt < .01) {
            vec3 n = normalize(nGrad(q));
            float dif = clamp(.3+.7*dot(n, light), 0., 1.);
            vec3 col = vec3(1.0,0.9,0.9)-sqrt(q.y*q.y+0.5)*vec3(0.1,0.4,0.9);
            return (0.7*dif+0.2*pow(max(dot(d, light),0.),4.)+.5)*col;
        }
        if (t > 15.) break;
    }
    vec3 col = sin(20.*d.x)+sin(20.*d.y)+sin(20.*d.z)>0.?vec3(0.6,0.8,1.0): vec3(0.8,0.6,1.0);
    t = max(dot(d,light), 0.);
    return (0.5+0.5*t)*col;
}

#define AA 1
void main() {
    float rx = iRotate.x, rz = iRotate.y;
    vec3 w = vec3(cos(rx)*vec2(-sin(rz),cos(rz)), sin(rx));
    vec3 u=vec3(-cos(rz),-sin(rz),0);
    vec3 v=cross(w,u);
    mat3 M=-mat3(u,v,w);
    vec3 pos = 10.0 * w;

    vec3 col = vec3(0.0);
    for (int i=0;i< AA;i++) for (int j=0;j< AA;j++) {
        vec3 d=M*vec3(0.5*iResolution-(gl_FragCoord.xy+vec2(i,j)/float(AA)),length(iResolution));
        col += clamp(castRay(pos,normalize(d)),vec3(0),vec3(1));
    }
    col/=float(AA*AA);

    float gma = .7;
    col.x=pow(col.x,gma),col.y=pow(col.y,gma),col.z=pow(col.z,gma);
    col = col*1.1-0.1;

    gl_FragColor = vec4(col,1.0);
}