{"id":"ferrofluid","version":"1.0.0","title":"Ferrofluid","summary":"A dish of black ferrofluid with magnets circling beneath it: glossy spikes rise and fall across the surface. Loops perfectly.","kind":"object","target":"three","collections":["satisfying","chrome-glass","hypnotic-loops"],"tags":["ferrofluid","magnetic","liquid","spikes","black liquid","magnet","macro","rosensweig","satisfying","glossy","science","loop","3d"],"loopable":true,"motion":"procedural","durationSeconds":16,"status":"published","media":{"poster":"https://aipixelwizard.com/media/ferrofluid/1.0.0/poster.webp","preview":"https://aipixelwizard.com/media/ferrofluid/1.0.0/preview.mp4","sample":"https://aipixelwizard.com/media/ferrofluid/1.0.0/sample.mp4","sampleBytes":12436992,"sampleNote":"Pre-rendered with the default settings. Customised settings must be exported locally (npm run render)."},"urls":{"page":"https://aipixelwizard.com/visuals/ferrofluid","manifest":"https://aipixelwizard.com/api/v1/visuals/ferrofluid/versions/1.0.0","agentMd":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/agent.md","files":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/","demo":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/index.html"},"description":"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.","role":"Object (3D, three.js): a hypnotic macro of a liquid for music, tech, product and \"satisfying\" content.","useCases":["A mesmerising macro backdrop for music and visualisers","A science or tech explainer on magnetism and fluids","A glossy product-style or \"oddly satisfying\" loop"],"synonyms":["magnetic liquid","magnetic fluid","black liquid metal","spiky liquid","ferro fluid","liquid magnet","rosensweig instability","magnetic spikes"],"digest":"e7d4e0a9d421a0443a6601e0feffe5fcc5192607746f1cfd7aefeb26504018eb","implementation":{"target":"three","runtime":"browser","language":"javascript","module":"esm","entry":"src/ferrofluid.js","exports":[{"name":"createFerrofluid","signature":"createFerrofluid({ look?, magnets?, centre?, field?, spike?, height?, speed?, ripples?, drift?, seed? }) => { scene, camera, plan, setSize(width, height), update(time, loopSeconds), dispose() }","description":"The dish, the table and the liquid (a finely gridded surface displaced by a vertex shader) with its own camera: render its scene with its camera after setSize and update, ideally through createBloomPass."},{"name":"createBloomPass","signature":"createBloomPass(renderer, { width, height, glow?, exposure?, grain? }) => { render(scene, camera, output?), dispose() }","description":"A small bloom with filmic tone mapping and an anti-aliased, depth-tested scene target: draws a scene to the canvas with its glow."},{"name":"planMagnets","signature":"planMagnets({ count?, centre?, seed? }) => magnet[]","description":"The magnets under the dish: radius, whole turns per loop, phase, strength, width and wobble."},{"name":"LOOKS","signature":"LOOKS: { studio, midnight, neon, amber }","description":"Backdrop, table, dish and studio softboxes (sRGB hex) for each look."}],"reusable":["src/ferrofluid.js"],"demo":"demo.js","harness":"index.html"},"dependencies":[{"id":"three","version":"0.185.1","scope":"source","reason":"Renderer, the displaced surface, the dish and the bloom targets."},{"id":"apw-runtime","version":"1.0.0","scope":"demo","reason":"Demo harness."}],"uses":[],"usedBy":[],"params":[{"key":"look","label":"Look","type":"select","default":"studio","options":[{"value":"studio","label":"High-key studio"},{"value":"midnight","label":"Midnight blue and pink"},{"value":"neon","label":"Neon cyan and magenta"},{"value":"amber","label":"Amber"}]},{"key":"magnets","label":"Magnets","help":"Magnets circling under the dish (the fixed one in the middle is extra).","type":"integer","min":2,"max":9,"step":1,"default":4},{"key":"centre","label":"Middle magnet","help":"A strong fixed magnet that raises a big crown in the middle.","type":"boolean","default":true},{"key":"field","label":"Field","help":"The strength of the magnets: more makes wider crowns of spikes.","type":"number","min":0.6,"max":1.6,"step":0.05,"default":1},{"key":"spike","label":"Spike size","help":"The spacing of the spikes: larger makes fewer, bigger spikes.","type":"number","min":0.6,"max":1.6,"step":0.05,"default":1},{"key":"height","label":"Spike height","type":"number","min":0.5,"max":1.4,"step":0.05,"default":1},{"key":"speed","label":"Pace","help":"A whole-number factor on how fast the magnets circle.","type":"integer","min":1,"max":3,"step":1,"default":1},{"key":"ripples","label":"Ripples","type":"number","min":0,"max":2,"step":0.05,"default":1},{"key":"drift","label":"Camera drift","type":"boolean","default":true},{"key":"seed","label":"Seed","type":"integer","min":1,"max":999,"step":1,"default":5}],"presets":[{"id":"default","label":"High-key studio, four magnets","params":{}},{"id":"midnight","label":"Midnight blue and pink","params":{"look":"midnight","magnets":6,"seed":12}},{"id":"neon","label":"Neon, a swarm of fine spikes","params":{"look":"neon","magnets":7,"spike":0.7,"height":0.8,"seed":3}},{"id":"amber","label":"Amber, few big spikes","params":{"look":"amber","magnets":3,"spike":1.4,"field":1.2,"seed":8}}],"output":{"width":1080,"height":1080,"fps":30,"durationSeconds":16,"posterSeconds":5,"alpha":false,"motion":"procedural","loop":{"seamless":true,"cycleSeconds":16,"method":"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."},"seed":{"param":"seed","behavior":"Seed picks each magnet's circle, direction, speed, strength and width, and the height variation of the spikes: same seed, same dance."}},"composition":{"inputs":"Time within the loop; the look, the number of magnets, the middle magnet, the field, the spike size and height, the pace, the ripples, the camera drift and the seed.","outputs":"A full frame, rendered in 3D (a displaced grid, a lathe dish and a table) with a procedural studio reflected in the liquid.","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.","compatibleWith":["chrome-material","orbit-camera","kinetic-title","number-reveal"],"notes":["The surface is a 440 × 440 grid displaced in a vertex shader: height = a swelling with the field + a spike on a hexagonal lattice (height by the field at its foot, radius up to half the lattice spacing so the cones never meet) + ripples running out from the magnets; normals come from forward differences of the same formula.","The field is a sum of bell-shaped dipole-like terms (1 + (r/w)²)^-1.5, one per magnet; spikes begin above a threshold field and grow with the field above it (a smoothstep raised to the power 1.5)."]},"reuse":["Music visualiser or tech backdrop: Midnight blue and pink.","Oddly-satisfying macro: High-key studio.","Science explainer on magnetism: High-key studio, five magnets."],"integration":{"newProject":"Create a WebGLRenderer, createFerrofluid() and createBloomPass(renderer, { width, height }); call ferro.setSize(width, height), then each frame ferro.update(time, loopSeconds) and bloom.render(ferro.scene, ferro.camera).","existingProject":"Copy src/ferrofluid.js; render ferro.scene with ferro.camera into a render target (or through the bloom pass), or add the pool mesh to your own scene (it needs a perspective camera and its own studio uniforms)."},"performance":{"notes":"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.","limits":"Software WebGL (no GPU) renders in a few seconds a frame."},"limitations":["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."],"license":{"spdx":"MIT","notice":"Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.","thirdParty":[]},"rights":{"approvedForPublicRelease":true},"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.","changelog":[{"version":"1.0.0","date":"2026-10-05","notes":"Initial release."}],"verification":{"testedOn":"2026-10-05","inputs":{"ferrofluid@1.0.0":"e7d4e0a9d421a0443a6601e0feffe5fcc5192607746f1cfd7aefeb26504018eb","three@0.185.1":"664ca387e5fab46ff2daaa6895e1d015426850891af5ea5082cbbcc3985b068c","apw-runtime@1.0.0":"5be859cdac74823ba0bcc32c6daf06688a871104d24db5d4ceaffffd84d7c40d"},"environment":"Chrome 154.0.8037.97 headless on Linux 7.0.0-38-generic (x64), Node 22.14.0","renderer":"WebGL 2 via SwiftShader (software)","width":1080,"height":1080,"fps":30,"frames":480,"renderSeconds":3796,"loopCheck":{"checked":true,"seamless":true,"maxDifference":0,"note":"Frame 0 vs end state (progress 1): mean |Δ| 0.0000, max |Δ| 0 of 255."},"determinism":{"checked":true,"identical":true},"errors":[],"media":{"poster":"/media/ferrofluid/1.0.0/poster.webp","preview":"/media/ferrofluid/1.0.0/preview.mp4","sample":"/media/ferrofluid/1.0.0/sample.mp4","sampleBytes":12436992}},"files":[{"path":"LICENSE","size":1072,"sha256":"8a5f3a96f07e11522ec4bdd0a583356f99bad1245920f9709cee09b995a45153","contentType":"text/plain; charset=utf-8","url":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/LICENSE"},{"path":"asset.json","size":11091,"sha256":"90799088f7332dc4f93d43d63174d6426e06042fb2a68f23bb875955e135a618","contentType":"application/json; charset=utf-8","url":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/asset.json"},{"path":"demo.js","size":1309,"sha256":"cdd8760324f47c6dcb0df86b11fad39290c02cf6f99bf87fa69bee781f02f409","contentType":"text/javascript; charset=utf-8","url":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/demo.js"},{"path":"index.html","size":524,"sha256":"3baa4c81cc6af74a9dc5a1a04d4eab239547d758105d0ae6b343fd7393a01088","contentType":"text/html; charset=utf-8","url":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/index.html"},{"path":"src/ferrofluid.js","size":20716,"sha256":"07c6311f92521990e0d089be0dcfd7cde82e4bab0fa0f07a0e76d2a35ccc47ae","contentType":"text/javascript; charset=utf-8","url":"https://aipixelwizard.com/registry/ferrofluid/1.0.0/src/ferrofluid.js"}],"warnings":[]}