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);
}