Skip to content

Functions callable from a kernel

SyntaxDescriptionNote
Falloff(d)Calling a helper functionThat helper function does not need [Kernel].
Mix(a, b)Helper function taking 2 arguments
static Color4 Dim(Color4 c, float k)Helper function taking and returning Color4
static float Pick(Vector3 v, bool first)Helper functions with several parameter types
static float Half(float v) => v * 0.5f;Expression-bodied helper function
Mathf.Abs(n), Mathf.Min(n, m), Mathf.Clamp(n, m, k)Integer versions of Mathf
Gpu.Pack16x2(v)Packing 2 valuesPacked, each one keeps up to 65536 steps.
Gpu.Unpack16x2(c)Unpacking a packed value

Of the members of Mathf, Vector2, Vector3, Vector4, and Gpu, only those listed in this table can be written.

The “Difference from C#” column carries these marks:

  • Adjusted / The compiler rewrites the expression so it produces the same value.
  • Differs / A difference remains even after rewriting.
SyntaxDescriptionDifference from C#
Mathf.Abs(f)Absolute value
Mathf.Acos(f)Arccosine
Mathf.Asin(f)Arcsine
Mathf.Atan(f)Arctangent
Mathf.Atan2(f, g)Angle from y, x
Mathf.Ceil(f)Ceiling
Mathf.CeilToInt(f)Rounds up to an integer
Mathf.Clamp(f, g, h)Clamp between a lower and upper boundAdjusted
Mathf.Clamp01(f)Clamp to 0..1Adjusted
Mathf.Cos(f)Cosine
Mathf.Deg2RadDegrees-to-radians factor
Mathf.DeltaAngle(ang, ang2)The difference between two angles (folded into -180..180)Adjusted
Mathf.Exp(f)Power of e
Mathf.Floor(f)Floor
Mathf.FloorToInt(f)Rounds down to an integer
Mathf.InverseLerp(f, g, h)Where the value falls between a and b (0..1)Adjusted
Mathf.Lerp(f, g, h)Linear interpolation (t is clamped to 0..1)Adjusted
Mathf.LerpAngle(ang, ang2, h)Linear interpolation between angles (turns the short way; t is clamped to 0..1)Adjusted
Mathf.LerpUnclamped(f, g, h)Linear interpolation (t is not clamped)
Mathf.Log(f)Natural logarithm
Mathf.Log(f, g)Logarithm with a specified baseDiffers
Mathf.Log10(f)Base-10 logarithm
Mathf.Max(f, g)The larger one
Mathf.Min(f, g)The smaller one
Mathf.MoveTowards(f, g, h)Moves toward target by at most maxDelta (never overshoots)Adjusted
Mathf.MoveTowardsAngle(ang, ang2, h)Moves an angle toward target by at most maxDelta (turns the short way)Adjusted
Mathf.PIPi
Mathf.PingPong(f, g)Travels back and forth between 0 and lengthAdjusted
Mathf.Pow(f, g)PowerDiffers
Mathf.Rad2DegRadians-to-degrees factor
Mathf.Repeat(f, g)Wrap within 0..length (remainder)Adjusted
Mathf.Round(f)Round to nearest (0.5 rounds to even)
Mathf.RoundToInt(f)Rounds to the nearest integer (exactly half goes to the even side)
Mathf.Sign(f)Sign (0 counts as positive, returns 1)Adjusted
Mathf.Sin(f)Sine
Mathf.SmoothStep(f, g, h)Smooth interpolation (zero velocity at both ends)Adjusted
Mathf.Sqrt(f)Square root
Mathf.Tan(f)Tangent
SyntaxDescriptionDifference from C#
Vector2.Distance(v, w)Distance between 2 points
Vector2.Dot(v, w)Dot product
Vector2.Lerp(v, w, f)Linear interpolation (t is clamped to 0..1)Adjusted
Vector2.LerpUnclamped(v, w, f)Linear interpolation (t is not clamped)
Vector2.Max(v, w)The larger value per component
Vector2.Min(v, w)The smaller value per component
Vector2.one(1, 1)
Vector2.right(1, 0)
Vector2.up(0, 1)
Vector2.zero(0, 0)
v.magnitudeLength
v.normalizedDirection normalized to length 1 (returns (0,0) if length is 0)Adjusted
v.sqrMagnitudeSquared length (no square root)
SyntaxDescriptionDifference from C#
Vector3.Cross(a, b)Cross product (the direction perpendicular to both)
Vector3.Distance(a, b)Distance between 2 points
Vector3.Dot(a, b)Dot product
Vector3.Lerp(a, b, f)Linear interpolation (t is clamped to 0..1)Adjusted
Vector3.LerpUnclamped(a, b, f)Linear interpolation (t is not clamped)
Vector3.Max(a, b)The larger value per component
Vector3.Min(a, b)The smaller value per component
Vector3.forward(0, 0, 1)
Vector3.one(1, 1, 1)
Vector3.right(1, 0, 0)
Vector3.up(0, 1, 0)
Vector3.zero(0, 0, 0)
a.magnitudeLength
a.normalizedThe direction with length 1 (zero length gives (0,0,0))Adjusted
a.sqrMagnitudeSquared length (no square root)
SyntaxDescriptionDifference from C#
Vector4.Distance(p, q)Distance between 2 points
Vector4.Dot(p, q)Dot product
Vector4.Lerp(p, q, f)Linear interpolation (t is clamped to 0..1)Adjusted
Vector4.LerpUnclamped(p, q, f)Linear interpolation (t is not clamped)
Vector4.Max(p, q)The larger value per component
Vector4.Min(p, q)The smaller value per component
Vector4.one(1, 1, 1, 1)
Vector4.zero(0, 0, 0, 0)
p.magnitudeLength
p.normalizedThe direction with length 1 (zero length gives (0,0,0,0))Adjusted
p.sqrMagnitudeSquared length (no square root)
SyntaxDescriptionDifference from C#
prev.heightThe number of cells down this buffer
prev.widthThe number of cells across this buffer
SyntaxDescriptionDifference from C#
Gpu.Hash(id.X, id.Y)Mixes two integers into one (used to build a value from a cell’s coordinates)
Gpu.Hash(n)Mixes an integer into another integer (the same input always gives the same value)
Gpu.Noise(v)Smooth noise (0..1, interpolated with a direction chosen per lattice point)
Gpu.OutHeightThe number of cells down the destination buffer
Gpu.OutWidthThe number of cells across the destination buffer
Gpu.Pack16x2(v)Pack 2 values into 1 cell (65536 steps each)
Gpu.Random01(n)A value in 0..1 (the same input always gives the same value)
Gpu.Unpack16x2(c)Unpack a value packed by Pack16x2
SyntaxDescriptionDifference from C#
Color4.Lerp(c, c2, h)Interpolate between two colors (t is clamped to 0..1)Adjusted
c.RGBThe 3 color components (without the alpha)

A static method called from a kernel is emitted alongside it as a shader function.

using UnityEngine;
using Tsukimi;
public class ParCallHelper : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
static float Falloff(float d) { return Mathf.Clamp01(1f - d * d); }
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
float d = (id.X - 32) * 0.05f;
return new Color4(Falloff(d), 0f, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}
using UnityEngine;
using Tsukimi;
public class ParHelperTwoArgs : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
static float Mix(float a, float b) { return a * 0.5f + b * 0.5f; }
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
return new Color4(Mix(prev[id].R, prev[id].G), 0f, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

Helper function taking and returning Color4

Section titled “Helper function taking and returning Color4”
using UnityEngine;
using Tsukimi;
public class ParHelperColor4 : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
// Helper function parameters and return values can also be Color4
static Color4 Dim(Color4 c, float k)
{
return c * k;
}
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
return Dim(prev[id], 0.5f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

Helper functions with several parameter types

Section titled “Helper functions with several parameter types”

Parameters and return values can be float int bool Color4 KernelId Vector2 Vector3 Vector4.

using UnityEngine;
using Tsukimi;
public class ParHelperTypes : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
// Parameters and return values can be float, int, bool, Color4, KernelId, Vector2, Vector3, or Vector4
static float Pick(Vector3 v, bool first)
{
return first ? v.x : v.y;
}
static float Weight(KernelId k)
{
return (k.X + k.Y) * 0.01f;
}
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
Vector3 v = new Vector3(prev[id].R, prev[id].G, 0f);
float t = Pick(v, id.X > 32) * Weight(id);
return new Color4(t, 0f, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}
using UnityEngine;
using Tsukimi;
public class ParHelperExpressionBody : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
// A helper function can also be written with =>
static float Half(float v) => v * 0.5f;
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
return new Color4(Half(prev[id].R), 0f, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

Mathf.Abs Mathf.Min Mathf.Max Mathf.Clamp compute in integers when called with integers.

using UnityEngine;
using Tsukimi;
public class ParMathfIntOverloads : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
// Called with integers, the computation stays in integers
int a = Mathf.Abs(id.X - 32);
int b = Mathf.Min(a, 8);
int c = Mathf.Max(b, 2);
int d = Mathf.Clamp(c, 0, 4);
return new Color4(d * 0.25f, 0f, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

One cell is 4 components of 8 bits each (256 steps).

using UnityEngine;
using Tsukimi;
public class ParPackTwoValues : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
Vector2 fine = new Vector2(prev[id].R, prev[id].G);
return Gpu.Pack16x2(fine);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

A packed value can be split back into the original 2 with Gpu.Unpack16x2.

using UnityEngine;
using Tsukimi;
public class ParPackRoundtrip : TsukimiBehaviour
{
private GpuBuffer2D current;
private GpuBuffer2D next;
void Start()
{
current = Gpu.Buffer(64, 64);
next = Gpu.Buffer(64, 64);
}
[Kernel]
static Color4 Step(KernelId id, GpuBuffer2D prev)
{
Vector2 fine = new Vector2(0.5f, 0.25f);
Color4 packed = Gpu.Pack16x2(fine);
Vector2 back = Gpu.Unpack16x2(packed);
return new Color4(back.x, back.y, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}