Helix Noise — divergence-free flow fields
Give anything the motion of a fluid
One function tells you which way things drift at any point in space — and it always moves like water: swirling, folding, never clumping. This whole page is one field, running in JavaScript — and identical in Python, Rust, and shaders.
…or drag anywhere to stir the current yourself.
What you're looking at
You're standing inside an invisible current that fills all of space.
Ask it about any point and it tells you which way things drift there — so you can carry smoke, water, particles, hair, or a whole crowd along that flow and it looks alive. No fluid solver, no bake, no grid to fill. The current above is the real library, running as you read.
The reason it feels like a fluid is one guarantee: it's divergence-free — nothing piles up and nothing vanishes, exactly like real, incompressible water. That's why tracers swirl and fold instead of collapsing into blobs the way ordinary noise makes them. Three qualities shape the look — how big the swirls are, which way they spin, and whether it reads as calm noise or organized eddies — and each current above is one blend of the three.
For the curious: the field is a grid-free sum of divergence-free helical (Beltrami)
modes; the three qualities are spectral slope, helicity, and phase
coherence. Full details in the docs.
Why it's built this way
Real physics underneath, art direction on top.
Incompressible
Moves like real fluid
Nothing piles up, nothing vanishes — ink stretches and folds but never tears, and particles never clump into blobs.
divergence-free — exact to machine precisionArt-directable
Qualities you can dial
Set the size of the swirls, which way they spin, and how organized the flow reads. Handedness and structure are things ordinary curl-noise simply can't do.
slope · helicity · coherenceGrid-free
Works anywhere, endless
Ask about any point in space — no grid to fill, no boundary, no tiling seam, no simulation to step. It just answers, in constant time.
one call is O(modes)CPU & GPU
Same field on the GPU
One call drops the exact field into your shader, matching the CPU version bit-for-bit — so a million particles is no problem. Zero dependencies.
field.glsl() · WASM SIMD batchesSee it move
One field, every renderer.





One algorithm, four languages
The same field, wherever you build.
Pick a current in the browser above — then take that exact field to your language of choice. Every port is generated from one shared spec and checked against the JavaScript reference: for the same seed and settings they produce bit-identical output to ~1e-15 — machine precision. Not a lookalike, the same field.
JavaScript / TS
The reference
Spectral + atom engines, boundaries, GLSL export, a WASM SIMD batch kernel. Runs the field on this page. Zero dependencies.
npm install helix-noise · docs →Python
numpy-native
The spectral engine with vectorized batch sampling — for scientific viz, generative art, and synthetic flow data.
pip install helix-noise · docs →Rust
Zero-dependency crate
The spectral engine as a lean, WASM-friendly crate — for engines, high-performance procedural work, and native tools.
cargo add helix-noise · docs →Shaders
GPU, engine-agnostic
A generator that emits ready-to-paste GLSL, HLSL, WGSL, and Godot — for Shadertoy, Unity, Unreal, Godot, and WebGPU.
generate.py → glsl · hlsl · wgsl · docs →Get it running
In your project in two lines.
# zero runtime deps · ESM · CJS · IIFE · TS types (or a CDN <script>) npm install helix-noise import { create } from "helix-noise"; const field = create({ helicity: 0.8, coherence: 0.5 }); const [ux, uy, uz] = field.sample(x, y, z); // divergence-free, anywhere
# numpy-native, vectorized batch sampling pip install helix-noise from helix_noise import create field = create(helicity=0.8, coherence=0.5) u = field.sample(x, y, z) # divergence-free, anywhere
// zero-dependency crate, WASM-friendly cargo add helix-noise use helix_noise::{HelixField, HelixOptions}; let field = HelixField::new(HelixOptions { helicity: 0.8, coherence: 0.5, ..Default::default() }); let u = field.sample(x, y, z); // divergence-free, anywhere
# emit a self-contained shader for your target (glsl · hlsl · wgsl · godot) python generate.py --target glsl --helicity 0.8 > helix.glsl // then, in your shader: vec3 u = helixNoise(p); // divergence-free, anywhere