Skip to content

Ferrofluid

A dish of black ferrofluid with magnets circling beneath it: glossy spikes rise and fall across the surface. Loops perfectly.

3D object, V2 Objects3DSeamless loop, verified485 lines of codev1.0.0

In Science & maths, Light, glass & shine, Liquids

Next: Soap FilmSurprise me

Ferrofluid preview
Starting live preview…
00:00:00:00 / 00:00:00:01

Live, running the real source at reduced resolution.

Your current settings go with it. Combine several clips and hand them over together from your sequence.

Effect controls

Presets

4

Magnets circling under the dish (the fixed one in the middle is extra).

A strong fixed magnet that raises a big crown in the middle.

1

The strength of the magnets: more makes wider crowns of spikes.

1

The spacing of the spikes: larger makes fewer, bigger spikes.

1
1

A whole-number factor on how fast the magnets circle.

1
5

The preview runs the same code your AI receives. These settings travel with the hand-off.

Info

What it is

The most mesmerising liquid there is: ferrofluid, a black magnetic fluid, in a glazed dish with magnets circling beneath it. Where the field is strong the surface swells and bristles into the hexagonal lattice of sharp, glossy spikes of the Rosensweig instability, thick and tall over the fixed magnet in the middle, small and fading at the edge of each moving one; where it is weak the liquid lies as a flat black mirror, rippling as the magnets pass. The black metal reflects a photo studio, so every spike carries a white line of light. Choose the look (high-key studio, midnight, neon or amber), the number of magnets, the field strength, the size and height of the spikes, the pace, the ripples and whether the camera sways round the dish.

Reuse it in your own idea

  • Music visualiser or tech backdrop: Midnight blue and pink.
  • Oddly-satisfying macro: High-key studio.
  • Science explainer on magnetism: High-key studio, five magnets.

Which part is reusable

src/ferrofluid.js is the ingredient your AI reuses. demo.js is only the example scene around it, and uses the demo harness only for the demo.

Good to know

  • The liquid is a height field: spikes are vertical cones that appear and vanish with the field, they do not lean along field lines or merge into drops.
  • The lattice is fixed to the dish, so spikes do not slide: they grow and shrink where the field passes.
  • Reflections are of the studio only: spikes do not reflect each other or the dish.

Technical details

Technical details
Implementation
Three.js 0.185.1 (WebGL) · ES module src/ferrofluid.js
Exports
  • createFerrofluid({ look?, magnets?, centre?, field?, spike?, height?, speed?, ripples?, drift?, seed? }) => { scene, camera, plan, setSize(width, height), update(time, loopSeconds), dispose() }
  • createBloomPass(renderer, { width, height, glow?, exposure?, grain? }) => { render(scene, camera, output?), dispose() }
  • planMagnets({ count?, centre?, seed? }) => magnet[]
  • LOOKS: { studio, midnight, neon, amber }
Dependencies (exact)
  • three@0.185.1 (source) — Renderer, the displaced surface, the dish and the bloom targets.
  • apw-runtime@1.0.0 (demo) — Demo harness.
How it fits a scene

Coordinates: The liquid lies in the plane y = 0 inside a dish of radius 3 centred on the origin; the camera orbits a point just above it at an elevation of about 45°.

Lighting: The studio is a function of the reflected direction: a dark dome with four softboxes; the black liquid is a Fresnel mirror of it, the glazed dish takes a diffuse term and the same reflection.

Timing: update(time, loopSeconds) sets the loop phase; frames render in any order.

Output
1080×1080, 30 fps, 16 s · procedural (computed from the frame number) · seamless loop — Every magnet goes round its circle a whole number of times per loop and its radius, its strength and the ripples running out from it are sines of whole cycles, and the camera sway is a sine of the loop, so the last frame meets the first.
Tested
Rendered 480 frames on 2026-10-05 in Chrome 154.0.8037.97 headless on Linux 7.0.0-38-generic (x64), Node 22.14.0 (WebGL 2 via SwiftShader (software)). Same frame twice from fresh pages: identical. Loop: Frame 0 vs end state (progress 1): mean |Δ| 0.0000, max |Δ| 0 of 255.
Performance
A 440 × 440 grid (about 194 000 vertices) displaced in the vertex shader, evaluating the height three times per vertex, and a small bloom with an anti-aliased target. About 16 ms a frame at 1080p on an integrated Intel GPU. Software WebGL (no GPU) renders in a few seconds a frame.
Export a video yourself
Download the source, then in the folder: npm install npm run render -- ferrofluid/1.0.0 --out my-video.mp4Needs Node 18+, ffmpeg and Chrome/Chromium. Add --params my-settings.json (from Copy settings) for your own settings.
Version
1.0.0 · sha256:e7d4e0a9d421a044…
Files
License
MIT. Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder. License details
Provenance
Adapted from the owner's threejs-sketches/liquid-fluid/magnetic-ferrofluid (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original scene: a Rosensweig lattice of spikes whose height follows a dipole-like field of magnets on closed whole-turn paths, a fine displaced grid with analytic normals, a procedural softbox studio reflected in the black liquid, a glazed dish and the frame/time contract.
BinMore like this

Soap Film

3D object3DSeamless loop12 seconds