Skip to main content
  1. Blog/

How I Made The Background

Pranav
Author
Pranav
Coding with Physics, Physics-ing with code

If you’re wondering what the moving background on the homepage is, this post is the build notes: it isn’t stock footage and it isn’t a shader, it’s a real simulation.

Short version: the background is a 2D Kolmogorov flow simulation rendered as a vorticity heatmap. The animated version is a video; the still image you see on slower connections or reduced-motion settings is a poster frame from the same render.

The homepage background video (vorticity field).

What you’re seeing
#

The colors show vorticity (how much the flow is locally spinning), computed as:

omega = dx v - dy u

Warm colors are strong positive vorticity, cool colors are strong negative vorticity. The colormap is inferno for high contrast and good visibility against the dark UI.

How it’s made
#

The render comes from the script scripts/render_bg_video_uhd.jl, built with Oceananigans.jl and GLMakie:

  • 2D periodic domain with a 16:9 aspect ratio (768 x 432 grid) so it fills the screen cleanly at 1440p.
  • A sinusoidal body force F = A sin(k y) drives the flow (classic Kolmogorov forcing).
  • A small random perturbation breaks perfect stripes so vortices can roll up.
  • Frames are recorded at 30 fps for a 15-second loop.
  • The color range is fixed per render to avoid flicker.

The output video lives at static/media/kolmogorov_1440p_lavalamp.mp4, and the fallback poster at static/media/kolmogorov_1440p_poster.png.

Why it loops nicely
#

The flow is continuously forced, so it keeps moving without obvious “start” or “end” cues. On the homepage, the loop starts at 4 seconds into the clip to avoid the initial transient, which makes the background feel more seamless.

Want the live version?
#

There’s also an optional interactive mode that streams live frames from a small Julia WebSocket server (scripts/kolmogorov_server.jl). When enabled, the background isn’t a video anymore - it’s a real-time simulation feeding the canvas. I keep that off by default for performance, but it’s fun to toggle when testing locally.

Related