Gallery

Smooth-Min Spheres

Live parameters

Blend
0.40
Geometry
0.50
Motion
1.00
Light
-0.59
0.80
Color
GLSL source
#define SMOOTHNESS_K 0.4
#define SPHERE_R 0.5
#define ORBIT_SPEED 1.0
#define LIGHT_ANGLE -0.588
#define LIGHT_ELEVATION 0.8
const vec3 PALETTE_A = vec3(0.5, 0.5, 0.5);
const vec3 PALETTE_B = vec3(0.5, 0.5, 0.5);
const vec3 PALETTE_C = vec3(1.0, 1.0, 1.0);
const vec3 PALETTE_D = vec3(0.0, 0.31831, 0.63662);

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

float smin(float a, float b, float k) {
  float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
  return mix(b, a, h) - k * h * (1.0 - h);
}

float map(vec3 p) {
  float t = iTime * ORBIT_SPEED;
  float d = sdSphere(p - vec3(sin(t)*0.6, cos(t*1.2)*0.4, 0.0), SPHERE_R);
  d = smin(d, sdSphere(p - vec3(cos(t*0.8)*0.7, sin(t*1.1)*0.5, sin(t)*0.3), SPHERE_R * 0.8), SMOOTHNESS_K);
  d = smin(d, sdSphere(p - vec3(sin(t*1.4)*0.5, -0.3, cos(t)*0.5), SPHERE_R * 0.7), SMOOTHNESS_K);
  return d;
}

vec3 normal(vec3 p) {
  vec2 e = vec2(0.001, 0.0);
  return normalize(vec3(
    map(p + e.xyy) - map(p - e.xyy),
    map(p + e.yxy) - map(p - e.yxy),
    map(p + e.yyx) - map(p - e.yyx)
  ));
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
  vec3 ro = vec3(0.0, 0.0, -2.5);
  vec3 rd = normalize(vec3(uv, 1.2));
  float t = 0.0;
  vec3 col = vec3(0.05, 0.05, 0.08);
  for (int i = 0; i < 80; i++) {
    vec3 p = ro + rd * t;
    float d = map(p);
    if (d < 0.001) {
      vec3 n = normal(p);
      vec3 l = normalize(vec3(cos(LIGHT_ANGLE) * 0.7211, LIGHT_ELEVATION, sin(LIGHT_ANGLE) * 0.7211));
      float diff = max(dot(n, l), 0.0);
      float spec = pow(max(dot(reflect(-l, n), -rd), 0.0), 32.0);
      vec3 base = PALETTE_A + PALETTE_B * cos(6.28318 * (PALETTE_C * (vec3(iTime * 0.5) + p.xyx) * 0.15915 + PALETTE_D));
      col = base * (0.2 + 0.8 * diff) + vec3(spec);
      break;
    }
    if (t > 10.0) break;
    t += d;
  }
  fragColor = vec4(col, 1.0);
}