コンテンツにスキップ

カーネルの文と式

書き方説明注意
float v = prev[id].Rローカル変数
v = prev[id].R代入
v += 0.25f複合代入
v -= 0.1f; v *= 2f; v /= 4fそのほかの複合代入
n++増減
++n; --n; n--前置の増減
if (v > 0.5f) { ... }条件による分岐
if (...) { } else { }二手の分岐
switch (n) { case 0: ... }値による分岐アームの終わりの break だけが書けます。
case 0: case 1: ...複数の case を持つアーム
if (id.X == 0) { return ...; }途中の return
for (int i = 0; i < 4; i++)回数を決めた繰り返し
for (int i = 0, j = 3; i < j; i++, j--)for の複数の宣言
for (i = 0; i < 4; i++)for の代入による初期化
while (i < 4)条件による繰り返し
do { ... } while (i < 4);後判定の繰り返し
break繰り返しの脱出
continue次の繰り返しへの継続
{ ... }ブロック
if (...) { if (...) { } }条件の入れ子
0.5f小数の値
id.X * 2 + 1整数の計算
(a - b) / 2f + a * b小数の四則演算
a && b真偽の組み合わせ
a || b真偽の論理和
!(id.X > 0)否定
v >= 0.25f && v <= 0.75f範囲の比較
n == 3, f != 0f等値と非等値
cond ? a : b条件による値の選択
-v符号の反転
(float)n整数から小数への変換
(int)(v * 4f)小数から整数への変換
id.X % 4整数の剰余コンパイル先のシェーダーコンパイラが、遅いと警告することがあります。
f % 1f小数の剰余
Mathf.Repeat(v, 0.5f)小数の折り返し
id.X & 3ビットごとの演算真偽値どうしには使えません(論理演算子のほうを使います)。
(id.X | 1) ^ 2ビットごとの論理和と排他的論理和
~id.Xビットの反転
id.X << 2ビットをずらす
id.X >> 1右シフト
id.Offset(dy: 1, dx: 0)名前付き引数書いた順ではなく、宣言の順に並べ直されます。
new Vector2(x, y)2 成分の値の生成
v + w, v.magnitude2 成分の値の演算メンバは magnitude sqrMagnitude normalized の 3 つです。
v * 2f, 2f * v, v / 2f, -v2 成分の値の定数倍
v * w, v / w2 成分の値の成分ごとの乗除
v == w2 成分の値どうしの等値
v != w2 成分の値どうしの非等値
v.x = 1f2 成分の値の成分への代入
v += w; v *= 2f2 成分の値への複合代入
new Vector3(1f, 0f, 0f)3 成分の値の生成成分ごとの * と / は Vector2 にだけある演算子です。
new Vector4(1f, 0f, 0f, 1f)4 成分の値の生成
a + b, a * 0.5f, -a3 成分の値の演算
p + q, p * 0.5f, -p4 成分の値の演算
a == b, a != b3 成分の値どうしの等値
p == q, p != q4 成分の値どうしの等値
a.z = 0.5f; p.w = 1f3 成分と 4 成分の値の成分への代入
a += b; p /= 2f3 成分と 4 成分の値への複合代入
prev[id] + Color4.Blackセルどうしの加算
prev[id] - Color4.Blackセルどうしの減算
prev[id] * 0.5fセルの定数倍
prev[id] / 2fセルの値の割り算
prev[id] * prev[id.Offset(1, 0)]セルどうしの乗算
new Color4(rgb, 1f)3 成分と透明度からの生成
new Color4(v)4 成分からの生成
c += b; c *= 0.5f; c /= 2fセルの値への複合代入
c.R = 0.5fセルの成分への代入
private const float Gain = 0.5f;型の定数
const float gain = 0.5f;ローカル定数
float sample; float matrix;コンパイル先の予約語と同じ名前
書き方説明エラー理由代替
v %= 2f剰余の複合代入(&= |= ^= <<= >>= も同じ)TUKI0001未定v = v % 2f と開いて書く
+v単項のプラスTUKI0001設計外す(値は変わりません)
書き方説明例
new Color4(r, g, b, a)4 つの小数から作るセルの値の生成
new Color4(rgb, a)Vector3 の色と小数の透明度から作る3 成分と透明度からの生成
new Color4(v)Vector4 から作る4 成分からの生成
Color4.White Color4.Black定数定数の色
c.R c.G c.B c.A成分の読み出し成分の読み出し
c.R = 0.5f成分への代入(ローカル変数)セルの成分への代入
a + b成分ごとの和セルどうしの加算
a - b成分ごとの差セルどうしの減算
a * 0.5f各成分の定数倍セルの定数倍
a * b成分ごとの積セルどうしの乗算
a / 2f各成分を小数で割るセルの値の割り算
c += b c -= b c *= 0.5f c *= b c /= 2f複合代入セルの値への複合代入
書き方説明例
new Vector2(x, y)2 つの小数から作る2 成分の値の生成
v.x v.y成分の読み出し2 成分の値の定数倍
v.x = 1f成分への代入(ローカル変数)2 成分の値の成分への代入
v + w v - w成分ごとの和と差2 成分の値の演算
v * 2f 2f * v v / 2f -v定数倍・小数で割る・符号の反転2 成分の値の定数倍
v * w v / w成分ごとの積と商(Vector2 にだけある演算子)2 成分の値の成分ごとの乗除
v == w近似比較2 成分の値どうしの等値
v != w近似比較の否定2 成分の値どうしの非等値
v += w v -= w v *= 2f v /= 2f複合代入2 成分の値への複合代入
書き方説明例
new Vector3(x, y, z)3 つの小数から作る3 成分の値の生成
new Vector4(x, y, z, w)4 つの小数から作る4 成分の値の生成
a.x a.y a.z p.w成分の読み出し4 成分の値の生成
a.z = 0.5f p.w = 1f成分への代入(ローカル変数)3 成分と 4 成分の値の成分への代入
a + b a - b a * 2f 2f * a a / 2f -aVector3 の和・差・定数倍・小数で割る・符号の反転3 成分の値の演算
p + q p - q p * 2f 2f * p p / 2f -pVector4 の和・差・定数倍・小数で割る・符号の反転4 成分の値の演算
a == b a != bVector3 の近似比較3 成分の値どうしの等値
p == q p != qVector4 の近似比較4 成分の値どうしの等値
a += b a *= 2f p -= q p /= 2f複合代入3 成分と 4 成分の値への複合代入
書き方説明例
0.5f小数の定数小数の値
a + b a - b a * b a / b四則演算小数の四則演算
f % 1f剰余小数の剰余
-v符号の反転符号の反転
a < b a > b a <= b a >= b大小の比較範囲の比較
a == b a != b等値と非等値等値と非等値
(float)n整数からの変換整数から小数への変換
v += 0.25f加算の複合代入複合代入
v -= 0.1f v *= 2f v /= 4fそのほかの複合代入そのほかの複合代入
書き方説明例
id.X * 2 + 1四則演算整数の計算
id.X % 4剰余整数の剰余
n == 3等値と非等値等値と非等値
id.X & 3ビットごとの論理積ビットごとの演算
n | 1 n ^ 2ビットごとの論理和と排他的論理和ビットごとの論理和と排他的論理和
~nビットの反転ビットの反転
id.X << 2左シフトビットをずらす
id.X >> 1右シフト右シフト
n++後置の増加増減
++n --n n--前置の増減と後置の減少前置の増減
(int)f小数からの変換小数から整数への変換
書き方説明例
a && b論理積真偽の組み合わせ
a || b論理和真偽の論理和
!a否定否定
cond ? a : b条件による値の選択条件による値の選択
型一覧
Vector2Vector2(13)
Vector3Vector3(15)
Vector4Vector4(11)
Color4Color4(2)
intMathf の整数版
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);
}
}
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);
}
}
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);
}
}

+= のほかに -= *= /= が書けます。

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;
// += のほかに -= *= /= が書けます
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);
}
}
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);
}
}

文の位置と 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;
// 前置の ++ と --、後置の -- も文として書けます
++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);
}
}
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);
}
}
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);
}
}

switch は if の連鎖へ落とされます。

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

1 つのアームに case を並べて書けます。

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)
{
// 1 つのアームに case を並べて書けます
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);
}
}
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);
}
}
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);
}
}

1 つの for で変数を 2 つ宣言でき、増分も 2 つ並べて書けます。

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;
// 1 つの for で変数を 2 つ宣言でき、増分も 2 つ並べて書けます
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);
}
}

初期化式には、手前で宣言した変数への代入も書けます。

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;
// 初期化式は宣言でなくてもよく、手前で宣言した変数への代入が書けます
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);
}
}
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);
}
}
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);
}
}
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);
}
}
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);
}
}
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);
}
}

末尾に 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);
}
}
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);
}
}
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;
// 小数どうしの四則演算です
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);
}
}
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);
}
}
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;
// 真偽値の論理和です
return new Color4(a || b ? 1f : 0f, 0f, 0f, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}
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);
}
}
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);
}
}

整数どうし・小数どうしの == と != が書けます。

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;
// 整数どうし・小数どうしの == と != が書けます
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);
}
}
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);
}
}
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);
}
}
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);
}
}
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);
}
}

% で整数の剰余を計算できます。

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

% は小数どうしにも書けます。

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;
// % は小数どうしにも書けます
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);
}
}

0 から長さまでの範囲に折り返すには Mathf.Repeat を使います。

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

整数どうしのビット演算が書けます。

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

ビットごとの論理和と排他的論理和

Section titled “ビットごとの論理和と排他的論理和”
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)
{
// | と ^ も整数どうしで書けます
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);
}
}

整数にだけ書けます。

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)
{
// ~ はビットの反転です(整数だけ)
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);
}
}

整数どうしの左シフトと右シフトが書けます。

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

引数は名前で渡せます。

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)
{
// 引数は名前で渡せます。書いた順ではなく、宣言の順に並べ直されます
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);
}
}
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);
}
}

Vector2 どうしの加減算が書けます。

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);
}
}
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);
// 小数との乗除と、符号の反転が書けます
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);
}
}

Vector2 どうしの * と / は成分ごとの積と商です。

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);
// Vector2 どうしの * と / は成分ごとの積と商です
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);
}
}

Vector2 どうしの == は、Unity と同じ近似比較です。

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);
}
}
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);
// != も == と同じ近似比較です
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);
}
}

ローカル変数の成分には代入できます。

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);
// ローカル変数の成分には代入できます
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);
}
}
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);
// 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);
}
}

Vector3 と Vector4 は、生成・成分の読み出し・加減算・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);
}
}
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)
{
// 4 成分の値を作り、成分を読めます
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);
}
}
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);
// 加減算・小数との乗除・符号の反転が書けます(成分ごとの * と / は Vector2 だけ)
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);
}
}
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);
// 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);
}
}

Vector3 どうしの == と != は、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);
// Vector3 どうしの == と != は、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);
}
}
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);
// Vector4 どうしの == と != も近似比較です
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);
}
}

3 成分と 4 成分の値の成分への代入

Section titled “3 成分と 4 成分の値の成分への代入”
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);
// Vector3 と 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);
}
}

3 成分と 4 成分の値への複合代入

Section titled “3 成分と 4 成分の値への複合代入”
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);
// Vector3 と 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);
}
}
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);
}
}
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);
}
}
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);
}
}

4 つの成分がそれぞれ割られます。

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)
{
// 小数で割ると、4 つの成分がそれぞれ割られます
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);
}
}

成分ごとの積です。

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)
{
// Color4 どうしの * は成分ごとの積です
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);
}
}

Vector3 の色と、小数の透明度から作れます。

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);
// 3 成分の色と透明度から作れます
return new Color4(rgb, 1f);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

Vector4 の値をそのまま色にできます。

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);
// 4 成分の値をそのまま色にできます
return new Color4(v);
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}
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];
// Color4 にも複合代入が書けます(+= -= は Color4・*= は小数と Color4・/= は小数)
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);
}
}

ローカル変数の成分には代入できます。

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];
// ローカル変数の成分には代入できます
c.R = 0.5f;
c.A = 1f;
return c;
}
void Update()
{
Gpu.Run(nameof(Step), next, current);
Gpu.Swap(ref current, ref next);
}
}

定数は、コンパイルのときに値へ置き換わります。

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

コンパイル先の予約語と同じ名前

Section titled “コンパイル先の予約語と同じ名前”

シェーダー側の予約語と重なる名前は、コンパイルのときに改名されます。

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