演算子

記号で書く演算子と、後置で作用する swizzle・unpack・スタック操作語をまとめる。 記号演算子にはすべて英字の別名があり、どちらで書いても同じ命令になる。

算術

記号 別名 引数 クラス 意味
+ add a b Ei a + b
- sub a b Ei a - b
* mul a b Ei 成分ごとの積 (内積ではない)
/ div a b Ef a / b (常に float)
// idiv a b Io 整数除算。両辺が int でなければ型エラー。b = 0 なら 0
% mod a b Ei int なら剰余 (b = 0 なら 0)、float なら fmod (符号は被除数に従う)

単項マイナスは演算子ではなく関数 neg である (5.1 節)。

比較・論理

記号 別名 引数 クラス 意味
> gt a b Ef a > b
< lt a b Ef a < b
>= geq a b Ef a >= b
<= leq a b Ef a <= b
== eq a b Ef a == b (浮動小数の厳密比較)
!= neq a b Ef a != b
! not a Ef a == 0 なら 1、そうでなければ 0

いずれも成分ごとに評価され、結果は 1.0 / 0.0 からなる同じ型の値になる (float3 同士の比較は float3 のマスクを返す)。真偽型は存在しないので、 結果はそのまま lerp の重みや乗算のマスクとして使える。

swizzle #…

スタック先頭のベクトルに対する成分抽出・並べ替えを行う後置演算子。

  • 成分文字は xyzw / rgba / uvst の 3 セット。1 つの swizzle 内でセットを混ぜられない (#xgInvalidSwizzle)。同じ成分の重複は可 (#xxxx)。
  • 長さは 1 から 4。結果型は長さ 1 なら float、それ以外は floatN
  • 対象がスカラなら SwizzleOnScalar、対象の次元を超える成分を指すと SwizzleOutOfRange
@color #rgb      ; float4 -> float3
@color #a        ; float4 -> float  (成分抽出)
@uv   #yx        ; float2/3/4 -> float2 (入れ替え)
@position #xxz   ; float3 -> float3

unpack ... / unpack

スタック先頭のベクトルを取り除き、その成分を float スカラとして次元数ぶん push する。 vec2 / vec3 / vec4 の逆操作であり、成分ごとに別々の計算をしてから組み直すときに使う。

@position ... vec3    ; 恒等 (float3 -> 3 スカラ -> float3)
@uv #xy ... swap vec2 ; xy 入れ替え

スカラに適用すると UnpackOnScalar

スタック操作語

Forth 系と同じ意味論を持つ 5 語。型はコンパイル時に追跡されるため、任意の型に対して使える。

効果 必要な深さ
dup a → a a 1
drop a → 1
swap a b → b a 2
over a b → a b a 2
rot a b c → b c a 3

深さが足りなければ NotEnoughOperands。局所変数がないため、部分式を 2 回使いたいときは dup、引数順を入れ替えたいときは swap / rot を使う。

演算子の落とし穴

  • * は成分ごとの積: 内積は dot
  • / は常に float: 整数除算が必要なら // を使うが、両辺が int でなければ型エラー。
  • int の 0 除算は例外ではなく 0: // と int の % は 0 を返す。float の 0 除算は無限大 / NaN。
  • == は浮動小数の厳密比較: 誤差を許容するなら - abs EPSILON < のように書く。
  • ベクトル同士の次元不一致は昇格されない: float2float3 の演算は型エラー。