Expression cookbook
Copy-paste recipes for the Expression node — short snippets you can drop in, tweak, and make your own.
Each recipe below goes in an Expression node, sitting downstream of whatever you want to affect. @name reads a per-element attribute (one value per point); $NAME reads a global like time. Change the numbers until it looks right.
Every recipe assumes the incoming data already has the attribute you're reading — points carry @P automatically, but @Cd (colour) or a custom attribute may need a node upstream to create it first.
Jitter points with noise
Nudge every point by a small random-but-smooth amount, so a tidy grid becomes organic.
@P = @P + noise(@P * 0.5) * 10.0;
noise(@P * 0.5) samples a smooth 3D noise at each point's position. The * 0.5 zooms the noise pattern (smaller = bigger, smoother lumps); the * 10.0 is how far points move. Multiply by $T inside the noise for drifting, living jitter:
@P = @P + noise(@P * 0.5 + $T) * 10.0;
Colour by height
Tint points by how high they sit — great for instant readability on terrain, scatters, or simulations.
@Cd = @P.y > 0 ? {1, 0.6, 0.1, 1} : {0.1, 0.4, 1, 1};
@P.y is the up axis. This picks warm above zero, cool below. For a smooth gradient instead of a hard cutoff, blend with mix and a normalised height:
float h = clamp(@P.y / 100.0, 0.0, 1.0);
@Cd = mix({0, 0, 0, 1}, {1, 1, 1, 1}, h);
For richer colour ramps, feed h into a Gradient widget rather than hand-blending two colours.
A wave over time
Animate any value with a sine wave driven by the playhead. This one bobs points up and down:
@P.y = @P.y + sin($T * 2.0 + @P.x * 0.1) * 20.0;
$T is animation time in seconds. * 2.0 sets the speed; * 20.0 the height. Adding @P.x * 0.1 offsets each point by its X position, so the whole row ripples like a flag instead of moving as one block.
You can use the same idea in any parameter field — type sin($T * 2.0) * 10.0 + 72.0 straight into a number box to make it oscillate.
Point at the mouse
Aim every point's colour (or motion) toward the cursor. Read live pointer position as a global, then react to distance:
float d = length(@P.xy - $POINTER);
@Cd = mix({1, 1, 1, 1}, {1, 0, 0, 1}, clamp(d / 200.0, 0.0, 1.0));
Points near the cursor stay white, far ones go red. Swap the colour blend for a position nudge to make points flee or chase the mouse:
@P.xy = @P.xy + normalize(@P.xy - $POINTER) * 5.0;
Live pointer input is captured through a pointer source in the graph. If $POINTER isn't recognised in your build, wire a pointer node's value into a parameter and read that instead — see Recording live input.
Sample a field at each point
Fields are values that exist everywhere in space. Sample one at each point's position to colour, push, or scale by it — for example, reading a noise field to drive displacement:
@P = @P + sample(@field, @P) * @N;
This pushes every point along its normal @N by however much the field reads at that point. Use it to wrinkle a surface, carve detail, or let a field sculpt a scatter.
To colour by a field instead:
@Cd.rgb = sample(@field, @P);
Only the colour channels change; alpha is left alone because of the .rgb on the left.
Combine a few at once
Recipes stack. Drop several lines in one Expression node and they run top to bottom:
// drift, then colour by the new height
@P = @P + noise(@P * 0.5 + $T) * 8.0;
@Cd = mix({0, 0.2, 0.6, 1}, {1, 0.9, 0.4, 1}, clamp(@P.y / 80.0, 0.0, 1.0));
Keep one effect per line while you dial it in, then merge. It's much easier to mute a single line (comment it out with //) when something looks off.
See also
The Expression language — what the Expression node is and how it fits the graph
Expression attributes — the
@nameattributes you can read and writeGlobals & parameters —
$T,$F,$POINTERand the restBuilt-in functions —
noise,mix,sample,clampand friendsFields & sampling — how field sampling works
Parameter expressions — using these in parameter boxes