Part of the Wrangle reference. Everything on this page goes in the node's Code field, and runs once per element of the current Run Over mode.
Scalar functions
| Syntax | What it does | Example |
|---|---|---|
abs(x) or abs(v) |
Absolute value; vectors are component-wise. | wmap("Weights") = abs(P.z); P = abs(P) |
floor(x) |
Largest integer <= x. | wmap("Weights") = floor(2.7) |
ceil(x) |
Smallest integer >= x. | wmap("Weights") = ceil(2.1) |
round(x) |
Round half away from zero. | wmap("Weights") = round(2.5) |
frac(x) |
x - floor(x); always in [0,1). | wmap("Weights") = frac(P.x * 0.1) |
sign(x) |
-1, 0 or 1. | wmap("Weights") = sign(P.z) |
sqrt(x) |
Square root; negative x is guarded to 0. | wmap("Weights") = sqrt(dot(P, P)) |
pow(x, y) |
x to the power y; undefined combinations are guarded to 0. | wmap("Weights") = pow(mask, 2.2) |
exp(x) |
e to the x; overflow is guarded to 0. | wmap("Weights") = exp(-d * d) |
log(x) |
Natural log; x <= 0 is guarded to 0. | @logarea = log(area) |
log2(x) |
Base-2 log; x <= 0 is guarded to 0. | wmap("Weights") = log2(numpt) |
sin(x) |
Sine (radians). | wmap("Weights") = sin(P.x * 0.1) |
cos(x) |
Cosine (radians). | wmap("Weights") = cos(radians(45)) |
tan(x) |
Tangent (radians); overflow guarded to 0. | wmap("Weights") = tan(0.5) |
asin(x) |
Arcsine; the argument is clamped to [-1,1]. | wmap("Weights") = asin(N.z) |
acos(x) |
Arccosine; the argument is clamped to [-1,1]. | wmap("Weights") = acos(dot(N, vec3(0,0,1))) |
atan(x) |
Arctangent. | wmap("Weights") = atan(P.y) |
atan2(y, x) |
Angle of (x, y), full circle. | wmap("Weights") = atan2(P.y, P.x) |
radians(deg) |
Degrees to radians. | wmap("Weights") = sin(radians(30)) |
degrees(rad) |
Radians to degrees. | wmap("Weights") = degrees(acos(N.z)) |
min(a, b) |
Smaller of two; vectors are component-wise. | wmap("Weights") = min(mask, 0.5); P = min(P, vec3(1,1,1)) |
max(a, b) |
Larger of two; vectors are component-wise. | wmap("Weights") = max(P.z, 0); P = max(P, vec3(0,0,0)) |
clamp(x, lo, hi) |
x limited to [lo, hi] (reversed bounds are reordered). Vectors are component-wise; clamp(v, s, s) broadcasts the scalars. | wmap("Weights") = clamp(P.z, 0, 1); P = clamp(P, 0, 1) |
saturate(x) |
clamp(x, 0, 1). | wmap("Weights") = saturate(d / 50) |
lerp(a, b, t) |
a + (b - a) * t. mix is the same function. |
wmap("Weights") = lerp(0.2, 1, mask) |
mix(a, b, t) |
Alias of lerp. | wmap("Weights") = mix(0.2, 1, mask) |
fit(v, omin, omax, nmin, nmax) |
Map v from [omin, omax] to [nmin, nmax], clamped to the new range. remap is the same function. |
wmap("Weights") = fit(P.z, 0, 100, 0, 1) |
remap(v, omin, omax, nmin, nmax) |
Alias of fit. | wmap("Weights") = remap(d, 0, 25, 1, 0) |
fit01(v, nmin, nmax) |
Convenience alias of fit(v, 0, 1, nmin, nmax). | wmap("Weights") = fit01(mask, -1, 1) |
step(edge, x) |
0 while x < edge, else 1 (HLSL order). | wmap("Weights") = step(50, P.z) |
smoothstep(e0, e1, x) |
Hermite ramp from 0 at e0 to 1 at e1, clamped. | wmap("Weights") = smoothstep(0, 25, d) |
mod(a, b) |
Remainder with the sign of a; b = 0 is guarded to 0. | wmap("Weights") = mod(ptnum, 2) |
rand(seed) |
Deterministic hash of the seed to [0,1). Same seed, same value, every run and every machine. | wmap("Weights") = rand(ptnum) |
trunc(x) |
Toward zero. Differs from floor for every negative non-integer: trunc(-1.5) is -1, floor(-1.5) is -2. | wmap("Weights") = trunc(-1.5) |
exp2(x) |
2 to the x; overflow is guarded to 0. | wmap("Weights") = exp2(3) |
log10(x) |
Base-10 log; x <= 0 is guarded to 0. | wmap("Weights") = log10(1000) |
hypot(x, y) |
sqrt(xx + yy) - the 2D length, for uv and other two-component work. | wmap("Weights") = hypot(uv.x - 0.5, uv.y - 0.5) |
inversesqrt(x) |
1 / sqrt(x); x <= 0 is guarded to 0. | wmap("Weights") = inversesqrt(dot(P, P)) |
sinh(x) |
Hyperbolic sine; overflow is guarded to 0. | wmap("Weights") = sinh(1) |
cosh(x) |
Hyperbolic cosine; overflow is guarded to 0. | wmap("Weights") = cosh(0) |
tanh(x) |
Hyperbolic tangent, always in (-1, 1). The standard soft clip: it compresses large values instead of cutting them off the way clamp does. | wmap("Weights") = tanh(P.z * 0.1) |
finite(x) |
1 if x is finite, else 0. Finite(x) and isfinite(x) are the same function. Arithmetic already replaces overflow and divide-by-zero with 0, so finite(Num / Den) on a quotient the expression produced is 1; test the inputs (finite(Den) && Den != 0) when you care. | wmap("Weights") = finite(1) |
isnan(x) |
1 if x is NaN, else 0. | wmap("Weights") = isnan(0) |
isinf(x) |
1 if x is infinite, else 0. | wmap("Weights") = isinf(0) |
cbrt(x) |
Cube root, sign-preserving (unlike pow(x, 1/3), which guards every negative x to 0). | wmap("Weights") = cbrt(-8) // -2 |
bias(x, b) |
Schlick's fast bias curve: pushes x toward 0 (b < 0.5) or 1 (b > 0.5); b = 0.5 is the identity. x is clamped to [0,1], b to a safe (0,1) range. | wmap("Weights") = bias(mask, 0.25) |
gain(x, g) |
S-curve built from bias: steepens the middle and flattens the ends (g < 0.5) or the reverse (g > 0.5); g = 0.5 is the identity. Same clamping as bias. | wmap("Weights") = gain(mask, 0.75) |
Vector functions
| Syntax | What it does | Example |
|---|---|---|
vec3(x, y, z) |
Build a vector from three scalars. Compiles to nothing. | vector up = vec3(0, 0, 1) |
dot(a, b) |
Dot product of two vectors. | wmap("Weights") = dot(N, vec3(0,0,1)) |
cross(a, b) |
Cross product (left-handed, like the rest of UE). | vector t = cross(N, vec3(0,0,1)) |
length(v) or length(x, y, z) |
Euclidean length. Both spellings are the same function. | wmap("Weights") = length(P - nearpoint("Reference", P)) |
distance(a, b) |
length(a - b). | wmap("Weights") = distance(P, vec3(0,0,0)) |
normalize(v) |
v / length(v); the zero vector is guarded to the zero vector (and counted). | N = normalize(N) |
lerp(a, b, t) |
Component-wise blend of two vectors by a scalar t. mix works too. | P = lerp(P, nearpoint("Reference", P), 0.5) |
reflect(i, n) |
i - 2 * dot(i, n) * n; n is used verbatim (normalise it yourself). | vector r = reflect(v, N) |
planedist(planept, planenormal, p) |
Signed distance from p to the plane through planept with the given normal - positive on the side the normal points to. The normal is normalised for you; a zero-length one is guarded to 0. | wmap("Weights") = planedist(vec3(0,0,0), vec3(0,0,1), P) |
ptlined(a, b, p) |
Distance from p to the segment a-b (VEX's own argument order: the two endpoints, then the point). A degenerate segment (a == b) falls back to distance(p, a). | wmap("Weights") = ptlined(vec3(0,0,0), vec3(0,0,10), P) |
Integers
| Syntax | What it does | Example |
|---|---|---|
bitand / bitor / bitxor bitand(a, b) / bitor(a, b) / bitxor(a, b) |
Bitwise and / or / xor of two integral operands. | wmap("Weights") = bitand(floor(ptnum), 3) |
bitnot(a) |
Bitwise not (one's complement) of one integral operand. | wmap("Weights") = bitnot(0) |
shl / shr shl(a, count) / shr(a, count) |
Shift left / arithmetic (sign-preserving) shift right. count is clamped to [0, 63] and the clamp is counted (DomainGuarded) when it fires. | wmap("Weights") = shl(1, 4) |
floordiv(a, b) |
Floor division: floor(a / b), exact even where / followed by floor() would lose precision. Differs from / at every negative result - floordiv(-7, 2) is -4, not -3.5 truncated. b == 0 is guarded to 0 (DivideByZero), same as /. |
wmap("Weights") = floordiv(-7, 2) |
What these are
Eight functions filling gaps float arithmetic leaves - there is still no separate integer type anywhere in this language: every one of these takes and returns an ordinary float, so any local, channel or attribute can carry an integral value straight through them. Operands must be exactly integral and within +-2^53 (the largest integer a double represents exactly) or the result is 0, counted (DomainGuarded) - the same "defined fallback, always counted" convention every other domain guard in this file uses.
wmap("Weights") = bitand(ptnum, 1)
imod(a, b)
Euclidean modulo: always in [0, |b|), never negative. % and mod() keep their existing fmod behaviour (the sign of the dividend, so mod(-7, 3) is -1) - imod exists because that trap catches almost everyone who reaches for "wrap an index into range": imod(-7, 3) is 2, which is the wrap-around answer % does not give you. b == 0 is guarded to 0 (DivideByZero).
wmap("Weights") = imod(ptnum - 1, numpt)
Debug
trace(x)
Returns x unchanged, and folds it into this call site's running count/min/max/mean, reported in the node's run Summary as "trace at line N: count ..., min ..., max ..., mean ...". A read-back for what an expression actually computed without adding a permanent output. Legal in every run-over. Up to 64 trace() sites per expression; a 65th is a compile error naming the cap. Trace values are only reported by the Wrangle node's own run summary - the Custom Force (simulation) expression compiles trace() calls but discards the report, so trace() there returns x unchanged with no readable stats anywhere.
wmap("Weights") = trace(P.z) * 2