0.00
60.0 fps

Boing

classic..not

Log in to post a comment.

#version 300 es
precision highp float;

uniform float iTime;
uniform vec2  iResolution;
out vec4 fragColor;

#define PI         3.14159265359
#define MAX_STEPS  100
#define MAX_DIST   50.0
#define SURF_DIST  0.001

// triangular wave in [0,1]
float tri(float t) {
    return abs(mod(t, 2.0) - 1.0);
}

// SDFs
float sdSphere(vec3 p, vec3 c, float r) {
    return length(p - c) - r;
}
// plane at y = -1
float sdPlane(vec3 p) {
    return p.y + 1.0;
}

// scene‐map: sphere + finite floor
float mapScene(vec3 p, out int objID) {
    float d = MAX_DIST;
    objID = -1;
    // bouncing sphere
    float hx = tri(iTime * 0.5);
    float hy = tri(iTime * 0.7);
    vec3 center = vec3(
      mix(-1.5, 1.5, hx),
      mix(-0.5,  1.5, hy),
      0.0
    );
    float ds = sdSphere(p, center, 0.75);
    d = ds; objID = 1;

    // finite floor (disk radius = 5.0)
    float floorRadius = 5.0;
    float rad = length(p.xz);
    if (rad < floorRadius) {
        float dp = sdPlane(p);
        if (dp < d) {
            d = dp;
            objID = 0;
        }
    }

    return d;
}

// numerical normal
vec3 getNormal(vec3 p) {
    vec2 e = vec2(0.001, 0.0);
    int tmp;
    return normalize(vec3(
      mapScene(p + e.xyy, tmp) - mapScene(p - e.xyy, tmp),
      mapScene(p + e.yxy, tmp) - mapScene(p - e.yxy, tmp),
      mapScene(p + e.yyx, tmp) - mapScene(p - e.yyx, tmp)
    ));
}

// ray‐march
vec3 rayMarch(vec3 ro, vec3 rd, out int objID) {
    float t = 0.0;
    objID = -1;
    for (int i = 0; i < MAX_STEPS; i++) {
        vec3 p = ro + rd * t;
        float dist = mapScene(p, objID);
        if (dist < SURF_DIST) return p;
        if (t > MAX_DIST) break;
        t += dist;
    }
    return ro + rd * t;
}

// simple Phong
vec3 phong(vec3 p, vec3 n, vec3 v) {
    vec3 Lpos = vec3(5.0, 5.0, -5.0);
    vec3 L    = normalize(Lpos - p);
    float dif = max(dot(n, L), 0.0);
    vec3 R    = reflect(-L, n);
    float spec = pow(max(dot(R, v), 0.0), 32.0);
    return vec3(0.2) + dif * vec3(1.0) + spec * vec3(1.0);
}

// sky gradient
vec3 skyColor(vec3 rd) {
    // horizon is where rd.y = 0
    float t = clamp(rd.y * 0.5 + 0.5, 0.0, 1.0);
    vec3 hor = vec3(0.8, 0.9, 1.0);
    vec3 zen = vec3(0.2, 0.5, 0.9);
    return mix(hor, zen, t);
}

// rotating checker on the ball
vec3 checker(vec3 p, vec3 center) {
    vec3 d = normalize(p - center);
    float spin = iTime * 2.0;
    float cs = cos(spin), sn = sin(spin);
    vec3 d2 = vec3(cs * d.x - sn * d.z, d.y, sn * d.x + cs * d.z);
    float u = atan(d2.z, d2.x) / (2.0 * PI) + 0.5;
    float v = acos(d2.y) / PI;
    float tile = mod(floor(u * 8.0) + floor(v * 8.0), 2.0);
    return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), tile);
}

void main() {
    // uv + camera
    vec2 uv = (gl_FragCoord.xy / iResolution.xy) * 2.0 - 1.0;
    uv.x *= iResolution.x / iResolution.y;
    vec3 ro = vec3(0.0, 0.0, -3.0);
    vec3 rd = normalize(vec3(uv, 1.0));

    int obj;
    vec3 hit = rayMarch(ro, rd, obj);
    vec3 vDir = normalize(-rd);
    vec3 col;

    if (obj == 1) {
        // ball
        vec3 n = getNormal(hit);
        float hx = tri(iTime * 0.5);
        float hy = tri(iTime * 0.7);
        vec3 center = vec3(
          mix(-1.5, 1.5, hx),
          mix(-0.5,  1.5, hy),
          0.0
        );
        vec3 base = checker(hit, center);
        col = base * phong(hit, n, vDir);
    }
    else if (obj == 0) {
        // floor (finite disk)
        vec3 n    = vec3(0.0, 1.0, 0.0);
        float c   = mod(floor(hit.x) + floor(hit.z), 2.0);
        vec3 base = mix(vec3(0.1), vec3(0.8), c);
        col = phong(hit, n, vDir) * base;
    }
    else {
        // sky beyond the disk
        col = skyColor(rd);
    }

    fragColor = vec4(col, 1.0);
}