Log in to post a comment.

#version 300 es
precision highp float;

uniform float iTime;
uniform vec2  iResolution;

in vec2 vScreen;

out vec4 fragColor;


float sphereSdf(vec3 p, float r) {
    return length(p) - r;
}

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


float opSmoothUnion( float d1, float d2, float k )
{
    float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
    return mix( d2, d1, h ) - k*h*(1.0-h);
}

float sdf(vec3 p, float t) {
    t *= 4.;
    float ang = t + 0.4 * cos(t);
    return opSmoothUnion(
        sphereSdf(p - vec3(2.0 * cos(ang), 2.0 * sin(ang), 3), 1.0),
        sdRoundBox(p - vec3(0, 0.3 * sin(t + 1.3), 4), vec3(1, 1, 1), 0.2),
        1.5
    )
    + 0.04 * pow(0.5 + 0.5 * cos(t - 1.6), 4.0)
      * (sin(13.0 * p.x - p.y * 8.) + sin(7. * p.y + 10. * p.x));
}

vec3 gradient(vec3 p, float t) {
    float h = 0.001;
    return vec3(
        sdf(p + vec3(h, 0, 0), t) - sdf(p - vec3(h, 0, 0), t),
        sdf(p + vec3(0, h, 0), t) - sdf(p - vec3(0, h, 0), t),
        sdf(p + vec3(0, 0, h), t) - sdf(p - vec3(0, 0, h), t)
    ) / h;
}

vec3 rainbow(float r, int n) {
    //r /= 6.28318530718;
    r = floor(float(n) * r) / float(n);
    r *= 6.28318530718;
    return vec3(
        0.5 * sin(r + 0.000 - 0.0 * iTime) + 0.5, 
        0.5 * sin(r + 2.094 - 0.0 * iTime) + 0.5, 
        0.5 * sin(r + 4.188 - 0.0 * iTime) + 0.5
    );
}

vec3 getColorAtTime(float t, int iterationCount) {
    vec3 p = vec3(0, 0, -1);
    vec3 dir = normalize(vec3(vScreen.x, vScreen.y, 0) - p);
    
    float s = 0.0;
    for (int i=0; i<iterationCount; i++) {
        float d = sdf(p, t);
        p += d * dir;
        s += d;
        
        if (d < 0.001 || s > 1000.0) break;
    }
    
    vec3 color;
    
    float r = length(vScreen);
    if (s > 1000.0) {
        return vec3(0);
    }
    vec3 lightPos = vec3(5, 5, 1);
    
    vec3 N = normalize(gradient(p, t));
    vec3 L = normalize(lightPos - p);  // dir from pos to light
    vec3 R = reflect(-L, N);
    float diff = max(dot(N, L), 0.0);
    float spec = pow(max(dot(-dir, R), 0.0), 40.0);
    
    vec3 diffColor = rainbow(0.73-diff, 8);
    vec3 ambient = diffColor * 0.2;
    
    return ambient
        + diffColor// * diff
        + spec;
}

void main() {
    float delay = 0.02;
    vec3 color =
          0.6 * getColorAtTime(iTime, 200)
        + 0.2 * min(vec3(0.4), getColorAtTime(iTime - 1. * delay, 50))
        + 0.2 * min(vec3(0.4), getColorAtTime(iTime - 2. * delay, 50));
    fragColor = vec4(color, 1.0);
}