Caustics

코스틱

The shimmering net of light that forms when rays bend through a curved transparent surface — water, glass — and converge or spread as they land.

Also known as: Caustic pattern
···
html
<canvas id="ca-canvas"></canvas><span class="ca-cap">faked caustics · layered sine distortion</span>
css
#ca-canvas{width:100%;height:100%;display:block}
.ca-cap{position:absolute;left:0;right:0;bottom:4%;text-align:center;font-size:clamp(9px,2.4vmin,12px);color:#cfe8ffcc}
js
const canvas = document.getElementById('ca-canvas');
const ctx = canvas.getContext('2d');
function resize() {
  const r = canvas.getBoundingClientRect();
  canvas.width = Math.round(r.width);
  canvas.height = Math.round(r.height);
}
addEventListener('resize', resize); resize();

function draw(t) {
  const w = canvas.width, h = canvas.height;
  const bg = ctx.createLinearGradient(0, 0, 0, h);
  bg.addColorStop(0, '#0b2540'); bg.addColorStop(1, '#04101d');
  ctx.fillStyle = bg; ctx.fillRect(0, 0, w, h);

  ctx.globalCompositeOperation = 'lighten';
  const time = t * 0.00035;
  for (let l = 0; l < 3; l++) {
    ctx.beginPath();
    const rows = 9;
    for (let r = 0; r <= rows; r++) {
      const y0 = (r / rows) * h;
      ctx.moveTo(0, y0);
      for (let x = 0; x <= w; x += 8) {
        const n = Math.sin(x * 0.045 + time * (1.2 + l * 0.4) + r * 0.9) * 9
          + Math.sin(x * 0.018 - time * (0.7 + l * 0.3) + r * 1.6) * 13;
        ctx.lineTo(x, y0 + n);
      }
    }
    const cols = 11;
    for (let cIdx = 0; cIdx <= cols; cIdx++) {
      const x0 = (cIdx / cols) * w;
      ctx.moveTo(x0, 0);
      for (let y = 0; y <= h; y += 8) {
        const n = Math.sin(y * 0.05 - time * (1.1 + l * 0.35) + cIdx * 0.9) * 9
          + Math.sin(y * 0.02 + time * (0.6 + l * 0.25) + cIdx * 1.5) * 13;
        ctx.lineTo(x0 + n, y);
      }
    }
    ctx.strokeStyle = l === 0 ? 'rgba(120,200,255,0.3)' : l === 1 ? 'rgba(160,230,255,0.24)' : 'rgba(210,248,255,0.2)';
    ctx.lineWidth = 1.3;
    ctx.stroke();
  }
  ctx.globalCompositeOperation = 'source-over';
  requestAnimationFrame(draw);
}
requestAnimationFrame(draw);

The shimmering net on a swimming pool floor, the crescent of light beside a wine glass — both are caustics. Every ripple in water or curve in glass refracts light at a slightly different angle, so rays bunch tightly in some spots (bright lines) and spread thin in others (dark regions), producing that distinctive net pattern.

Physically accurate caustics get computed by path-tracing-style renderers using techniques like photon mapping or bidirectional path tracing — tracing light that converges after passing through a refractive surface is especially expensive. So games and real-time graphics mostly fake it: projecting a pre-rendered animated texture onto the floor, or, like this demo, layering several distorted sine waves to synthesize a similar net pattern in real time.

Renderers like Blender’s Cycles or Corona expose caustics as an option you can toggle, since turning up accuracy raises render time a lot. Keep in mind the demo’s pattern is a pure visual approximation, not a physics simulation.

When to use

Reach for it to add realism to a floor or wall near water, glass, or a gem. In real time, fake it with an approximated texture rather than a true simulation.