Curl Noise
Function. Calculates a divergence-free (curl) 3D velocity at a position in space.
Unlike Noise3, this field has no sources or sinks: it is built by taking the curl of a vector potential, so nothing flows into or out of any region. Particles carried by it flow around obstacles in the field instead of piling up in its sinks, which is what gives it a fluid, swirling look rather than a clumped one.
The field is one fixed volume that every runtime builds or loads, so the same effect looks the same in the editor preview, in an exported JavaScript build, in an exported C# build and in GPU33.
A typical use is feeding the output into a ForceMove block, either as a wind (a target velocity the particles are dragged towards) or as a force (an acceleration applied directly). The Emitter Guide's Movement → Forces section builds the same block for you from either list: Add Wind... or Add Force..., both offering Curl. Any other 3D value can sample the field too: pick Curl Noise in its type menu (see Emitter Guide values).
A Curl source added in the Emitter Guide starts with a Strength sized to your project's scale: half the project's base unit for a wind, an eighth of it for a force (500 and 125 with the default base unit of 1000). A wind acts through air resistance, so it takes a moment to carry a particle along: on very short-lived particles even this Strength shows little, and a force, or a higher Air resistance, suits them better. It is set once, when the source is added — changing the base unit later, or opening an existing effect, never rewrites a Strength you already have.
Properties & inputs:
- Strength (input | property): Multiplier for the output vector. The field itself is normalised, so this alone sets how strong the flow is: a speed when the output feeds a wind, an acceleration when it feeds a force.
- Wavelength (input | property): Size of one field feature in world units. Larger values give broader, slower swirls; smaller values give tighter, more chaotic ones.
- Animation speed (input | property): Velocity vector that moves the field through space over time, so the turbulence keeps changing instead of staying frozen.
- Space offset (input | property): Shifts which part of the field is sampled. Two emitters with the same settings but different offsets get uncorrelated motion.
In the Emitter Guide all four are regular values: switch any of them to another value type (a random number, a curve, Multi-Value) and the block's matching input is connected for you.
Two more properties are not inputs:
- Variant (property): Which of 48 variations of the field to use,
0..47;0is the original field. Each variation swaps and flips the field's axes as a whole, so it looks like a different field in the same place, yet stays just as smooth and just as free of sinks. Use it when two sources in one effect should not move together, or simply to try another look. It is written into the exported code as fixed numbers, so it costs nothing at run time. - Show visualizer (property): Draws the field in the 3D preview (see below). Off by default; it affects only the editor.
The Emitter Guide offers the same two settings on every Curl wind and force and on the Curl Noise value: a slider next to a number for Variant (drag the slider to try one after another, type the number to pick a known one) and a Show visualizer checkbox. On a reflected emitter both can be overridden like any other setting.
Output:
- 3D velocity vector sampled from the field at the input position.
Notes
Wavelength is evaluated per particle. A random value gives each particle its own scale, so one emitter can mix broad and tight motion at once. A curve over the emitter's time instead changes the scale of the field as the effect plays. A constant Wavelength gives every particle the same field.
Animation speed is a rate, not an accumulated speed. The field is sampled at Animation speed × system time + position + Space offset. If Animation speed itself changes over time, the whole field jumps by the change multiplied by the elapsed system time, instead of smoothly speeding up. To move the field along a path of your own, animate Space offset and leave Animation speed constant.
The field repeats. It tiles seamlessly every Wavelength units on each axis. With a small Wavelength and a large emitter, that repetition can become visible as a pattern; raise Wavelength or add a Space offset per emitter to break it up.
Seeing the field. With Show visualizer on, the preview draws the field as streamlines: lines that follow the flow, starting from 216 points spread evenly over a cube at the center of the world, one Wavelength wide — exactly one repeat of the field. Each line reaches half a Wavelength along the flow, behind and ahead of its starting point, and runs from blue to yellow in the direction the flow goes, so the swirls, their size and where they carry particles are visible at a glance. Strength is not applied: the lines show the shape of the field, not how hard it pushes. The lines follow Space offset, and as the preview plays the whole picture drifts with the field without changing shape — opposite to the Animation speed vector, just as the field the particles feel moves; a line whose starting point leaves the cube through one face comes back in through the opposite one. Near such a face the line fades out and fades back in on the other side, so lines do not pop in and out; the faces the field does not move across are left alone. Turning the visualizer on or off changes only the preview: the effect is marked as changed, but it is not rebuilt and keeps playing. A Curl Noise value that samples somewhere other than the particle position still shows the field itself, not what that value feeds. When Wavelength, Space offset or Animation speed is connected to an input (in the Emitter Guide: is not a constant), the field can differ from particle to particle, so only the grey outline of the cube is drawn, sized by the block's own Wavelength property.
Set the field up in your game. The editor preview has the field built in, but an exported effect needs its runtime to have it before the effect is created; without it Curl simply has no effect. The JavaScript runtime says so once in the console, and the MonoGame and Unity integrations once in their logs (the base C# runtime reports it through CurlNoise.onMissingField). In C# the runtime generates the field itself (a second or more, blocking): the Unity package does it when the first effect that uses Curl is created, and in MonoGame you call it at start-up. GPU33 builds the field itself when its context is created. In JavaScript, either bake the field at start-up (a few seconds, in small slices without blocking the page, at most brief hitches) or load the prebaked neutrinoparticles.curl-noise.v1.bin, which you can download from the Noise Generator page. Each integration's documentation shows the calls.
Not supported by the older export targets. The block requires JavaScript v1.1, C# v1.2 or GPU33. Exporting an effect that uses it to JavaScript v1.0, C# v1.0 or C# v1.1 is rejected with an error rather than silently producing a broken effect.