Kernel statements and expressions
Forms that compile (69)
Section titled “Forms that compile (69)”Forms that don’t compile (2)
Section titled “Forms that don’t compile (2)”| Syntax | Description | Error | Reason | Alternative |
|---|---|---|---|---|
v %= 2f | Compound assignment with remainder (the same applies to &= |= ^= <<= >>=) | TUKI0001 | undecided | Write it out as v = v % 2f |
+v | Unary plus | TUKI0001 | by design | Remove it (the value does not change) |
Operators by type
Section titled “Operators by type”Color4
Section titled “Color4”| Syntax | Description | Example |
|---|---|---|
new Color4(r, g, b, a) | Construct from 4 floats | Constructing a cell value |
new Color4(rgb, a) | Construct from a Vector3 color and a float alpha | Constructing from 3 components and an alpha |
new Color4(v) | Construct from a Vector4 | Constructing from 4 components |
Color4.White Color4.Black | Constant | Constant color |
c.R c.G c.B c.A | Reading a component | Reading a component |
c.R = 0.5f | Assigning to a component (local variable) | Assigning to a cell component |
a + b | Component-wise sum | Adding cells |
a - b | Component-wise difference | Subtracting cells |
a * 0.5f | Scale each component by a constant | Scaling a cell by a constant |
a * b | Component-wise product | Multiplying cells |
a / 2f | Divide each component by a float | Dividing a cell value |
c += b c -= b c *= 0.5f c *= b c /= 2f | Compound assignment | Compound assignment to a cell value |
Vector2
Section titled “Vector2”| Syntax | Description | Example |
|---|---|---|
new Vector2(x, y) | Construct from 2 floats | Constructing a 2-component value |
v.x v.y | Reading a component | Scaling a 2-component value |
v.x = 1f | Assigning to a component (local variable) | Assigning to a component of a 2-component value |
v + w v - w | Component-wise sum and difference | Operating on a 2-component value |
v * 2f 2f * v v / 2f -v | Scaling, division by a float, sign negation | Scaling a 2-component value |
v * w v / w | Component-wise product and quotient (operators only Vector2 has) | Component-wise multiplication and division of 2-component values |
v == w | Approximate comparison | Equality between 2-component values |
v != w | Negated approximate comparison | Inequality between 2-component values |
v += w v -= w v *= 2f v /= 2f | Compound assignment | Compound assignment to a 2-component value |
Vector3 and Vector4
Section titled “Vector3 and Vector4”| Syntax | Description | Example |
|---|---|---|
new Vector3(x, y, z) | Construct from 3 floats | Constructing a 3-component value |
new Vector4(x, y, z, w) | Construct from 4 floats | Constructing a 4-component value |
a.x a.y a.z p.w | Reading a component | Constructing a 4-component value |
a.z = 0.5f p.w = 1f | Assigning to a component (local variable) | Assigning to a component of a 3- or 4-component value |
a + b a - b a * 2f 2f * a a / 2f -a | Vector3 sum, difference, scaling, division by a float, sign negation | Operating on a 3-component value |
p + q p - q p * 2f 2f * p p / 2f -p | Vector4 sum, difference, scaling, division by a float, sign negation | Operating on a 4-component value |
a == b a != b | Approximate comparison of Vector3 | Equality between 3-component values |
p == q p != q | Approximate comparison of Vector4 | Equality between 4-component values |
a += b a *= 2f p -= q p /= 2f | Compound assignment | Compound assignment to a 3- or 4-component value |
| Syntax | Description | Example |
|---|---|---|
0.5f | Float constant | Float value |
a + b a - b a * b a / b | Arithmetic | Float arithmetic |
f % 1f | Remainder | Float remainder |
-v | Sign negation | Sign negation |
a < b a > b a <= b a >= b | Ordering comparison | Range comparison |
a == b a != b | Equality and inequality | Equality and inequality |
(float)n | Conversion from int | Converting int to float |
v += 0.25f | Compound assignment with addition | Compound assignment |
v -= 0.1f v *= 2f v /= 4f | Other compound assignments | Other compound assignments |
| Syntax | Description | Example |
|---|---|---|
id.X * 2 + 1 | Arithmetic | Integer arithmetic |
id.X % 4 | Remainder | Integer remainder |
n == 3 | Equality and inequality | Equality and inequality |
id.X & 3 | Bitwise AND | Bitwise operations |
n | 1 n ^ 2 | Bitwise OR and XOR | Bitwise OR and XOR |
~n | Bitwise NOT | Bitwise NOT |
id.X << 2 | Left shift | Shifting bits |
id.X >> 1 | Right shift | Right shift |
n++ | Postfix increment | Increment and decrement |
++n --n n-- | Prefix increment and decrement, postfix decrement | Prefix increment and decrement |
(int)f | Conversion from float | Float-to-int conversion |
| Syntax | Description | Example |
|---|---|---|
a && b | Logical AND | Combining booleans |
a || b | Logical OR | Boolean OR |
!a | Negation | Negation |
cond ? a : b | Choosing a value by condition | Choosing a value by condition |
Functions and members
Section titled “Functions and members”| Types | List |
|---|---|
Vector2 | Vector2(13) |
Vector3 | Vector3(15) |
Vector4 | Vector4(11) |
Color4 | Color4(2) |
int | Integer versions of Mathf |
Statements
Section titled “Statements”Local variable
Section titled “Local variable”using UnityEngine;using Tsukimi;
public class ParLocalVariable : 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) { float v = prev[id].R; return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Assignment
Section titled “Assignment”using UnityEngine;using Tsukimi;
public class ParAssignment : 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) { float v = 0f; v = prev[id].R; return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Compound assignment
Section titled “Compound assignment”using UnityEngine;using Tsukimi;
public class ParCompoundAssignment : 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) { float v = prev[id].R; v += 0.25f; return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Other compound assignments
Section titled “Other compound assignments”Besides +=, you can write -= *= /=.
using UnityEngine;using Tsukimi;
public class ParCompoundAssignmentMore : 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) { float v = prev[id].R; // Besides +=, you can write -= *= /= v -= 0.1f; v *= 2f; v /= 4f; return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Increment and decrement
Section titled “Increment and decrement”using UnityEngine;using Tsukimi;
public class ParIncrement : 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) { int n = id.X; n++; return new Color4(n * 0.01f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Prefix increment and decrement
Section titled “Prefix increment and decrement”They can be written only as a statement or in the increment of a for.
using UnityEngine;using Tsukimi;
public class ParIncrementPrefix : 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) { int n = id.X; // Prefix ++ and --, and postfix --, can also be written as statements ++n; --n; n--; return new Color4(n * 0.01f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Branch on a condition
Section titled “Branch on a condition”using UnityEngine;using Tsukimi;
public class ParIf : 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) { float v = prev[id].R; if (v > 0.5f) { v = 1f; } return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Two-way branch
Section titled “Two-way branch”using UnityEngine;using Tsukimi;
public class ParIfElse : 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) { float v = prev[id].R; if (v > 0.5f) { v = 1f; } else { v = 0f; } return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Branching on a value
Section titled “Branching on a value”switch is lowered to a chain of ifs.
using UnityEngine;using Tsukimi;
public class ParSwitch : 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) { float v = 0f; switch (id.X % 3) { case 0: v = prev[id].R; break; case 1: v = prev[id].G; break; default: v = prev[id].B; break; } return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Arm with several case labels
Section titled “Arm with several case labels”Several case labels can be stacked on one arm.
using UnityEngine;using Tsukimi;
public class ParSwitchMultiCase : 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) { int n = id.X % 4; float v = 0f; switch (n) { // Several case labels can be stacked on one arm case 0: case 1: v = 0.25f; break; case 2: v = 0.5f; break; default: v = 1f; break; } return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Return partway through
Section titled “Return partway through”using UnityEngine;using Tsukimi;
public class ParEarlyReturn : 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) { if (id.X == 0) { return Color4.Black; } return new Color4(prev[id].R, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Loop a fixed number of times
Section titled “Loop a fixed number of times”using UnityEngine;using Tsukimi;
public class ParFor : 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) { float v = 0f; for (int i = 0; i < 4; i++) { v = v + prev[id.Offset(i, 0)].R; } return new Color4(v * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Several declarations in for
Section titled “Several declarations in for”One for can declare 2 variables, and can have 2 incrementors.
using UnityEngine;using Tsukimi;
public class ParForMultiDeclaration : 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) { float v = 0f; // One for can declare 2 variables and have 2 incrementors for (int i = 0, j = 3; i < j; i++, j--) { v += prev[id.Offset(i, j)].R; } return new Color4(v * 0.5f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Initializing for with an assignment
Section titled “Initializing for with an assignment”The initializer can also be an assignment to a variable declared earlier.
using UnityEngine;using Tsukimi;
public class ParForAssignInit : 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) { int i; float v = 0f; // The initializer need not be a declaration; assigning to a variable declared earlier works for (i = 0; i < 4; i++) { v += prev[id.Offset(i, 0)].R; } return new Color4(v * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Conditional loop
Section titled “Conditional loop”using UnityEngine;using Tsukimi;
public class ParWhile : 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) { float v = 0f; int i = 0; while (i < 4) { v = v + prev[id.Offset(i, 0)].R; i++; } return new Color4(v * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Loop with the check after the body
Section titled “Loop with the check after the body”using UnityEngine;using Tsukimi;
public class ParDoWhile : 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) { float v = 0f; int i = 0; do { v = v + prev[id.Offset(i, 0)].R; i++; } while (i < 4); return new Color4(v * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Loop exit
Section titled “Loop exit”using UnityEngine;using Tsukimi;
public class ParBreak : 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) { float v = 0f; for (int i = 0; i < 8; i++) { if (prev[id.Offset(i, 0)].R > 0.5f) { break; } v = v + 0.125f; } return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Continue to the next iteration
Section titled “Continue to the next iteration”using UnityEngine;using Tsukimi;
public class ParContinue : 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) { float v = 0f; for (int i = 0; i < 4; i++) { if (i == 2) { continue; } v = v + prev[id.Offset(i, 0)].R; } return new Color4(v * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}using UnityEngine;using Tsukimi;
public class ParBlock : 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) { float v = prev[id].R; { v = v * 2f; } return new Color4(Mathf.Clamp01(v), 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Nested condition
Section titled “Nested condition”using UnityEngine;using Tsukimi;
public class ParNestedIf : 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) { float v = prev[id].R; if (v > 0.25f) { if (v > 0.75f) { v = 1f; } } return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Values and operators
Section titled “Values and operators”Float value
Section titled “Float value”Write a float constant by appending f.
using UnityEngine;using Tsukimi;
public class ParFloatLiteral : 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) { return new Color4(0.5f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Integer arithmetic
Section titled “Integer arithmetic”using UnityEngine;using Tsukimi;
public class ParIntArith : 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) { int n = id.X * 2 + 1; return new Color4(n * 0.001f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Float arithmetic
Section titled “Float arithmetic”using UnityEngine;using Tsukimi;
public class ParFloatArith : 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) { float a = prev[id].R; float b = prev[id].G; // Arithmetic between floats float v = (a - b) / 2f + a * b; return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Combining booleans
Section titled “Combining booleans”using UnityEngine;using Tsukimi;
public class ParBoolLogic : 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) { bool b = id.X > 0 && id.Y > 0; return new Color4(b ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Boolean OR
Section titled “Boolean OR”using UnityEngine;using Tsukimi;
public class ParBoolOr : 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) { bool a = id.X > 8; bool b = id.Y > 8; // Logical OR of booleans return new Color4(a || b ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Negation
Section titled “Negation”using UnityEngine;using Tsukimi;
public class ParNot : 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) { bool b = !(id.X > 0); return new Color4(b ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Range comparison
Section titled “Range comparison”using UnityEngine;using Tsukimi;
public class ParComparisonChain : 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) { bool b = prev[id].R >= 0.25f && prev[id].R <= 0.75f; return new Color4(b ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Equality and inequality
Section titled “Equality and inequality”== and != can be written between integers and between floats.
using UnityEngine;using Tsukimi;
public class ParEquality : 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) { int n = id.X % 4; float f = prev[id].R; // == and != work between integers and between floats bool a = n == 3; bool b = f != 0f; return new Color4(a ? 1f : 0f, b ? 1f : 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Choosing a value by condition
Section titled “Choosing a value by condition”using UnityEngine;using Tsukimi;
public class ParTernary : 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) { return new Color4(id.X > 32 ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Sign negation
Section titled “Sign negation”using UnityEngine;using Tsukimi;
public class ParNegate : 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) { return new Color4(-(-prev[id].R), 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Converting int to float
Section titled “Converting int to float”using UnityEngine;using Tsukimi;
public class ParCastIntToFloat : 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) { int n = id.X; return new Color4((float)n * 0.001f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Float-to-int conversion
Section titled “Float-to-int conversion”using UnityEngine;using Tsukimi;
public class ParCastFloatToInt : 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) { int n = (int)(prev[id].R * 4f); return new Color4(n * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Integer remainder
Section titled “Integer remainder”% computes an integer remainder.
using UnityEngine;using Tsukimi;
public class ParModuloInt : 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) { int n = id.X % 4; return new Color4(n * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Float remainder
Section titled “Float remainder”% can also be written between floats.
using UnityEngine;using Tsukimi;
public class ParModuloFloatOperator : 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) { float f = prev[id].R * 4f; // % also works between floats float v = f % 1f; return new Color4(v, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Float wraparound
Section titled “Float wraparound”Use Mathf.Repeat to wrap into the range from 0 to the length.
using UnityEngine;using Tsukimi;
public class ParModuloFloat : 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) { return new Color4(Mathf.Repeat(prev[id].R, 0.5f), 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Bitwise operations
Section titled “Bitwise operations”Bitwise operations between integers can be written.
using UnityEngine;using Tsukimi;
public class ParBitwiseAnd : 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) { int n = id.X & 3; return new Color4(n * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Bitwise OR and XOR
Section titled “Bitwise OR and XOR”using UnityEngine;using Tsukimi;
public class ParBitwiseOrXor : 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) { // | and ^ also work between integers int n = (id.X | 1) ^ 2; return new Color4((n & 3) * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Bitwise NOT
Section titled “Bitwise NOT”It can be written only for integers.
using UnityEngine;using Tsukimi;
public class ParBitwiseNot : 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) { // ~ is bitwise NOT (integers only) int n = ~id.X & 3; return new Color4(n * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Bit shift
Section titled “Bit shift”Left and right shifts between integers can be written.
using UnityEngine;using Tsukimi;
public class ParShift : 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) { int n = id.X << 1; return new Color4(n * 0.001f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Right shift
Section titled “Right shift”using UnityEngine;using Tsukimi;
public class ParShiftRight : 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) { int n = (id.X >> 1) & 3; return new Color4(n * 0.25f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Named arguments
Section titled “Named arguments”Arguments can be passed by name.
using UnityEngine;using Tsukimi;
public class ParNamedArguments : 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) { // Arguments can be passed by name. They are reordered into declaration order, not the order written Color4 c = prev[id.Offset(dy: 1, dx: 0)]; float t = Mathf.Lerp(t: 0.5f, a: 0f, b: c.R); return new Color4(a: 1f, r: t, g: 0f, b: 0f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}2-component value
Section titled “2-component value”Constructing a 2-component value
Section titled “Constructing a 2-component value”using UnityEngine;using Tsukimi;
public class ParVector2Construct : 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 v = new Vector2(0.25f, 0.5f); return new Color4(v.x + v.y, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Operating on a 2-component value
Section titled “Operating on a 2-component value”Addition and subtraction between Vector2 values can be written.
using UnityEngine;using Tsukimi;
public class ParVector2Ops : 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 v = new Vector2(1f, 0f) + new Vector2(0f, 1f); return new Color4(v.magnitude * 0.5f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Scaling a 2-component value
Section titled “Scaling a 2-component value”using UnityEngine;using Tsukimi;
public class ParVector2Scale : 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 v = new Vector2(prev[id].R, prev[id].G); // Multiplication and division by a float, and sign negation Vector2 a = v * 0.5f; Vector2 b = 0.5f * v; Vector2 c = v / 2f; Vector2 d = -v; return new Color4(a.x, b.y, c.x, d.y + 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Component-wise multiplication and division of 2-component values
Section titled “Component-wise multiplication and division of 2-component values”* and / between Vector2 values are the component-wise product and quotient.
using UnityEngine;using Tsukimi;
public class ParVector2Componentwise : 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 v = new Vector2(prev[id].R, prev[id].G); Vector2 w = new Vector2(0.5f, 2f); // * and / between Vector2 values are the component-wise product and quotient Vector2 p = v * w; Vector2 q = v / w; return new Color4(p.x, p.y, q.x, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Equality between 2-component values
Section titled “Equality between 2-component values”== between Vector2 values is the same approximate comparison Unity uses.
using UnityEngine;using Tsukimi;
public class ParVector2Equality : 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 v = new Vector2(prev[id].R, prev[id].G); bool same = v == new Vector2(0f, 0f); return new Color4(same ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Inequality between 2-component values
Section titled “Inequality between 2-component values”using UnityEngine;using Tsukimi;
public class ParVector2Inequality : 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 v = new Vector2(prev[id].R, prev[id].G); Vector2 w = new Vector2(0.5f, 0.5f); // != is the same approximate comparison as == bool differs = v != w; return new Color4(differs ? 1f : 0f, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Assigning to a component of a 2-component value
Section titled “Assigning to a component of a 2-component value”You can assign to a component of a local variable.
using UnityEngine;using Tsukimi;
public class ParVector2ComponentWrite : 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 v = new Vector2(0f, 0f); // You can assign to a component of a local variable v.x = prev[id].R; v.y = 1f; return new Color4(v.x, v.y, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Compound assignment to a 2-component value
Section titled “Compound assignment to a 2-component value”using UnityEngine;using Tsukimi;
public class ParVector2CompoundAssignment : 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 v = new Vector2(prev[id].R, prev[id].G); Vector2 w = new Vector2(0.25f, 0.25f); // Compound assignment also works on Vector2 v += w; v -= w; v *= 2f; v /= 2f; return new Color4(v.x, v.y, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Three- and four-component values
Section titled “Three- and four-component values”Constructing a 3-component value
Section titled “Constructing a 3-component value”Vector3 and Vector4 support construction, reading components, addition and subtraction, and multiplication and division by a float.
using UnityEngine;using Tsukimi;
public class ParVector3Value : 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) { Vector3 v = new Vector3(1f, 0f, 0f); return new Color4(v.x, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Constructing a 4-component value
Section titled “Constructing a 4-component value”using UnityEngine;using Tsukimi;
public class ParVector4Value : 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) { // Construct a 4-component value and read its components Vector4 p = new Vector4(prev[id].R, 0f, 0f, 1f); return new Color4(p.x, p.y, p.z, p.w); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Operating on a 3-component value
Section titled “Operating on a 3-component value”using UnityEngine;using Tsukimi;
public class ParVector3Ops : 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) { Vector3 a = new Vector3(prev[id].R, 0f, 0f); Vector3 b = new Vector3(0f, 1f, 0f); // Addition, subtraction, multiplication and division by a float, and sign negation (component-wise * and / are Vector2 only) Vector3 s = a + b; Vector3 d = a - b; Vector3 m = a * 0.5f; Vector3 n = 0.5f * a; Vector3 q = a / 2f; Vector3 neg = -a; return new Color4(s.x, d.y + 1f, m.x + n.x + q.x, neg.x + 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Operating on a 4-component value
Section titled “Operating on a 4-component value”using UnityEngine;using Tsukimi;
public class ParVector4Ops : 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) { Vector4 p = new Vector4(prev[id].R, 0f, 0f, 1f); Vector4 q = new Vector4(0f, 1f, 0f, 0f); // The same operators as Vector3 Vector4 s = p + q; Vector4 d = p - q; Vector4 m = p * 0.5f; Vector4 n = 0.5f * p; Vector4 h = p / 2f; Vector4 neg = -p; return new Color4(s.x, d.y + 1f, m.x + n.x + h.x, neg.w + 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Equality between 3-component values
Section titled “Equality between 3-component values”== and != between Vector3 values are the same approximate comparison as for Vector2.
using UnityEngine;using Tsukimi;
public class ParVector3Equality : 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) { Vector3 a = new Vector3(prev[id].R, 0f, 0f); Vector3 b = new Vector3(0.5f, 0f, 0f); // == and != between Vector3 values are the same approximate comparison as for Vector2 bool same = a == b; bool differs = a != b; return new Color4(same ? 1f : 0f, differs ? 1f : 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Equality between 4-component values
Section titled “Equality between 4-component values”using UnityEngine;using Tsukimi;
public class ParVector4Equality : 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) { Vector4 p = new Vector4(prev[id].R, 0f, 0f, 1f); Vector4 q = new Vector4(0.5f, 0f, 0f, 1f); // == and != between Vector4 values are approximate comparisons too bool same = p == q; bool differs = p != q; return new Color4(same ? 1f : 0f, differs ? 1f : 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Assigning to a component of a 3- or 4-component value
Section titled “Assigning to a component of a 3- or 4-component value”using UnityEngine;using Tsukimi;
public class ParVectorComponentWrite : 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) { Vector3 a = new Vector3(0f, 0f, 0f); Vector4 p = new Vector4(0f, 0f, 0f, 0f); // You can also assign to components of Vector3 and Vector4 a.z = prev[id].R; p.w = 1f; return new Color4(a.z, 0f, 0f, p.w); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Compound assignment to a 3- or 4-component value
Section titled “Compound assignment to a 3- or 4-component value”using UnityEngine;using Tsukimi;
public class ParVectorCompoundAssignment : 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) { Vector3 a = new Vector3(prev[id].R, 0f, 0f); Vector4 p = new Vector4(0f, 0f, 0f, 1f); // Compound assignment also works on Vector3 and Vector4 a += new Vector3(0f, 0.5f, 0f); a *= 0.5f; p -= new Vector4(0f, 0f, 0f, 0.5f); p /= 2f; return new Color4(a.x, a.y, 0f, p.w + 0.75f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Operating on cell values
Section titled “Operating on cell values”Adding cells
Section titled “Adding cells”using UnityEngine;using Tsukimi;
public class ParCellAdd : 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) { Color4 c = prev[id] + Color4.Black; return new Color4(c.R, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Subtracting cells
Section titled “Subtracting cells”using UnityEngine;using Tsukimi;
public class ParCellSub : 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) { Color4 c = prev[id] - Color4.Black; return new Color4(c.R, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Scaling a cell by a constant
Section titled “Scaling a cell by a constant”using UnityEngine;using Tsukimi;
public class ParCellScale : 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) { Color4 c = prev[id] * 0.5f; return new Color4(c.R, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Dividing a cell value
Section titled “Dividing a cell value”Each of the 4 components is divided.
using UnityEngine;using Tsukimi;
public class ParCellDivide : 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) { // Dividing by a float divides each of the 4 components Color4 c = prev[id] / 2f; return new Color4(c.R, c.G, c.B, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Multiplying cells
Section titled “Multiplying cells”It is the component-wise product.
using UnityEngine;using Tsukimi;
public class ParCellMultiply : 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) { // * between Color4 values is the component-wise product Color4 c = prev[id] * prev[id.Offset(1, 0)]; return new Color4(c.R, c.G, c.B, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Constructing from 3 components and an alpha
Section titled “Constructing from 3 components and an alpha”It can be built from a Vector3 color and a float alpha.
using UnityEngine;using Tsukimi;
public class ParCellFromVector3 : 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) { Vector3 rgb = new Vector3(prev[id].R, 0f, 0f); // Built from a 3-component color and an alpha return new Color4(rgb, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Constructing from 4 components
Section titled “Constructing from 4 components”A Vector4 value can be used directly as a color.
using UnityEngine;using Tsukimi;
public class ParCellFromVector4 : 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) { Vector4 v = new Vector4(prev[id].R, 0f, 0f, 1f); // A 4-component value can be used directly as a color return new Color4(v); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Compound assignment to a cell value
Section titled “Compound assignment to a cell value”using UnityEngine;using Tsukimi;
public class ParCellCompoundAssignment : 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) { Color4 c = prev[id]; // Compound assignment also works on Color4 (+= -= take a Color4, *= a float or a Color4, /= a float) c += Color4.Black; c -= Color4.Black; c *= 0.5f; c *= prev[id]; c /= 2f; return c; }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Assigning to a cell component
Section titled “Assigning to a cell component”You can assign to a component of a local variable.
using UnityEngine;using Tsukimi;
public class ParCellComponentWrite : 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) { Color4 c = prev[id]; // You can assign to a component of a local variable c.R = 0.5f; c.A = 1f; return c; }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Constants and names
Section titled “Constants and names”Type constant
Section titled “Type constant”A constant is replaced with its value at compile time.
using UnityEngine;using Tsukimi;
public class ParConstField : TsukimiBehaviour{ private GpuBuffer2D current; private GpuBuffer2D next;
private const float Gain = 0.5f;
void Start() { current = Gpu.Buffer(64, 64); next = Gpu.Buffer(64, 64); }
[Kernel] static Color4 Step(KernelId id, GpuBuffer2D prev) { return new Color4(prev[id].R * Gain, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Local constant
Section titled “Local constant”using UnityEngine;using Tsukimi;
public class ParConstLocal : 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) { const float gain = 0.5f; return new Color4(prev[id].R * gain, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}Same name as a reserved word in the compile target
Section titled “Same name as a reserved word in the compile target”A name that collides with a reserved word on the shader side is renamed at compile time.
using UnityEngine;using Tsukimi;
public class ParReservedWordName : 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) { float sample = prev[id].R; float matrix = 0.5f; return new Color4(sample * matrix, 0f, 0f, 1f); }
void Update() { Gpu.Run(nameof(Step), next, current); Gpu.Swap(ref current, ref next); }}