1. Home
  2. Docs
  3. PopcornFX v2
  4. Scripting
  5. builtin functions

builtin functions

This page lists all builtin functions in the root namespace.
Function parameters enclosed in square brackets mean they are optional, and the function can be called without specifying that parameter.
The # character used when specifying types can either mean ‘any type’ when it is used alone, or ‘any dimension’ if it is after a scalar type.
For example, float# lerp(float# a, float# b, float #t) means the following overloads of lerp are available:

float  lerp(float a, float b, float t);
float2 lerp(float2 a, float2 b, float2 t);
float3 lerp(float3 a, float3 b, float3 t);
float4 lerp(float4 a, float4 b, float4 t);

Most functions on that page will appear with that notation, as they can be used with multiple types.

 

Interpolation

Return typeDescription
float#step(float# x, float# y)

Step function. evaluates to 0.0 if x < y, and evaluates to 1.0 if x >= y

[-∞, +∞] ⟶ [0, 1]

float#linearstep(float# a, float# b, float# x)

Linearstep function. linearly evaluates between 0.0 to 1.0 the position of x between a and b.

[-∞, +∞] ⟶ [0, 1]

float#smoothstep(float# a, float# b, float# x)

Smoothstep function. smoothly evaluates between 0.0 to 1.0 the position of x between a and b.

[-∞, +∞] ⟶ [0, 1]

float#lerp(float# a, float# b, float# t)

 

Lineary blends between a and b based on the value of t.
t is an interpolation factor in the [0, 1] range. when t equals 0.0, a is returned, when t equals 1.0, b is returned. values in between return values between a and b.

Ex: lerp(float3(0), float3(1,2,3), 0.5); will return float3(0.5, 1, 1.5).

float#smoothlerp(float# a, float# b, float# t)

 

Smoothly blends between a and b based on the value of t.
t is an interpolation factor in the [0, 1] range. when t equals 0.0, a is returned, when t equals 1.0, b is returned. values in between return values between a and b.

Ex: smoothlerp(float3(0), float3(1,2,3), 0.5); will return float3(0.5, 1, 1.5).

Equivalent to

lerp(a, b, smoothstep(0, 1, t));

Or

lerp(a, b, 3*t*t - 2*t*t*t);

 

Random numbers

Return typeDescription
float#rand(a, b)

Random function, returns a random value r uniformly distributed in the range [a, b[

a <= r < b

#
#
randsel(a, b)
randsel(a, b, float# k)

 

Randomly returns a or b.

The two-argument version of randsel has equal probability to return a or b, and calling randsel(a, b); is equivalent to calling randsel(a, b, 0.5);.
You can specify a custom probability to get either a or b by using the the three-argument version of randsel:
randsel(a, b, 0.1); will have a 10% chance of returning b, and a 90% chance of returning a
randsel(a, b, 0.75); will have a 75% chance of returning b, and a 25% chance of returning aThe order of the parameters can be counter-intuitive, but you can think of it like lerp(a,b,k), a value of k close to 0 will return values close to a, a value of k close to 1 will return values close to b. Same with randsel(a,b,k), low values of k return a more often, high values return b more often.logic:

select(a, b, rand(0,1) < k);
float
float#
randsign()
randsign(float# k)

 

Randomly returns -1.0 or 1.0.
randsign() is equivalent to randsel(-1.0, 1.0), or to sign(rand(-1,1))
The version of randsign() with no arguments has equal probability to return -1.0 or 1.0, and calling randsign() is equivalent to calling randsign(0.5)You can specify a custom probability to get either -1.0 or 1.0 by using the the one-argument version:
randsign(0.1); will have a 10% chance of returning 1.0, and a 90% chance of returning -1.0
randsign(0.75); will have a 75% chance of returning 1.0, and a 25% chance of returning -1.0logic:

select(-1.0, 1.0, rand(0,1) < k);
float3
float3
float3
vrand()
vrand(float inner, float outer)
vrand(float inner, float outer, curveResource probabilityCurve)

 

Random function, stands for “vector-rand”, returns a random float3 vector uniformly distributed on the unit sphere surface.
Very useful to generate nicely distributed random normals, random 3D offsets, or other unit vectors to give a bit of randomization to particle velocities, etc..

base vrand() functionvrand()*rand(0,1)vrand()*rand(0.5,1)
60k samples of vrand()vrand()*rand(0,1)vrand()*rand(0.5,1)

 

vrand(inner, outer) allows you to generate a point in a spherical shell instead of a sphere surface. ‘inner’ is the radius of the inner shell, ‘outer’ is the radius of the outer shell.

vrand(1,1) will give the same results as calling the classic vrand(). To generate a point inside the volume of a whole sphere, use vrand(0,1).
It keeps correct uniform distribution of samples per unit volume.

vrand(0,1)vrand(0.5,1)
vrand(0,1)vrand(0.5,1)

 

vrand(inner, outer, probabilityCurve) expects the name of a 1D curve sampler as third argument, which should have its IsProbabilityCurve property checked. It will use that curve as a probability distribution between the ‘inner’ and ‘outer’ radius and distribute the random samples accordingly.

vrand(0,1,MyCurve)vrand(0.5,1,MyCurve)'MyCurve' Probability curve
vrand(0,1,MyCurve)vrand(0.5,1,MyCurve)‘MyCurve’ Probability curve

 

Noise

Return typeDescription
float
float
noise(float# t)
fast.noise(float# t)

 

Evaluates a coherent noise field. t can be a float, float2, float3, or float4 cursor.

All functions return a single float value in the [-1,1] range.

noise() computes a high quality simplex-noise.
fast.noise() computes a slightly lower quality, but faster, noise.Ex:
noise(LifeRatio); will sample a 1D noise
noise(uv * 100); will sample a 2D noise
noise(Position); will sample a 3D noise
noise(float4(Position, scene.Time)); will sample a 4D noise

float#
float
dnoise(float# t)
fast.dnoise(float# t)

 

Evaluates the derivative of the coherent noise field returned by noise(t) or dnoise(t).
t can be a float, float2, float3, or float4 cursor.

The returned value is a vector of the same dimension as t, and is in the ]-∞,+∞[ range.

 

Math constants

TypeDescription
floatpi

Constant pi
π ~= 3.14159265359

floatphi

Constant phi
φ ~= 1.61803398875

floatinfinity

infinity: +∞

 

Math functions

Return typeDescription
float#dot(float# u, float# v)

vector dot-product
]-∞, +∞[ ⟶ ]-∞, +∞[

float3cross(float3 u, float3 v)

3D vector cross-product
]-∞, +∞[ ⟶ ]-∞, +∞[

float3reflect(float3 v,float3 n)

Reflects (mirrors) the vector v on the plane defined by the normal n.
]-∞, +∞[ ⟶ ]-∞, +∞[

#abs(x)

Returns the absolute value of x
script function abs()
[-∞, +∞] ⟶ [0, +∞]

#sign(x)
Sign function.
If x is a floating-point scalar or vector, returns -1.0 when x <= -0.0, and +1.0 when x >= +0.0
If x is an integer scalar or vector, returns -1 when x < 0, and +1 when x >= 0
script function sign()
[-∞, +∞] ⟶ [-1], [+1]
float#ceil(float# x)
Ceiling rounding: rounds to the closest integer value >= x
script function ceil()
[-∞, +∞] ⟶ [-∞, +∞]
float#floor(float# x)
Floor rounding: rounds to the closest integer value <= x
script function ceil()
[-∞, +∞] ⟶ [-∞, +∞]
float#frac(float# x)
Extracts the fractional part of x
script function frac()
[0, +∞[ ⟶ [0, 1[
]-∞, 0[ ⟶ ]-1, 0]
float#wavesq(float# x)
Square wave function
script function wavesq()
]-∞, +∞[ ⟶ [-1, 1]
float#wavetri(float# x)
Triangular wave function
script function wavetri()
]-∞, +∞[ ⟶ [0, 1]
float#wavesaw(float# x)
Sawtooth wave function
script function wavesaw()
]-∞, +∞[ ⟶ [0, 1]
float#discretize(float# x, float# y)

Discretization function, snaps x to the nearest step, given a step size y
script function discretize()
[-∞, +∞] ⟶ [-∞, +∞]

#min(x,y)

Minimization function: if x < y, returns x, otherwise, returns y
script function min()
[-∞, +∞] ⟶ [-∞, y]

#max(x,y)

Maximization function: if x > y, returns x, otherwise, returns y
script function max()
[-∞, +∞] ⟶ [y, +∞]

float#clamp(x,a,b)

Clamp function: if x < a, returns a, otherwise, if x > b, returns b, otherwise, returns x
script function clamp()
[-∞, +∞] ⟶ [a, b]

float#saturate(float# x)

Clamps x in the [0, 1] range
script function saturate()
[-∞, +∞] ⟶ [0, 1]

float#
float#
float#
sqrt(float# x)
fast.sqrt(float# x)
accurate.sqrt(float# x)

Square-root function
The fast version is faster, but gives a lower precision result.
script function sqrt()
[0, +∞] ⟶ [0, +∞]

float#
float#
float#
rsqrt(float# x)
fast.rsqrt(float #x)
accurate.rsqrt(float #x)

Reverse square-root
The fast version is faster, but gives a lower precision result.
script function rsqrt()
[0, +∞] ⟶ [0, +∞]

float#
float#
float#
cbrt(float# x)
fast.cbrt(x)
accurate.cbrt(x)

Cube root
The fast version is faster, but gives a lower precision result.
script function sqrt()
[0, +∞] ⟶ [0, +∞]

float
float#
float#
length(float# v)
fast.length(float# v)
accurate.length(float# v)

Returns the length of vector v. Works with vectors from 1 to 4 dimensions.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [0, +∞]

float#
float#
float#
normalize(float# v)
fast.normalize(float# v)
accurate.normalize(float# v)

Normalizes vector v (returns the unit vector pointing in the same direction). Works with vectors from 1 to 4 dimensions.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [-1, 1]

float#
float#
float#
exp(float# x)
fast.exp(float# x)
accurate.exp(float# x)

Natural exponential.
Uses the fast namespace by default.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [0, +∞]

float#
float#
float#
exp2(float# x)
fast.exp2(float# x)
accurate.exp2(float# x)

Base-2 exponential.
Uses the fast namespace by default.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [0, +∞]

float#
float#
float#
pow(float# x, float# y)
fast.pow(float# x,float# y)
accurate.pow(float# x,float# y)

Power function.
The fast version is faster, but gives a lower precision result.
{[0, +∞], [-∞, +∞]} ⟶ [-∞, +∞]

float#
float#
float#
log(float# x)
fast.log(float# x)
accurate.log(float# x)

Natural logarithm.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [-∞, +∞]

float#
float#
float#
log2(float# x)
fast.log2(float# x)
accurate.log2(float# x)

Base-2 logarithm.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [-∞, +∞]

float#
float#
float#
rcp(float# x)
fast.rcp(float# x)
accurate.rcp(float# x)

Inverse function.
The fast version is faster, but gives a lower precision result.
[-∞, +∞] ⟶ [-∞, +∞]

#within(x, lower, upper)

 

Returns 1.0 if x is within the [lower, upper] range, returns 0.0 otherwise.
All the function’s arguments can be either scalars, or vectors. if some arguments are vectors, they must have the same dimension. The return value will be a vector as large as the largest input vector.
IE: you cannot call within(float2, float3, float4), but you can call within(float, float, float4) or within(float3, float, float3)

 

Ex:
within(0.5, -1.2, 3.0); will return 1.0.
within(float3(-2,0,2.5), -1.2, 3.0); will return float3(0.0, 1.0, 1.0).
within(1.5, -1.0, float4(0,1,2,3)); will return float4(0.0, 0.0, 1.0, 1.0).

float#
float#
remap(value, newMin, newMax)
remap(value, oldMin, oldMax, newMin, newMax)

 

Remaps value from the [oldMin, oldMax] range to the [newMin, newMax] range.
all the function’s arguments can be either scalars, or vectors. If some arguments are vectors, they must have the same dimension. The return value will be a vector as large as the largest input vector.
IE: you cannot call remap(float2, float3, float4), but you can call remap(float, float, float4) or remap(float3, float, float3)
the version that has no ‘oldMin’ and ‘oldMax’ assumes the original range is [0,1]Ex:
remap(0.5, 1.0, 3.0); will return 2.0.
remap(0.5, 0, 0.5, 1.0, 3.0); will return 3.0.

boolall(bool# c)

 

Returns true if ALL elements of vector c are true
c can be a boolean scalar or vector of any dimension.

 

Ex:
all(float3(0) < float3(1,2,3)); will return true.
all(float3(0) < float3(1,-2,3)); will return false.

boolany(bool# c)

 

Returns true if ANY element of vector c is true
c can be a boolean scalar or vector of any dimension.

 

Ex:
any(float3(0) > float3(1,2,3)); will return false.
any(float3(0) > float3(1,-2,3)); will return true.

#bias(float# x, float# e)

 

De-linearizes the input x by applying a power function based on value e.

x is expected to be in the [0,1] range, e has to be in the [-1,1] range.

bias functione = 0 : black (x)
e = +-0.3 : green
e = +-0.6 : yellow
e = +-0.85 : orange
e = +-0.99 : red
float#
float#
safe_normalize(v[, vz, epsilon])
fast.safe_normalize(v[, vz, epsilon])

 

Normalizes the input vector v and returns the resulting unit-vector. Unlike the normalize and safe_normalize builtins, these safe versions check for null vectors.
This will prevent normalizing a null vector and getting an Infinity or NaN vector in return.
Works on any vector dimensions.

 

Ex:
safe_normalize(vector3); returns normalize(vector3), but if length(vector3) < 1.0e-8, returns float3(0,0,0).
safe_normalize(vector3, float3(0,1,0)); returns normalize(vector3), but if length(vector3) < 1.0e-8, returns float3(0,1,0).
safe_normalize(vector3, float3(0,1,0), 1.0e-6); returns normalize(vector3), but if length(vector3) < 1.0e-6, returns float3(0,1,0).safe_normalize(vector3)
is equivalent to:
select(normalize(vector3), float3(0), length(vector3) < 1.0e-8);

float3
float3
float3
float3
float3suf(side, up, forward)
float3suf(...)
float3sfu(side, forward, up)
float3sfu(...)

 

Takes the side, up, and forward components and permutes/swizzles them based on the current axis-System.
Accepts the same kind of arguments as the regular float3 construction: you can pass a float2 and a float, a float3, or three floats.Ex:

float3suf(0, 18, 0);
  • Y-Up axis-system: float3(0, 18, 0);
  • Z-Up axis-system: float3(0, 0, 18);

 

float3 vec = float3(1, 2, 3);
res = float3suf(vec);
  • Y-Up axis-system: res = vec; (no changes)
  • Z-Up axis-system: res = vec.xzy; (so: float3(1, 3, 2))
bool#isfinite(float# v)

 

Useful to detect infinite or invalid values.

isfinite(v) returns true if v is a finite value, false if not.

isfinite(42);      --> true
isfinite(1.0/0.0); --> false
isfinite(0.0/0.0); --> false

 

This function can be used to check the return values of some functions that return infinite values as a way to report en empty result.
For example, scene raycasts:

float4 isec = scene.intersect(pos, dir, len);
float3 reflPos = pos + dir * isec.w + reflect(dir, isec.xyz) * (len - isec.w); // Bounced pos, will be invalid if no collision, as isec.w will be +inf
float3 endPos = pos + dir * len; // Unblocked end pos
pos = select(endPos, reflPos, isfinite(isec.w)); // If invalid, fallback to unblocked end pos
bool#isinf(float# v)

 

Useful to detect infinite or invalid values.
isinf(v) returns true if v is an infinite value, false if not (either finite or NaN).

isinf(42);        --> false
isinf(1.0/0.0);   --> true
isinf(0.0/0.0);   --> false

 

This function can be used to check the return values of some functions that return infinite values as a way to report en empty result.
For example, scene raycasts:

float4 isec = scene.intersect(pos, dir, len);
float3 reflPos = pos + dir * isec.w + reflect(dir, isec.xyz) * (len - isec.w); // Bounced pos, will be invalid if no collision, as isec.w will be +inf
float3 endPos = pos + dir * len; // Unblocked end pos
pos = select(reflPos, endPos, isinf(isec.w)); // If invalid, fallback to unblocked end pos
bool#isnan(float# v)

 

Useful to detect infinite or invalid values.
isnan(v) returns true if v is a NaN value (NaN = “Not a Number”), false if not.

isnan(42);        --> false
isnan(1.0/0.0);   --> false
isnan(0.0/0.0);   --> true

 

float#asfloat(v)

 

Reinterprets the input as a float. If given a float, does nothing. If given an int, will reinterpret its bits as if it was a float.
works on any vector, float to float4, int to int4.

 

asfloat(0x3F800000);     --> 1.0
asfloat(42.0);           --> 42.0
asfloat(int4(0x40490FDB, 0, 0xC0200000, -1071644672)) --> float4(3.141593, 0, -2.5, -2.5)
int#asint(v)

 

Reinterprets the input as an int. If given an int, does nothing. If given a float, will reinterpret its bits as if it was an int.
works on any vector, float to float4, int to int4.

 

asint(1.0);              --> 0x3F800000
asint(42);               --> 42
asint(float4(3.141593, 0, -2.5, -2.5)) --> int4(0x40490FDB, 0, 0xC0200000, 0xC0200000)

 

Trigonometric functions

All trigonometric functions below are also available in the fast and accurate namespaces. fast versions are faster, but give a lower precision result. accurate versions are slower but give a higher-precision results. Functions in the root namespace without an explicit precision namespace will use the accurate namespace unless otherwise stated.

All trigonometric functions below are also available in the degrees and radians sub-namespaces, and will use the corresponding angle units. If an angle namespace isn’t explicitly specified, the functions will use degrees by default.

Return typeDescription
float#sin(float# x)

Sine function.

Uses the fast namespace by default.
]-∞, +∞[ ⟶ [-1, 1]

float#cos(float# x)

Cosine function

Uses the fast namespace by default.
]-∞, +∞[ ⟶ [-1, 1]

float#tan(float# x)

Tangent function.
]-∞, +∞[ ⟶ [-∞, +∞]

float#asin(float# x)

Arc-sine : returns the inverse of the sin() function : asin(sin(x)) = x
The fast version is faster, but gives a lower precision result.
[-1, 1] ⟶ [-180, +180] | [-π, +π]

float#acos(float# x)

Arc-cosine : returns the inverse of the cos() function : acos(cos(x)) = x
[-1, 1] ⟶ [-180, +180] | [-π, +π]

float#atan(float# x)

Arc-tangent : returns the inverse of the tan() function : atan(tan(x)) = x
[-∞, +∞] ⟶ [-180, +180] | [-π, +π]

float#atan2(float# x,float# y)

Signed arc-tangent: like tan(), but uses the sign of y to determine which quadrant the angle lies on
]-∞, +∞[ ⟶ [-180, +180] | [-π, +π]

 

Rotation, orientation, & angles

Return typeDescription
float3
float3
float3
rotate(float3 v, float3 axis, float angle)
degrees.rotate(float3 v, float3 axis, float angle)
radians.rotate(float3 v, float3 axis, float angle)

 

Returns the vector v rotated around axis by angle.
v and axis are float3 vectors, angle is the angle in degrees by default (can be negative).The functions in the degrees and radians namespace expect the angle input to be in that respective unit.Ex:
rotate(float3(1,0,0), float3(0,1,0), 180); will return float3(-1,0,0) (rotates float3(1,0,0) along the y axis float3(0,1,0) by 180 degrees, leading to the opposite vector float3(-1,0,0).
rotate(float3(1,0,0), float3(0,1,0), 90); will return float3(0,0,1).
radians.rotate(float3(1,0,0), float3(0,1,0), pi); will return float3(-1,0,0) (180 degrees rotation).
radians.rotate(float3(1,0,0), float3(0,1,0), pi/2); will return float3(0,0,1) (90 degrees rotation).

float#deg2rad(float# angle)

 

deg2rad(a) converts the input angle a from degrees to radians.
deg2rad(90); will return pi/2.
deg2rad(123.456); will return 2.1547137.

float#rad2deg(float# angle)

 

rad2deg(a)converts the input angle a from radians to degrees.
rad2deg(pi/2); will return 90.
rad2deg(1.23456); will return 70.735.

orientationorientation_mult(orientation a, orientation b)

 

Combines orientations a and b.
Transforming a vector by the returned orientation will be equivalent to transforming it by orientation b, then transforming the result by orientation a.

float3 x = rotate(v, orientation_mult(a, b));
// Is equivalent to:
float3 x = rotate(rotate(v, b), a);

It is useful to combine orientations coming from different sources, for example:

orientation a = scene.orientation_f(Velocity); // rotation to orient "forward" to point towards "Velocity"
orientation b = scene.orientation_ea(float3suf(0, self.lifeRatio * 360*4, 0)); // spin along the Y axis over the lifetime of the particle
orientation x = orientation_mult(a, b); // combine both to get the final orientation

To create orientations, see the scene namespace.

orientationorientation_invert(orientation a)

 

Inverts orientations a.
The returned orientation cancels out orientation a. Transforming a vector by a, then transforming the result by orientation_invert(a) will give back the original vector.
Multiplying orientation a with orientation_invert(a) will give the identity orientation (scene.orientation_from_ea(0,0,0)).
To create orientations, see the scene namespace.

 

Colors

Return typeDescription
float#
float#
float#
float#
linear2srgb(c)
srgb2linear(c)
fast.linear2srgb(c)
fast.srgb2linear(c)

 

linear2srgb(c) converts the input color c from linear space to sRGB space.

srgb2linear(v)converts the input color c from sRGB space to linear space.

The ‘fast’ versions use an approximation (the absolute precision is under 0.001), whereas the non-fast versions use the real sRGB piecewise-curve conversion.Works for both float3 RGB and float4 RGBA values.

float#
float#
rgb2hsv(c)
hsv2rgb(c)
.rgb2hsv(c) converts the input color c from RGB space to HSV space.hsv2rgb(v)converts the input color c from HSV space to RGB space.The converters support HDR values.For the HSV color-space, the H-value (hue) is wrapped from 0 to 1 (1 means 360°), the S-value (saturation) is clipped from 0 to 1 and the V-value (intensity) is positive.Works for both float3 RGB and float4 RGBA values.
float3
float3
blackbody(t)
fast.blackbody(t)

 

Returns the normalized RGB chromaticity color of the emission spectrum of a blackbody at the specified temperatureThe input value should be a temperature in degrees kelvin. For example, 800 will give a red color, 3000 will give an orange/yellow color, 5000/6000 will give a white color, and higher temperatures will give a blue color. RGB colors returned are in linear space‘, not in sRGB space.
Can be very useful for ‘physically correct’ lava/fire effects.

The ‘fast’ version uses a different algorithm (a polynomial fit on the final RGB curves) than the regular version (which uses a polynomial fit of the chromaticity-space planckian locus), is roughly twice faster, but much less precise (although it’s probably fine for most applications).

 

Here’s the RGB comparison between the regular and fast versions:

Planckian locus vs poly-fit

 

The two are virtually identical. Only when plotting the actual RGB curves you start seeing a difference:

blackbody() : Planckian locus, polynomial fit in chroma spacefast.blackbody() : polynomial fit in RGB spaceRelative error between blackbody() and fast.blackbody(), magnified 10 times
blackbody()fast.blackbody()Rel. error times 10

 

Conditional selection

Return typeDescription
#select(a, b, bool# c)

 

Returns a or b depending on the value of c.

c should be the boolean result of a compare operation, or function returning bool.
c can a bool, bool2, bool3, or bool4.

Ex: select(float3(0), float3(1,2,3), x <= y); will return float3(1,2,3) if x <= y, otherwise it will return float3(0).

#iif(bool# c, b, a)

 

iif: Inline IFReturns a or b depending on the value of c. Like select, but reversed, syntactically closer to the syntax of an if/else block.c should be the boolean result of a compare operation, or function returning bool.
c can a bool, bool2, bool3, or bool4.Ex: iif(x <= y, float3(1,2,3), float3(0)); will return float3(1,2,3) if x <= y, otherwise it will return float3(0).

 

Z-order curves

Return typeDescription
intmorton_encode2(int2 a)

 

Returns the 32-bit integer morton-encoded (z-order) representation of the 2D integer vector a.
Interleaves the bits from the 2 lanes of the input vector into groups of 2 bits in the output value.
As the return value is 32-bits, the input value should be in the [0, 65535] range.

intmorton_encode3(int3 a)

 

Returns the 32-bit integer morton-encoded (z-order) representation of the 3D integer vector a.
Interleaves the bits from the 3 lanes of the input vector into groups of 3 bits in the output value.
As the return value is 32-bits, the input value should be in the [0, 1023] range.

int2morton_decode2(int a)

 

Returns the 2D integer vector resulting from decoding the morton-encoded (z-order) 32-bit integer value a.
De-interleaves groups of 2 bits into the 2 lanes of the output vector.
As the input value is 32-bits, the return value will be in the [0, 65535] range.

int3morton_decode3(int a)

 

Returns the 3D integer vector resulting from decoding the morton-encoded (z-order) 32-bit integer value a.
De-interleaves groups of 3 bits into the 3 lanes of the output vector.
As the input value is 32-bits, the return value will be in the [0, 1023] range.

 

Derivation & integration

Return typeDescription
float#dxdt(float# a)

 

Returns the analytical time-based partial derivative of a.
It is a similar concept to ddx() and ddy() in shader languages, except it’s based on time instead of screen position.
 
Treats a as a function, finds all its parameters that vary based on time, and computes the partial derivative of that function over time.
It will walk all the expressions used to compute a, so this can walk back the script, and go back out into the nodegraph as well.
 
Plugging the particle position into a script node, and doing dxdt(Position) will give the particle velocity.
 
If the compiler isn’t able to analytically derive a, it will fallback to the finite-difference dxdT function.
If the compiler is able to analytically integrate a, no additional per-particle storage will be created.

float#dxdT(float# a)

 

Returns the finite-difference time-based partial derivative of a.
It is a similar concept to ddx() and ddy() in shader languages, except it’s based on time instead of screen position.
 
Treats a as a function with a time parameter, and computes (a(t) - a(t - dt)) / dt
Can be implemented manually by dxdF(a) / scene.dt (dxdT performs extra-checks when dt is zero)
 
Creates an additional per-particle storage to store the previous frame’s value of a: a(t - dt).
Used as a fallback for dxdt() when the compiler is not able to compute an analytical derivative.

float#dxdF(float# a)

 

Returns the frame-based partial derivative of a.
It is a similar concept to ddx() and ddy() in shader languages, except it’s based on frames instead of screen position.
 
Returns the value of a at the current frame, minus the value of a had in the previous frame.
Plugging the particle position into a script node, and doing dxdF(Position) will give the particle move-offset vector for this frame.
 
Creates an additional per-particle storage to store the previous frame’s value of a.

float#ixdt(float# a)

 

Returns the analytical time-based integral of a.
 
If the compiler isn’t able to analytically integrate a, it will fallback to the ixdT function.
If the compiler is able to analytically integrate a, no additional per-particle storage will be created.

float#ixdT(float# a)

 

Returns the time-based integral of a computed with cumulative summations each frame.
 
Creates an additional per-particle storage to store the accumulator.

 

Was this article helpful to you? Yes No

How can we help?