Scripting reference 1110

From PopcornFX
(Redirected from Scripting reference)
Jump to: navigation, search

In PopcornFX, particle behavior is controlled by short programs called "scripts". These include the "Spawn scripts", "Evolve scripts" and "Layer Scripts".
The scripts are edited inside the PopcornFX editor with the Script editor

This page is for version v1.11.0 and above
For the latest version of PopcornFX, see: Scripting reference
For previous versions of PopcornFX, see the following pages:


Overview

The popcorn-script syntax borrows most of its concepts from a mix between C++ and high-level shader languages such as GLSL or HLSL.

Every name/symbol in popcorn-scripts is case-sensitive, and each statement must end with a semicolon.

For the language syntax reference, see the Scripting language reference page.


Particle-related functions and variables

In the following tables you will find an extensive list of things you can use inside a particle-script. Sometimes a link will be provided to a page that contains more details on a specific item.

How to read the tables:

  • The Spawn column tells which of these are available inside a particle Spawn-script.
  • The Evolve column tells which of these are available inside a particle Evolve-script.
  • R means you can read the variable.
  • RW means you can read AND write the variable.


Optional parameters are written inside brackets.

For example:
SamplerName.remapDensity(float2 uv [, int filterMode [, int wrapMode]])

Means you have three ways to call the 'remapDensity' function:

MySampler.remapDensity(uv);
MySampler.remapDensity(uv, textureFilter.Point);
MySampler.remapDensity(uv, textureFilter.Point, textureFilter.Clamp);


Whereas:
spatialLayers.LayerName.FieldName.sumKernel(float3 center, float radius, samplerCurve1D kernelSampler)

Means there is only a single way to call the 'sumKernel' function:

spatialLayers.MyLayer.MyField.sumKernel(center, radius, MyCurve);


Particle spawn and evolve scripts

Particle

Spawn Evolve type description
Fields
RW RW all the Particle fields particle fields
  RW float LifeRatio

Life-ratio of the particle, in the [0, 1] range. Does not exist inside Spawn-scripts.

RW RW float Life

Life duration of the particle. virtual particle field, for scripting convenience, maps to 1.0 / InvLife

  R float Age

Age of the particle in seconds

  R float dt

length of the simulation frame in seconds

ParentFields
R   all the Particle fields particle parent-fields
Functions
    void kill(int condition)

kills the particle if 'condition' is not false. Not available in spawn-scripts. To instant-kill inside a spawn-script, use Life = 0;


Spawner

Spawn Evolve type description
R   float spawner.Age

Time in seconds the spawner has been spawning particles. Useful for infinite spawner whose liferatio stays at zero. (Was SpawnerRunningTime before v1.8.0)

R   float spawner.Life

Duration of the spawner, in seconds

R   float spawner.LifeRatio

Life-ratio of the spawner, in the [0, 1] range. (Was SpawnerLifeRatio before v1.8.0)

R   float spawner.EmittedCount

number of particles already emitted by the spawner before it spawned this-one

R   float spawner.SpawnRate

number of particles emitted per spawn metric (per second, per world unit, or per custom metric, depending on the spawner's settings)

R   float spawner.SpawnCount

total number of particles the spawner will emit (if available, otherwise zero)

R   float spawner.BaseSpawnRate

number of particles emitted per spawn metric, before being weighted by the spawn flux and layer script

R   float spawner.BaseSpawnCount

total number of particles the spawner will emit (if available, otherwise zero), before being weighted by the spawn flux and layer script

R   float spawner.FirstSpawnDelay

returns the value of the 'FirstSpawnDelay' property in the parent particle spawner action layer or trail evolver evolver spawner.


Events

Spawn Evolve type description
    all the Particle events particle events
    void EventName.trigger(int condition)

triggers the event based on 'condition'. 'condition' must be 0 or -1, or the result of a compare (ex: MyEvent.trigger(LifeRatio > 0.5); )
Spawns at the current Position particle field, and Velocity oriented if it exists.
Never broadcasts the event to the game engine.

    void EventName.trigger(int condition, float3 position, float3 forwardAxis, float3 upAxis)

Like .trigger(cond), but with explicit position and axis for orientation (instead of Position and Velocity)

    void EventName.broadcast(int condition) Experimental

Like .trigger(cond), except it also forces broadcasting of the event to the game engine, as long as the event's 'Broadcast' property is enabled.

    void EventName.broadcast(int condition, float3 position, float3 forwardAxis, float3 upAxis) Experimental

Like .trigger(cond, pos, fwd, up) but .broadcast.

    void Trigger(int eventId, int condition) Deprecated

triggers the event referenced by 'eventId', which is the zero-based index of the desired event in the event list, based on 'condition'. 'condition' must be 0 or -1, or the result of a compare (ex: Trigger(select(0, 1, Position.y < 0), LifeRatio > 0.5); --> when the LifeRatio goes above 0.5, if the particle is above the plane on y = 0, will trigger the first event, if it's below or on the plane, will trigger the second event in the event-list.)

Layer scripts

See the Layer page for how to create and use layer scripts


Spawner

Layer spawn-scripts not yet available. In the current PopcornFX SDK you can only use layer evolve scripts.

Spawn Evolve type description
  R float Age

Time in seconds the spawner has been spawning particles (at the beginning of the frame)

RW R float Life

Duration of the spawner, in seconds

  R float LifeRatio

Life-ratio of the spawner, in the [0, 1] range (at the beginning of the frame)

  R float EmittedCount

Number of particles already emitted by the spawner (at the beginning of the frame)

  R float LiveCount

v1.9.0 Estimated number of particles emitted by the spawner that are still alive (at the beginning of the frame)

  RW float Flux

Base value each frame is 1.0, you can write to this to weight the spawn rate by a custom value. Setting it to 2.0 will make the spawner emit twice as many particles as its base value.

  R float SpawnRate

number of particles emitted per spawn metric (per second, per world unit, or per custom metric, depending on the spawner's settings)

  R float SpawnCount

total number of particles the spawner will emit (if available, otherwise zero)

RW R float BaseSpawnRate

number of particles emitted per spawn metric, before being weighted by any spawn flux

RW R float BaseSpawnCount

total number of particles the spawner will emit (if available, otherwise zero), before being weighted by any spawn flux

RW R float FirstSpawnDelay

returns the value of the 'FirstSpawnDelay' property in the parent particle spawner action layer.

R R float3 Position

Position of the layer at the end of the current frame.

R R float3 PrevPosition

Position of the layer at the beginning of the current frame.

R R float3 Orientation

Orientation of the layer at the end of the current frame. (represented as euler angles in radians)

R R float3 PrevOrientation

Orientation of the layer at the beginning of the current frame. (represented as euler angles in radians)

R R float3 Velocity

v1.9.0 Velocity of the layer at the end of the current frame. (units per second)

R R float3 PrevVelocity

v1.9.0 Velocity of the layer at the beginning of the current frame. (units per second)

RW RW float3 PositionOffset

Position offset of the layer at the end of the current frame. Defaults to zero

RW RW float3 PrevPositionOffset

Position offset of the layer at the beginning of the current frame. Defaults to zero

RW RW float3 OrientationOffset

Orientation offset of the layer at the end of the current frame. Defaults to zero. (represented as euler angles in radians)

RW RW float3 PrevOrientationOffset

Orientation offset of the layer at the beginning of the current frame. Defaults to zero. (represented as euler angles in radians)


Common to particle and layer scripts

Attributes

Spawn Evolve type description
R R all the particle attributes
Special attributes : Camera
R R float3 ViewPosition Deprecated v1.10.0, use the view.position() function instead

If the editor sees your effect has this attribute, it will automatically fill it each frame with the current camera position.
You will still have to bind the correct values to this attribute inside your engine (UE4/Unity/in-house engine)

R R float3 ViewDirection Deprecated v1.10.0, use the view.axisForward() function instead

If the editor sees your effect has this attribute, it will automatically fill it each frame with the current camera direction.
You will still have to bind the correct values to this attribute inside your engine (UE4/Unity/in-house engine)

R R float3 ViewForward Deprecated v1.10.0, use the view.axisForward() function instead

If the editor sees your effect has this attribute, it will automatically fill it each frame with the current camera 'forward' vector.
You will still have to bind the correct values to this attribute inside your engine (UE4/Unity/in-house engine)

R R float3 ViewSide Deprecated v1.10.0, use the view.axisSide() function instead

If the editor sees your effect has this attribute, it will automatically fill it each frame with the current camera 'side' vector.
You will still have to bind the correct values to this attribute inside your engine (UE4/Unity/in-house engine)

R R float3 ViewUp Deprecated v1.10.0, use the view.axisUp() function instead

If the editor sees your effect has this attribute, it will automatically fill it each frame with the current camera 'up' vector.
You will still have to bind the correct values to this attribute inside your engine (UE4/Unity/in-house engine)


Samplers

Attribute-samplers cannot currently be accessed during evolve. If you do try to access them, you will instead get the values of the original sampler, as defined in the effect, NOT the actual sampler overridden by the game.
Regular samplers work fine in any script, but cannot be changed in-game.

Spawn Evolve type description
R ~ all the Particle samplers particle samplers
curve sampler Curve sampler
  ~ float# SamplerName.sample(float cursor)

Samples the curve sampler curve at x=cursor. Return type is a float vector whose dimension matches the curve dimension. a 1D curve will return a float, 3D curve will return a float3, etc...

  ~ float# SamplerName.sampleCDF(float cursor)

v1.9.0 Treats the curve sampler curve as a Probability Density Function (PDF), and samples its Cumulative Density Function (CDF) at x=cursor. Only works for 'float' curves (single channel / 1D), and curves whose "IsDensityCurve" property has been checked. Useful to get custom random distributions by doing Curve.sampleCDF(rand(0,1))

  ~ float# SamplerName.derive(float cursor)

v1.10.0 Computes the derivative of the curve sampler curve at x=cursor. Return type is a float vector whose dimension matches the curve dimension. Each xyzw element of the result will contain the derivative of each of the separate curve components.

  ~ float# SamplerName.integrate(float cursorStart, float cursorEnd)

Computes the integral of the curve sampler curve between x0=cursorStart and x1=cursorEnd. Return type is a float vector whose dimension matches the curve dimension. Each xyzw element of the result will contain the integral of each of the separate curve components.

double-curve sampler Double-curve sampler
  ~ float# SamplerName.sample(float cursor, float ratio)

Samples the double-curve sampler double-curve at x=cursor, and interpolates between the results from each curve using ratio which should be in the [0,1] range.

shape sampler Shape sampler
  ~ int3 SamplerName.sampleParametricCoords()

Samples a random location identifier on the shape sampler shape. The resulting parametric coordinate then be passed to the other sampling functions.

  ~ float3 SamplerName.samplePosition([ int3 pCoords ])

Samples a position on the shape sampler shape. Accepts an optional parametric coordinate. If no pCoord is provided, will sample a random location.

  ~ float3 SamplerName.sampleNormal([ int3 pCoords ])

Samples a normal on the shape sampler shape. Accepts an optional parametric coordinate. If no pCoord is provided, will sample a random location.

  ~ float4 SamplerName.sampleTangent([ int3 pCoords ]) Only available for 'Mesh' shapes

Samples a tangent on the shape sampler shape. Accepts an optional parametric coordinate. If no pCoord is provided, will sample a random location. Sampled tangent contains a sign-flip in its 'w' component to take into account tangent-basis mirroring.

  ~ float2 SamplerName.sampleTexcoord([ int3 pCoords ]) Only available for 'Mesh' shapes

Samples a texture-coordinate on the shape sampler shape. Accepts an optional parametric coordinate. If no pCoord is provided, will sample a random location. additional functions sampleTexcoord0 to sampleTexcoord9 are declared, to sample different explicit UV streams.

  ~ float4 SamplerName.sampleColor([ int3 pCoords ]) Only available for 'Mesh' shapes

Samples a color on the shape sampler shape. Accepts an optional parametric coordinate. If no pCoord is provided, will sample a random location. additional functions sampleColor0 to sampleColor9 are declared, to sample different explicit Color streams.

  ~ float3 SamplerName.sampleVelocity([ int3 pCoords ])

Samples the instantaneous surface-velocity of the shape sampler shape. Accepts an optional parametric coordinate. If no pCoord is provided, will sample a random location.

  ~ float SamplerName.surface()

Returns the surface of the shape sampler shape.

  ~ float SamplerName.volume()

Returns the volume of the shape sampler shape.

  ~ float SamplerName.radius()

Returns the radius of the shape sampler shape if it's a sphere, complexEllipsoid, capsule, cone, or cylinder. If not, returns zero.

  ~ float SamplerName.innerRadius()

Returns the innerRadius of the shape sampler shape if it's a sphere, complexEllipsoid, capsule, or cylinder. If not, returns zero.

  ~ float SamplerName.height()

Returns the height of the shape sampler shape if it's a capsule, cone, or cylinder. If not, returns zero.

  ~ int SamplerName.vertexCount()

Returns the vertex-count of the shape sampler shape if it's a mesh. If not, returns zero.

  ~ int SamplerName.triangleCount()

Returns the triangle-count of the shape sampler shape if it's a mesh. If not, returns zero.

  ~ int SamplerName.tetraCount()

v1.10.0 Returns the tetrahedron-count of the shape sampler shape if it's a mesh, and contains tetrahedral information (required for volume sampling). If not, returns zero.

  ~ float3 SamplerName.meshScale()

Returns the mesh-scale of the shape sampler shape if it's a mesh. If not, returns zero.

  ~ float3 SamplerName.boxDim()

Returns the dimensions of the shape sampler shape if it's a box. If not, returns zero.

  ~ int SamplerName.type()

Returns the type of the shape sampler shape. Can be any of the following:

  1. shapeType.Box
  2. shapeType.Sphere
  3. shapeType.ComplexEllipsoid
  4. shapeType.Cylinder
  5. shapeType.Capsule
  6. shapeType.Cone
  7. shapeType.Plane
  8. shapeType.Mesh
  9. shapeType.Spline
  10. shapeType.Collection
  11. shapeType.Sweep

  ~ float3 SamplerName.position()

Returns the position of the shape sampler shape.

  ~ float3 SamplerName.axisUp()

Returns the up axis of the shape sampler shape.

  ~ float3 SamplerName.axisSide()

Returns the side axis of the shape sampler shape.

  ~ float3 SamplerName.axisForward()

Returns the forward axis of the shape sampler shape.

  ~ int3 SamplerName.buildParametricCoordsMesh(int vertexId)

v1.10.0 Allows to manually build parametric coordinates on a mesh shape sampler mesh shape setup for vertex sampling.
'vertexId' is the index of the vertex to sample. it's in the [0,Shape.vertexCount()-1] range. If an invalid index is given (greater than Shape.vertexCount()-1), the sampling functions that get passed this parametric coordinate will clamp the vertexId to Shape.vertexCount()-1.

  ~ int3 SamplerName.buildParametricCoordsMesh(int triangleId, float2 barycentricCoordinates)

Allows to manually build parametric coordinates on a mesh shape sampler mesh shape setup for surface sampling.
'triangleId' is the index of the triangle to sample. it's in the [0,Shape.triangleCount()-1] range. If an invalid index is given (greater than Shape.triangleCount()-1), the sampling functions that get passed this parametric coordinate will clamp the vertexId to Shape.triangleCount()-1.
'uv' is a float2 UV barycentric coordinate in the selected triangle. it's in the [0,1] range. float2(0.3333) is the triangle center. (uv.x + uv.y) should be lower than 1, otherwise the sample will fall outside the triangle.

  ~ int3 SamplerName.buildParametricCoordsMesh(int tetraId, float3 barycentricCoordinates)

v1.10.0 Allows to manually build parametric coordinates on a mesh shape sampler mesh shape setup for volume sampling.
'tetraId' is the index of the vertex to sample. it's in the [0,Shape.tetraCount()-1] range. If an invalid index is given (greater than Shape.tetraCount()-1), the sampling functions that get passed this parametric coordinate will clamp the vertexId to Shape.tetraCount()-1.
'uvw' is a float3 UVW barycentric coordinate in the selected tetrahedron. it's in the [0,1] range. float3(0.25) is the tetra center. (uv.x + uv.y + uv.z) should be lower than 1, otherwise the sample will fall outside the tetrahedron.

  ~ int3 SamplerName.buildParametricCoordsBox(int faceId, float2 uv)

Allows to manually build parametric coordinates on a box shape sampler box shape setup for Surface sampling.
'faceId' can be one of the following values: [-3, -2, -1, 1, 2, 3]. -1 and 1 map the -X and +X faces, respectively. -2, 2 map the -Y, +Y faces, and -3, 3 map the -Z, +Z faces.
'uv' is a float2 UV coordinate on the selected face. it's in the [0,1] range.

  ~ int3 SamplerName.buildParametricCoordsBox(float3 normalizedPos)

Allows to manually build parametric coordinates on a box shape sampler box shape setup for Volume sampling.
'normalizedPos' is a float3 coordinate in normalized box coordinates. it's in the [-1,1] range.

  ~ int3 SamplerName.buildParametricCoordsSphere(float2 polarAngles, float radius)

Allows to manually build parametric coordinates on a sphere shape sampler sphere shape. Works for both Surface' and Volume sampling.
'polarAngles' is a float2 theta-phi coordinate. it's in the [0,1] range, and gets mapped internally to [0,2*pi].
'radius' is a lerp factor between the sphere's InnerRadius and Radius properties. it's in the [0,1] range.

  ~ int3 SamplerName.buildParametricCoordsCone(float height, float angle [, float radius])

Allows to manually build parametric coordinates on a cone shape sampler cone shape. Works for both Surface' and Volume sampling.
'height' is the normalized cone height. it's in the [0,1] range.
'angle' is the angle around the cone axis. it's in the [0,1] range, and gets mapped internally to [0,2*pi].
'radius' is the distance between the cone center and the cone edge. it's in the [0,1] range. Only for Volume sampling.

  ~ int3 SamplerName.buildParametricCoordsCapsule(float height, float angle, float radius)

Allows to manually build parametric coordinates on a capsule shape sampler capsule shape. Works for both Surface' and Volume sampling.
'height' is a normalized cursor along the capsule height, cap-spheres included. it's in the [0,1] range.
'angle' is the angle around the capsule axis. it's in the [0,1] range, and gets mapped internally to [0,2*pi].
'radius' is a lerp factor between the capsule's InnerRadius and Radius properties. it's in the [0,1] range.

  ~ int3 SamplerName.buildParametricCoordsCylinder(float height, float angle, float radius)

Allows to manually build parametric coordinates on a cylinder shape sampler cylinder shape. Works for both Surface' and Volume sampling.
'height' is the normalized cylinder height. it's in the [0,1] range.
'angle' is the angle around the cylinder axis. it's in the [0,1] range, and gets mapped internally to [0,2*pi].
'radius' is a lerp factor between the cylinder's InnerRadius and Radius properties. it's in the [0,1] range.

  ~ float SamplerName.sampleDistanceField(float3 position)

Samples the distance-field of the shape sampler shape at the specified location.

  ~ int SamplerName.contains(float3 position)

returns true if the shape sampler shape contains the specified position, false otherwise.

  ~ float4 SamplerName.intersect(float3 rayStart, float3 rayDirection, float rayLength)

raytraces the shape sampler shape with the specified ray. returns the hit normal and intersection distance packed in a float4.

  ~ float4 SamplerName.project(float3 position)

Computes the projection of the specified position on the shape sampler shape. returns the vector from position to projected position and projection distance packed in a float4.

  ~ int3 SamplerName.projectParametricCoords(float3 position)

Computes the projection of the specified position on the shape sampler shape. returns the parametric coordinate of the projected location.

texture sampler Texture sampler
  ~ float# SamplerName.sample(float2 uv [, int filterMode [, int wrapMode]])

Samples a texel on the texture sampler texture at the specified UV coordinates. the optional 'filterMode' can be one of the following:

  1. textureFilter.Default
  2. textureFilter.Point
  3. textureFilter.Linear

The optional 'addrMode' can be one of the following:

  1. textureAddr.Default
  2. textureAddr.Clamp
  3. textureAddr.Wrap

  ~ float# SamplerName.sample(float subRectId, float2 uv [, int filterMode [, int wrapMode]])

Samples a texel on the texture sampler texture atlas at the specified sub-rect and UV coordinates.

  ~ float2 SamplerName.remapDensity(float2 uv [, int filterMode [, int wrapMode]])

v1.9.0 This is the old 'sampleDensity' in versions anterior to v1.9.0
Builds a new UV from the input UV so that the final UV distribution matches the density of the texture sampler texture.

  ~ float2 SamplerName.remapDensity(float subRectId, float2 uv [, int filterMode [, int wrapMode]])

v1.9.0 This is the old 'sampleDensity' in versions anterior to v1.9.0
Builds a new UV from the input UV so that the final UV distribution matches the density of the texture sampler texture atlas at the specified sub-rect.

  ~ float2 SamplerName.sampleDensity([int filterMode [, int wrapMode]])

v1.9.0 Builds a random UV coordinate so that the UV distribution matches the density of the texture sampler texture.

  ~ float2 SamplerName.sampleDensity(float subRectId [, int filterMode [, int wrapMode]])

v1.9.0 Builds a random UV coordinate so that the UV distribution matches the density of the texture sampler texture atlas at the specified sub-rect.

  ~ float2 SamplerName.dimensions()

v1.9.0 Returns a float2 containing the texture texel dimensions (can be just an abstract aspect ratio if the sampler is an attribute sampler overriden by the game engine and is a procedural "infinite" texture rather than a physical texture).

turbulence sampler Turbulence sampler
  ~ float3 SamplerName.sample(float3 position)

Samples the default field turbulence sampler turbulence at the specified location. (by default, samples the curl, so it's basically curl-noise)

  ~ float3 SamplerName.sampleCurl(float3 position)

Samples the curl of the turbulence sampler turbulence noise-field at the specified location.

  ~ float3 SamplerName.samplePotential(float3 position)

Samples the potential of the turbulence sampler turbulence noise-field at the specified location.

audio sampler Audio sampler
  ~ float SamplerName.sample(float cursor [, int sampleFilter])

Samples the spectrum sampler spectrum at the specified cursor, which is in the [0,1] range, 0 meaning full-bass and 1 meaning full-treble. sampleFilter can be one of the following:

  1. spectrumFilter.Point
  2. spectrumFilter.Linear
  3. spectrumFilter.Cubic

  ~ float SamplerName.sample(float cursor, float convolution [, int sampleFilter [, int convolutionFilter]])

Samples the spectrum sampler spectrum at the specified cursor, which is in the [0,1] range, 0 meaning full-bass and 1 meaning full-treble. The convolution parameters is in the [0,1] range and allows to smooth the sampled spectrum. The convolutionFilter accepts the same values as the sampleFilter, and tells how to interpolate between the various spectrum 'mipmaps' used by the convolution level.

text sampler Text sampler
  ~ int SamplerName.charCode(int charId)

Samples the text sampler text at the specified character position, and returns the ASCII code of the sampled character.

  ~ int SamplerName.charCode(int2 lineAndCharId)

Samples the text sampler text at the specified line and character position, and returns the ASCII code of the sampled character.

  ~ int SamplerName.charCount(int lineId)

Returns the number of characters at the specified line of the text sampler text.

  ~ int SamplerName.charCount()

Returns the number of characters in the whole text sampler text.

  ~ int SamplerName.lineCount()

Returns the number of lines in the whole text sampler text.


Scene

Spawn Evolve type description
Variables
R R float scene.Time

global date of the current particle medium collection, in seconds. (Was CurrentDate before v1.8.0)

R R float scene.surfaceType.*

All surface types configured in the project-settings 'Scene' panel

R R float scene.collisionFilter.*

All collision filters configured in the project-settings 'Scene' panel

Functions
    float3 scene.axisUp()

constant: up axis (based on the Axis-System).
See #Axis-System helpers.

    float3 scene.axisSide()

constant: side axis (based on the Axis-System).
See #Axis-System helpers.

    float3 scene.axisForward()

constant: forward axis (based on the Axis-System).
See #Axis-System helpers.

    int scene.isRight()

v1.8.2 constant: true (0xFFFFFFFF) if the Axis-System is right handed, or false (0x0) if left handed.
Example: Axis = cross(Velocity, scene.axisUp()) * iif(scene.isRight(), 1, -1);
See #Axis-System helpers.

    float scene.isRightSign()

v1.8.2 constant: 1.0 if the Axis-System is right handed, -1.0 if left handed.
Example: Axis = cross(Velocity, scene.axisUp()) * scene.isRightSign();
See #Axis-System helpers.

    float4 scene.intersect(float3 rayStart, float3 rayDirection, float rayLength [, int collisionFilter])

issues a scene intersection query, returns the intersection normal in xyz, and intersection distance in w.
The optional 'collisionFilter' parameter must be one of the collision filters you configured in the project-settings 'Scene' panel
ex: scene.collisionFilter.StaticGeom, scene.collisionFilter.ConvexHulls, etc...

    int4 scene.intersectExt(float3 rayStart, float3 rayDirection, float rayLength [, int collisionFilter])

issues an extended scene intersection query, returns an int4 containing the packed intersection normal, intersection distance, and surface type.
Use the 'unpack' functions below to extract each one of them.
The optional 'collisionFilter' parameter must be one of the collision filters you configured in the project-settings 'Scene' panel
ex: scene.collisionFilter.StaticGeom, scene.collisionFilter.ConvexHulls, etc...

    float3 scene.unpackNormal(int4 packedISecResult)

takes a packed intersection result returned by scene.intersectExt(), extracts and returns the float3 intersection normal it contains.
Equivalent to scene.intersect(...).xyz

    float scene.unpackDist(int4 packedISecResult)

takes a packed intersection result returned by scene.intersectExt(), extracts and returns the float intersection distance it contains.
Equivalent to scene.intersect(...).w

    int scene.unpackSurfaceType(int4 packedISecResult)

takes a packed intersection result returned by scene.intersectExt(), extracts and returns the int surface-type it contains.
The returned surface-type can be tested against one of the surface-types you configured in the project-settings 'Scene' panel
ex: scene.surfaceType.Grass, scene.surfaceType.Rock, etc...

View

Spawn Evolve type description
Functions
    int view.count()

v1.10.0 returns the number of active cameras/views.
If no camera views are registered by the game engine, returns 0.

    float view.distance(float3 position [, int camIndex])

v1.10.0 returns the distance between 'position' and the camera whose ID is 'camIndex'.
If 'camIndex' is not specified, returns the distance to the closest cam.
If no camera views are registered by the game engine, returns infinity.
ex: view.distance(Position) returns the distance to the closest cam, view.distance(Position, 2) returns the distance to the 3rd cam.

    int view.closest(float3 position [, int n])

v1.10.0 returns the index of the cam closest to 'position'.
If 'n' is specified, returns the index of the 'nth' closest cam. '0' is the closest, '1' is the second closest, '2' is the third closest, etc..
If no camera views are registered by the game engine, returns -1.
ex: view.closest(Position)

    float3 view.position([int camIndex = 0])

v1.10.0 returns the position of the cam whose ID is 'camIndex'. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns float3(infinity).
ex: view.position() or view.position(2)

    float3 view.axisSide([int camIndex = 0])

v1.10.0 returns the side axis of the cam whose ID is 'camIndex'. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns float3(1,0,0).
ex: view.axisSide() or view.axisSide(2)

    float3 view.axisUp([int camIndex = 0])

v1.10.0 returns the up axis of the cam whose ID is 'camIndex'. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns float3(0,1,0).
ex: view.axisUp() or view.axisUp(2)

    float3 view.axisForward([int camIndex = 0])

v1.10.0 returns the forward axis of the cam whose ID is 'camIndex'. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns float3(0,0,1).
ex: view.axisForward() or view.axisForward(2)

    float3 view.project(float3 worldPos [, int camIndex = 0])

v1.10.0 projects the input worldspace coordinate into the clip-space of the cam whose ID is 'camIndex'. If 'camIndex' is not specified, uses the first camera.
Can be useful to get the screenspace-position of a particle.
If no camera views are registered by the game engine, returns float3(0,0,0).
ex: view.project(Position) or view.project(Position, 2)

    float3 view.unproject(float3 clipPos [, int camIndex = 0])

v1.10.0 unprojects to worldspace the input clipspace coordinate of the cam whose ID is 'camIndex'. If 'camIndex' is not specified, uses the first camera.
Can be useful to have a particle stick to a screenspace position by unprojecting the position to worldspace.
If no camera views are registered by the game engine, returns float3(0,0,0).
ex: view.unproject(float3(uv, 0)) or view.unproject(clipPos, 2)

    float3 view.unprojectAxis(float2 clipPos [, int camIndex = 0])

v1.10.0 returns the normalized axis of the ray that goes from the camera origin through the camera plane at coordinates specified in 'clipPos'. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns float3(infinity).
ex: view.unprojectAxis(uv) or view.unprojectAxis(uv, 2)

    int2 view.resolution([int camIndex = 0])

New v1.11.1 returns the resolution of the view in pixels. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns int2(1,1).
A camera rendering in a 1920x1024 viewport will return 'int2(1920,1024)'
Note that this function returns integer values, care must be taken to explicitely cast to float when required, for instance when dividing the x/y values together.

ex: view.resolution() or view.resolution(2)

    float view.aspect([int camIndex = 0])

New v1.11.1 returns the aspect-ratio of the view. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns 1.0.
Equivalent to doing: float aspect = view.resolution(id).x / float(view.resolution(id).y);
ex: view.aspect() or view.aspect(2)

    float view.fovHorizontal([int camIndex = 0])

New v1.11.2 returns the horizontal fov of the view, in radians. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns pi/2 (90 degrees fov).
ex: view.fovHorizontal() or view.fovHorizontal(2)

    float view.fovVertical([int camIndex = 0])

New v1.11.2 returns the vertical fov of the view, in radians. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns pi/2 (90 degrees fov).
ex: view.fovVertical() or view.fovVertical(2)

    float view.fov([int camIndex = 0])

New v1.11.2 returns the fov of the view, in radians. If 'camIndex' is not specified, uses the first camera.
If no camera views are registered by the game engine, returns pi/2 (90 degrees fov).
Equivalent to doing: float fov = max(view.fovHorizontal(), view.fovVertical());
ex: view.fov() or view.fov(2)

To get the fov in degrees:
float fovInDegrees = rad2deg(view.fov());

Spatial layers

Spawn Evolve type description
    all the Spatial layer Spatial layers
Global queries
    int spatialLayers.LayerName.neighborCount(float3 center, float radius)

Returns the number of particles inside the query volume.
If no particles are inside the query volume, returns 0

Field queries
    fieldType spatialLayers.LayerName.FieldName.closest(float3 center, float radius)

Returns the value of 'FieldName' of the closest particle inside the query volume.
If no particles are inside the query volume, returns infinity

    fieldType spatialLayers.LayerName.FieldName.closest(float3 center, float radius, int n [, int cacheSize])

v1.9.0 Returns the value of 'FieldName' of the n-closest particle inside the query volume.
If no particles are inside the query volume, returns infinity

'n' is 0-based, so calling the query with '0' for 'n' will return closest value, calling with '3' will return the 4th closest, etc...
'cacheSize' is an optional performance hint. When not specified, its default value is 4.

    float# spatialLayers.LayerName.FieldName.sum(float3 center, float radius)

Returns the sum of 'FieldName' of all particles inside the query volume.
If no particles are inside the query volume, returns infinity
If the original field is int, int2, int3, or int4, the returned value will actually be a float vector of the same dimension: float, float2, float3 or float4.

    float# spatialLayers.LayerName.FieldName.sumKernel(float3 center, float radius, samplerCurve1D kernelSampler)

Returns the sum of 'FieldName' of all particles inside the query volume, and uses the custom kernel (1D curve sampler curve sampler) to weight each value based on its distance to the query center.
If no particles are inside the query volume, returns infinity
If the original field is int, int2, int3, or int4, the returned value will actually be a float vector of the same dimension: float, float2, float3 or float4.

    float# spatialLayers.LayerName.FieldName.average(float3 center, float radius)

Returns the average value of 'FieldName' of all particles inside the query volume.
If no particles are inside the query volume, returns infinity
If the original field is int, int2, int3, or int4, the returned value will actually be a float vector of the same dimension: float, float2, float3 or float4.

    float# spatialLayers.LayerName.FieldName.averageKernel(float3 center, float radius, samplerCurve1D kernelSampler)

Returns the average value of 'FieldName' of all particles inside the query volume, and uses the custom kernel (1D curve sampler curve sampler) to weight each value based on its distance to the query center.
If no particles are inside the query volume, returns infinity
If the original field is int, int2, int3, or int4, the returned value will actually be a float vector of the same dimension: float, float2, float3 or float4.



Language builtins

Constants

Name Value
pi $ \pi $ ~= 3.14159265359
phi $ \varphi $ ~= 1.61803398875
infinity $ +\infty $


Math functions

Function Plot Notation float int Description Input range $ \longrightarrow $ output range
rand(x,y)
Y N random function, returns a random value 'r' such that x <= r < y $ [-\infty, +\infty] \longrightarrow [x, y[ $
dot(u,v)
$ \vec{u} \cdot \vec{v} $ Y N vector dot-product $ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
cross(u,v)
$ \vec{u} \times \vec{v} $ Y N 3D vector cross-product $ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
reflect(v,n)
ScriptFunc Abs.png $ \vec{v} - 2*\vec{n} * (\vec{v} \cdot \vec{n}) $ Y N reflects (mirrors) the float3 vector 'v' on the plane defined by the float3 normal 'n'. $ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
abs(x)
ScriptFunc Abs.png $ \begin{align} | x | \end{align} $ Y Y absolute value $ [-\infty, +\infty] \longrightarrow [0, +\infty] $
sign(x)
ScriptFunc Sign.png $ \begin{align} \frac{x}{| x |}\end{align} $ Y Y sign function, returns -1 when x <= -0, and +1 when x >= +0 $ [-\infty, +\infty] \longrightarrow [-1], [+1] $
ceil(x)
ScriptFunc Ceil.png $ \lceil x \rceil $ Y N/A ceiling rounding: rounds to the closest integer value >= x $ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
floor(x)
ScriptFunc Floor 0.png $ \lfloor x \rfloor $ Y N/A floor rounding: rounds to the closest integer value <= x $ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
frac(x) ScriptFunc Frac.png $ x % 1 $ Y N/A extracts the fractional part of 'x' $ [-\infty, +\infty] \longrightarrow [0, +1[ $


wavesq(x)
ScriptFunc WaveSquare.png Y N/A square wave function $ [-\infty, +\infty] \longrightarrow [-1, +1] $
wavetri(x)
ScriptFunc WaveTri.png Y N/A triangular wave function $ [-\infty, +\infty] \longrightarrow [0, +1] $
wavesaw(x)
ScriptFunc WaveSaw.png $ x - \lfloor x \rfloor $ Y N/A sawtooth wave function $ [-\infty, +\infty] \longrightarrow [0, +1] $
saturate(x)
ScriptFunc Saturate.png Y N/A clamps 'x' in the [0, 1] range $ [-\infty, +\infty] \longrightarrow [0, +1] $
step(x,y)
ScriptFunc Step.png $ \begin{align} x >= y\end{align} $ Y N step function. evaluates to 0 if x < y, and evaluates to 1 if x >= y $ [-\infty, +\infty] \longrightarrow [0, +1] $


linearstep(a,b,x)
ScriptFunc LinearStep.png $ \begin{align} t=\frac{x-a}{b-a} \end{align} $ Y N v1.10.0 linearstep function. linearly evaluates between 0 to 1 the position of x between a and b. $ [-\infty, +\infty] \longrightarrow [0, +1] $
smoothstep(a,b,x)
ScriptFunc SmoothStep.png $ \begin{align} 3t^2 - 2t^3 \end{align} $ Y N v1.9.0 smoothstep function. smoothly evaluates between 0 to 1 the position of x between a and b. $ [-\infty, +\infty] \longrightarrow [0, +1] $
discretize(x,y)
ScriptFunc Discretize.png Y N discretization function, snaps 'x' to the nearest step, given a step size 'y' $ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
min(x,y)
ScriptFunc Min.png $ \begin{align} min(x, y) \end{align} $ Y Y minimization function: if x < y, returns x, otherwise, returns y $ [-\infty, +\infty] \longrightarrow [-\infty, y] $
max(x,y)
ScriptFunc Max.png $ \begin{align} max(x, y) \end{align} $ Y Y maximization function: if x > y, returns x, otherwise, returns y $ [-\infty, +\infty] \longrightarrow [y, +\infty] $
clamp(x,a,b)
ScriptFunc Clamp.png $ \begin{align} clamp(x, a, b) \end{align} $ Y N v1.8.0 clamp function: if x < a, returns a, otherwise, if x > b, returns b, otherwise, returns x $ [-\infty, +\infty] \longrightarrow [a, b] $
sqrt(x)

fast_sqrt(x)

ScriptFunc Sqrt.png $ \sqrt{x} $ Y N
  • square-root
  • faster square-root, lower precision
$ [0, +\infty] \longrightarrow [0, +\infty] $
rsqrt(x)

fast_rsqrt(x)

ScriptFunc RSqrt.png $ \frac{1}{\sqrt{x}} $ Y N/A
  • reverse square-root
  • faster reverse square-root, lower precision
$ [0, +\infty] \longrightarrow [0, +\infty] $
cbrt(x)

fast_cbrt(x)

ScriptFunc Sqrt.png $ \sqrt[3]{x} $ Y N v1.10.0
  • cube-root
  • faster cube-root, lower precision
$ [0, +\infty] \longrightarrow [0, +\infty] $
length(v)

fast_length(v)

$ \left\| v \right\| $ Y N/A
  • vector length
  • faster vector length, lower precision
$ [-\infty, +\infty] \longrightarrow [0, +\infty] $
normalize(v)

fast_normalize(v)

$ \vec{v} \cdot \frac{1}{ \left\| v \right\| } $ Y N/A
  • vector normalization
  • faster vector normalization, lower precision
$ [-\infty, +\infty] \longrightarrow [-1, +1] $
exp(x)

fast_exp(x)

ScriptFunc Exp.png $ \begin{align} e^x \end{align} $ Y N
  • natural exponential
  • faster natural exponential, lower precision
$ [-\infty, +\infty] \longrightarrow [0, +\infty] $
exp2(x)

fast_exp2(x)

ScriptFunc Exp2.png $ \begin{align} 2^x \end{align} $ Y N
  • base-2 exponential
  • faster base-2 exponential, lower precision
$ [-\infty, +\infty] \longrightarrow [0, +\infty] $
pow(x,y)

fast_pow(x,y)

ScriptFunc Pow.png $ \begin{align} x^y \end{align} $ Y N
  • power function
  • faster power function, lower precision
$ {[0, +\infty], [-\infty, +\infty]} \longrightarrow [-\infty, +\infty] $
log(x)

fast_log(x)

ScriptFunc Ln.png $ \ln \!\left( x \right) $ Y N
  • natural logarithm
  • faster natural logarithm, lower precision
$ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
log2(x)

fast_log2(x)

ScriptFunc Log2.png $ \log_2 \!\left( x \right) $ Y N
  • base-2 logarithm
  • faster base-2 logarithm, lower precision
$ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
rcp(x)

fast_rcp(x)

ScriptFunc Rcp.png $ \frac{1}{x} $ Y N/A
  • inverse
  • faster inverse, lower precision
$ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
sin(x)

fast_sin(x)

ScriptFunc Sin.png $ \begin{align} \sin x \end{align} $ Y N/A
  • sine
  • faster sine, lower precision
$ [-\infty, +\infty] \longrightarrow [-1, +1] $
cos(x)

fast_cos(x)

ScriptFunc Cos.png $ \begin{align} \cos x \end{align} $ Y N/A
  • cosine
  • faster cosine, lower precision
$ [-\infty, +\infty] \longrightarrow [-1, +1] $
sincos(x)

fast_sincos(x)

ScriptFunc SinCos.png $ \begin{align} \sin x \end{align} $ $ \begin{align} \cos x \end{align} $ Y N/A

Warning: could be subject to change.

  • sine/cosine. takes a float value, returns a float2 containing the sine in 'x', and the cosine in 'y'
  • faster sine/cosine, lower precision
$ [-\infty, +\infty] \longrightarrow [-1, +1] $
tan(x)

fast_tan(x)

ScriptFunc Tan.png $ \begin{align} \tan x \end{align} $ Y N/A
  • tangent
  • faster tangent, lower precision
$ [-\infty, +\infty] \longrightarrow [-\infty, +\infty] $
asin(x)

fast_asin(x)

ScriptFunc ASin.png $ \begin{align} \sin^{-1} x \end{align} $ Y N/A
  • arc-sine : returns the inverse of the sin() function : asin(sin(x)) = x
  • fast arc-sine, lower precision
$ [-1, +1] \longrightarrow [-\pi, +\pi] $
acos(x)

fast_acos(x)

ScriptFunc ACos.png $ \begin{align} \cos^{-1} x \end{align} $ Y N/A
  • arc-cosine : returns the inverse of the cos() function : acos(cos(x)) = x
  • faster arc-cosine, lower precision
$ [-1, +1] \longrightarrow [-\pi, +\pi] $
atan(x)

fast_atan(x)

ScriptFunc ATan.png $ \begin{align} \tan^{-1} x \end{align} $ Y N/A
  • arc-tangent : returns the inverse of the tan() function : atan(tan(x)) = x
  • faster arc-tangent, lower precision
$ [-\infty, +\infty] \longrightarrow [-\pi, +\pi] $
atan2(x,y)

fast_atan2(x,y)

ScriptFunc ATan.png $ \begin{align} \tan^{-1} \!\left( x,y \right) \end{align} $ Y N/A
  • signed arc-tangent like tan(), but uses the sign of 'y' to determine which quadrant the angle lies on
  • faster signed arc-tangent, lower precision
$ [-\infty, +\infty] \longrightarrow [-\pi, +\pi] $


Functions

Function float int Description
vrand()
vrand(inner, outer)
vrand(inner, outer, probabilityCurve)
Y N
random function, stands for "vector-rand", returns a random float3 vector 'v' 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..

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


v1.10.0 (added inner-outer and curve sampler overloads)

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.

60k samples of vrand(0,1) 60k samples of vrand(0.5,1)
vrand(0,1) vrand(0.5,1)


vrand(inner, outer, probabilityCurve) expects the name of a Curve sampler 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.

60k samples of vrand(0,1,MyCurve) 60k samples of vrand(0.5,1,MyCurve) Probability curve used to remap the uniform distribution to a custom non-uniform distribution
vrand(0,1,MyCurve) vrand(0.5,1,MyCurve) 'MyCurve' Probability curve
select(a,b,c)
Y Y
returns 'a' or 'b' depending on the value of 'c'

'c' should be the boolean result of a compare operation, or function returning a true / false result.
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).

logic:

if (c is true)
  return b;
else
  return a;
iif(c,a,b)
Y Y
iif: Inline IF
returns '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 a true / false result.
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).

logic:

if (c is true)
  return a;
else
  return b;
lerp(a,b,t)
Y N
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, 'a' is returned, when 't' equals 1, '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).

logic:

return a + t * (b - a);

equivalent to:

return a * (1-t) + b * t;
smoothlerp(a,b,t)
Y N
v1.9.0 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, 'a' is returned, when 't' equals 1, '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).

logic:

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

equivalent to:

return lerp(a, b, 3*t*t - 2*t*t*t);
randsel(a,b)
randsel(a,b,k)
Y Y
v1.10.0 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 'a'
etc..
The 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:

  return select(a, b, rand(0,1) < k);
within(x,lower,upper)
Y N
returns 1.0f if 'x' is within the [lower, upper] range, returns 0.0f 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.0f.
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).

remap(value, newMin, newMax)
remap(value, oldMin, oldMax, newMin, newMax)
Y Y
v1.8.0

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.0f.
remap(0.5, 0, 0.5, 1.0, 3.0); will return 3.0f.

all(c)
N Y
returns true if ALL elements of vector 'c' are non-zero / not 'false'

'c' can be a boolean result of a compare operator, or any vector. ex:
all(float3(0) < float3(1,2,3)); will return true. all(float3(0) < float3(1,-2,3)); will return false.

logic:

foreach (element e in c)
  if (e == 0)
    return false;
return true;
any(c)
N Y
returns true if ANY element of vector 'c' are non-zero / not 'false'

'c' can be a boolean result of a compare operator, or any vector. ex:
any(float3(0) > float3(1,2,3)); will return false. any(float3(0) > float3(1,-2,3)); will return true.

logic:

foreach (element e in c)
  if (e != 0)
    return true;
return false;
rotate(v, axis, angle)
Y N
returns the vector 'v' rotated around 'axis' by 'angle'.

'v' and 'axis' are float3 vectors, 'angle' is the angle in radians (can be negative).
ex:
rotate(float3(1,0,0), float3(0,1,0), pi); will return float3(-1,0,0) (rotates float3(1,0,0) along the 'y' axis float3(0,1,0) by 180 degrees ('pi' radians), leading to the opposite vector float3(-1,0,0). rotate(float3(1,0,0), float3(0,1,0), pi/2); will return float3(0,0,1).

deg2rad(angle)
rad2deg(angle)
Y N
v1.10.0

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


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

linear2srgb(c)
srgb2linear(c)

fast_linear2srgb(c)
fast_srgb2linear(c)
Y N
New v1.11.0

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 a pow(rgb, 2.2) approximation, whereas the non-fast versions use the real sRGB piecewise-curve conversion.

safe_normalize(v)
safe_normalize(v, vz)
safe_normalize(v, vz, epsilon)

safe_fast_normalize(v)
safe_fast_normalize(v, vz)
safe_fast_normalize(v, vz, epsilon)
Y N/A
v1.5.5+ / v1.6.0

Normalizes the input 'v' vector 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);

logic:

if (length(v) < epsilon)
  return vz;
else
  return normalize(v);
noise(t)
fast_noise(t)
Y N/A
v1.6.0

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

float3suf(side, up, forward)
float3suf(...)
float3sfu(side, forward, up)
float3sfu(...)
Y N
v1.8.2

v1.10.0 (added SFU permutation)
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.

example:

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

example:

 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))

See #Axis-System helpers.

isfinite(v)
isinf(v)
isnan(v)
Y N
v1.10.0

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
  • 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
  • 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

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, spatial queries:

float3 p = spatialLayers.MyLayer.Position.closest(Position);
Position = select(Position, p, all(isfinite(p)));
blackbody(t)
fast_blackbody(t)
Y N
v1.10.0

returns the normalized RGB chromaticity color of the emission spectrum of a blackbody at the specified temperature

The 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:
blackbody() vs fast_blackbody()


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

blackbody() : Planckian locus, polynomial fit in chroma space fast_blackbody() : polynomial fit in RGB space relative error between blackbody() and fast_blackbody(), magnified 10 times
blackbody() fast_blackbody() Rel. error times 10
asfloat(v)
Y Y
v1.9.0

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)
asint(v)
Y Y
v1.9.0

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)


Axis-System helpers

Here is quick list of Axis-System dependent function to help create Axis-System independent effects.

  • Vector swizzling/shuffling s u f (side, up, forward), works same way as x y z, but changes depending on the current axis system:
    • Y-Up system .s => .x .u => .y .f => .z
    • Z-Up system .s => .x .u => .z .f => .y

Examples:

 float3   vec = ...;
 float3   vec_plus_42_up = vec + scene.axisUp() * 42;
 float3   vec_plus_42_up = vec + float3suf(0, 42, 0);
 float3   vec_plus_42_up = vec + float3sfu(0, 0, 42);
 float3   vec_plus_42_up = float3suf(vec.s, vec.u + 42, vec.f);
 float3   vec_plus_42_up = float3sfu(vec.sf, vec.u + 42);
All those vec_plus_42_up gives the same vector for a given Axis System: vec offset by 42.0 on the Up axis (so it adds 42 to Y when Y-Up, or 42 to Z when Z-Up)