Helix Noise · volumetric smoke · WebGL2 raymarch

Volumetric smoke — driven by field.bake3D()

A 48³ voxel smoke volume advected through a Helix Noise field and rendered by volume raymarching with self-shadowing. The velocity comes straight from the library: field.bake3D(48) returns an RGBA grid (rgb = velocity), the three smoke channels advect semi-Lagrangian each frame, upload as a 3-D texture, and a fragment shader marches it. Push helicity to ±1 and the plumes corkscrew with a single handedness — real 3-D chirality in smoke. Drag to orbit, scroll to zoom; toggle draw to pour smoke with the pointer.

building field…
drag to rotate · scroll / pinch to zoom
Helicity+0.80
left-handed −1right-handed +1
At ±1 every plume winds the same way as it rises — smoke with a handedness.
Spectral slope2.3
fine · raggedlarge · silky
Steep = a few silky folds; shallow = ragged multi-scale billows.
Phase coherence55%
diffuseorganised
Same spectrum, phases random → structured: haze becomes distinct rolling cells.
speed1.0×
rise0.40
emit1.0×
zoom1.0×
Colour gradient
256-px LUT · tints by height + density
left emitter right emitter drawn smoke (white)

How it works

Every knob change calls field.set({ slope, helicity, coherence, seed }) and then field.bake3D(48) — one RGBA Float32Array whose rgb is the divergence-free velocity at each voxel. The three smoke channels advect semi-Lagrangian on the CPU against that grid, upload as an RGBA8 3-D texture, and a WebGL2 fragment shader raymarches it: 72 steps, front-to-back compositing, one shadow tap per step for the self-shading that reads as smoke rather than fog. Nothing here reaches into the field internals — it is all the public API. The colour gradient row swaps a 256-px 1-D LUT (a second texture) into the shader, tinting each sample by height and density — the same trick a VFX artist wires as a smoke ramp.

Honest limits

48³ is demo resolution — production is 128³–512³ baked to OpenVDB with the same call. The velocity field is frozen per seed (the smoke moves through it; re-baking each frame is cheap enough for slow morphs but off here). Semi-Lagrangian sampling adds numerical diffusion — visible as the smoke's softness. Requires WebGL2; the canvas says so if it's missing.