← Daily shaders~/adventure-log/shaders/2026-10-09

Bubbles on a Mild Breeze

Bubbles on a Mild BreezeIridescent bubbles drift up through a clear autumn sky, swaying on a gentle breeze. · Mostly clear 15–25°C
Sourcerising soap-bubble discs with thin-film interference cosine-palette rims, angular wobble and specular glints over warm gradient sky
2026-10-09.frag
precision mediump float;
uniform vec2 u_resolution;
uniform float u_time;

float hash(float n){ return fract(sin(n * 127.1) * 43758.5453); }

vec3 film(float t){
  return 0.5 + 0.5 * cos(6.2831 * (t + vec3(0.0, 0.33, 0.67)));
}

void main(){
  vec2 uv = gl_FragCoord.xy / u_resolution.xy;
  float asp = u_resolution.x / u_resolution.y;
  vec2 p = vec2((uv.x - 0.5) * asp, uv.y - 0.5);
  float t = u_time;
  float px = 1.0 / u_resolution.y;

  vec3 top = vec3(0.32, 0.60, 0.86);
  vec3 bot = vec3(0.97, 0.80, 0.56);
  vec3 col = mix(bot, top, smoothstep(-0.55, 0.5, p.y));

  vec2 sun = vec2(0.42 * asp, 0.30);
  float sd = length(p - sun);
  col += vec3(1.0, 0.82, 0.50) * 0.35 * exp(-sd * 4.0);
  col = mix(col, vec3(1.0, 0.93, 0.74), smoothstep(0.085, 0.07, sd));

  float gy = -0.40 + 0.025 * sin(p.x * 5.0 + t * 0.4) + 0.015 * sin(p.x * 11.0 - t * 0.3);
  float g = smoothstep(gy + 2.0 * px, gy - 2.0 * px, p.y);
  vec3 grass = mix(vec3(0.80, 0.55, 0.25), vec3(0.62, 0.40, 0.20), smoothstep(gy, gy - 0.12, p.y));
  col = mix(col, grass, g);

  for (int i = 0; i < 14; i++) {
    float fi = float(i);
    float r = 0.045 + 0.065 * hash(fi + 1.0);
    float speed = 0.025 + 0.035 * hash(fi + 2.0);
    float span = 1.2 + 2.0 * r;
    float y = mod(hash(fi + 3.0) * span + t * speed, span) - 0.6 - r;
    float x = (hash(fi + 4.0) - 0.5) * asp * 0.95 + 0.05 * sin(t * 0.35 + fi * 1.7) + 0.08 * (y + 0.6);
    vec2 d = p - vec2(x, y);
    float a = atan(d.y, d.x);
    float rr = r * (1.0 + 0.035 * sin(3.0 * a + t * 1.1 + fi));
    float l = length(d);
    float inside = smoothstep(rr, rr - 2.0 * px, l);
    float q = l / rr;
    float e = pow(clamp(q, 0.0, 1.0), 4.0) * inside;
    vec3 f = film(q * 1.2 + d.y / rr * 0.35 + t * 0.05 + fi * 0.3);
    col = mix(col, col * 0.88 + f * 0.38, e * 0.75);
    col += 0.035 * inside;
    float ring = smoothstep(3.5 * px, 1.0 * px, abs(l - rr));
    col = mix(col, f * 0.55 + 0.42, ring * 0.45);
    vec2 hp = d - vec2(-0.38, 0.40) * rr;
    hp.x *= 1.4;
    float h = smoothstep(0.24 * rr, 0.06 * rr, length(hp));
    col += vec3(1.0, 0.97, 0.90) * 0.45 * h * inside;
  }

  vec2 vc = uv - 0.5;
  col *= 1.0 - 0.25 * dot(vc, vc);
  col = min(col, vec3(0.97));
  gl_FragColor = vec4(col, 1.0);
}