コンテンツにスキップ

カーネルから呼べる関数

書き方説明注意
Falloff(d)補助関数の呼び出しその補助関数に [Kernel] は必要ありません。
Mix(a, b)引数を 2 つ取る補助関数
static Color4 Dim(Color4 c, float k)Color4 を受け渡す補助関数
static float Pick(Vector3 v, bool first)複数の型を受け渡す補助関数
static float Half(float v) => v * 0.5f;式だけの補助関数
Mathf.Abs(n), Mathf.Min(n, m), Mathf.Clamp(n, m, k)Mathf の整数版
Gpu.Pack16x2(v)2 つの値の詰め込み詰めると、各 65536 段階まで保たれます。
Gpu.Unpack16x2(c)詰めた値の取り出し

Mathf・Vector2・Vector3・Vector4・Gpu のメンバは、この表に載っているものだけが書けます。

「C# との差」の列には、次の記号が付きます。

  • 補正 / 同じ値になるよう、コンパイラが式を組み替えています
  • 差あり / 組み替えても残る差があります
書き方説明C# との差
Mathf.Abs(f)絶対値
Mathf.Acos(f)逆余弦
Mathf.Asin(f)逆正弦
Mathf.Atan(f)逆正接
Mathf.Atan2(f, g)y,x から角度
Mathf.Ceil(f)切り上げ
Mathf.CeilToInt(f)小数点以下を切り上げて整数にする
Mathf.Clamp(f, g, h)下限と上限で挟む補正
Mathf.Clamp01(f)0..1 で挟む補正
Mathf.Cos(f)余弦
Mathf.Deg2Rad度→ラジアンの係数
Mathf.DeltaAngle(ang, ang2)2 つの角度の差(-180..180 に畳む)補正
Mathf.Exp(f)e の冪
Mathf.Floor(f)切り捨て
Mathf.FloorToInt(f)小数点以下を切り捨てて整数にする
Mathf.InverseLerp(f, g, h)値が a..b のどこにあるか(0..1)補正
Mathf.Lerp(f, g, h)線形補間(t は 0..1 に丸める)補正
Mathf.LerpAngle(ang, ang2, h)角度の線形補間(近いほうへ回る・t は 0..1 に丸める)補正
Mathf.LerpUnclamped(f, g, h)線形補間(t を丸めない)
Mathf.Log(f)自然対数
Mathf.Log(f, g)底を指定した対数差あり
Mathf.Log10(f)常用対数
Mathf.Max(f, g)大きいほう
Mathf.Min(f, g)小さいほう
Mathf.MoveTowards(f, g, h)target へ maxDelta だけ近づける(行き過ぎない)補正
Mathf.MoveTowardsAngle(ang, ang2, h)角度を target へ maxDelta だけ近づける(近いほうへ回る)補正
Mathf.PI円周率
Mathf.PingPong(f, g)0..length を往復する補正
Mathf.Pow(f, g)冪乗差あり
Mathf.Rad2Degラジアン→度の係数
Mathf.Repeat(f, g)0..length で折り返す(剰余)補正
Mathf.Round(f)四捨五入(0.5 は偶数側へ)
Mathf.RoundToInt(f)四捨五入して整数にする(ちょうど半分なら偶数側)
Mathf.Sign(f)符号(0 は正として 1)補正
Mathf.Sin(f)正弦
Mathf.SmoothStep(f, g, h)なめらかな補間(両端で速度 0)補正
Mathf.Sqrt(f)平方根
Mathf.Tan(f)正接
書き方説明C# との差
Vector2.Distance(v, w)2 点の距離
Vector2.Dot(v, w)内積
Vector2.Lerp(v, w, f)線形補間(t は 0..1 に丸める)補正
Vector2.LerpUnclamped(v, w, f)線形補間(t を丸めない)
Vector2.Max(v, w)成分ごとに大きいほう
Vector2.Min(v, w)成分ごとに小さいほう
Vector2.one(1, 1)
Vector2.right(1, 0)
Vector2.up(0, 1)
Vector2.zero(0, 0)
v.magnitude長さ
v.normalized長さ 1 にした向き(長さ 0 なら (0,0))補正
v.sqrMagnitude長さの 2 乗(平方根を取らない)
書き方説明C# との差
Vector3.Cross(a, b)外積(両方に垂直な向き)
Vector3.Distance(a, b)2 点の距離
Vector3.Dot(a, b)内積
Vector3.Lerp(a, b, f)線形補間(t は 0..1 に丸める)補正
Vector3.LerpUnclamped(a, b, f)線形補間(t を丸めない)
Vector3.Max(a, b)成分ごとに大きいほう
Vector3.Min(a, b)成分ごとに小さいほう
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.magnitude長さ
a.normalized長さ 1 にした向き(長さ 0 なら (0,0,0))補正
a.sqrMagnitude長さの 2 乗(平方根を取らない)
書き方説明C# との差
Vector4.Distance(p, q)2 点の距離
Vector4.Dot(p, q)内積
Vector4.Lerp(p, q, f)線形補間(t は 0..1 に丸める)補正
Vector4.LerpUnclamped(p, q, f)線形補間(t を丸めない)
Vector4.Max(p, q)成分ごとに大きいほう
Vector4.Min(p, q)成分ごとに小さいほう
Vector4.one(1, 1, 1, 1)
Vector4.zero(0, 0, 0, 0)
p.magnitude長さ
p.normalized長さ 1 にした向き(長さ 0 なら (0,0,0,0))補正
p.sqrMagnitude長さの 2 乗(平方根を取らない)
書き方説明C# との差
prev.heightこのバッファの縦のセル数
prev.widthこのバッファの横のセル数
書き方説明C# との差
Gpu.Hash(id.X, id.Y)2 つの整数を混ぜて 1 つの整数にする(セルの座標から作るときに使う)
Gpu.Hash(n)整数を混ぜて別の整数にする(同じ入力なら必ず同じ値)
Gpu.Noise(v)なめらかなノイズ(0..1・格子ごとに向きを変えて補間する)
Gpu.OutHeight書き込み先のバッファの縦のセル数
Gpu.OutWidth書き込み先のバッファの横のセル数
Gpu.Pack16x2(v)2 つの値を 1 セルに詰める(各 65536 段階)
Gpu.Random01(n)0..1 の値(同じ入力なら必ず同じ値)
Gpu.Unpack16x2(c)Pack16x2 で詰めた値を取り出す
書き方説明C# との差
Color4.Lerp(c, c2, h)2 つの色のあいだを取る(t は 0..1 に丸める)補正
c.RGB色の 3 成分(透明度を除いたぶん)

カーネルから呼んだ static メソッドは、シェーダーの関数として一緒に出力されます。

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);
}
}
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);
}
// 補助関数の引数と戻り値には 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);
}
}

引数と戻り値には 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);
}
// 引数と戻り値には float・int・bool・Color4・KernelId・Vector2・Vector3・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);
}
// 補助関数も => で書けます
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 は、整数で呼ぶと整数のまま計算されます。

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)
{
// 整数で呼ぶと、整数のまま計算されます
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);
}
}

1 セルは 4 成分・各 8 ビット(256 段階)です。

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

詰めた値は、Gpu.Unpack16x2 で元の 2 つに戻せます。

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