Open5

個人的に忘れがちなシェーダー関数メモ [SKShader/MSL/GLSL]

poteChpoteCh

こまかい仕様を忘れがちなシェーダーの関数の雑メモです。

ひさしぶりにシェーダーを書いたときによく調べなおしている関数を記録しておく場所として。
いいかんじの図を集めて体裁を整えられたら記事に移行するかもしれません。

主な動作確認環境

  • SKShader iOS 15.2 / macOS 12.1 (Swift Playgrounds 4.5.3で確認)
  • Metal Shading Language 3.2 (同上、SceneKitのSCNShadableで確認)
  • GLSL ES 1.0 / 3.0 (GLSL Editor / Shadertoy

※2025/4/1 時点。雑メモなので厳密な確認をしていないことがあります。

主なドキュメント

poteChpoteCh

丸め系

x floor(x) ceil(x) trunc(x)
*SK *M *GL3
round(x)
*SK *M *GL3
roundEven(x)
*GL3
rint(x)
*SK *M
2.0 2.0 2.0 2.0 2.0 2.0 2.0
1.75 1.0 2.0 1.0 2.0 2.0 2.0
1.5 1.0 2.0 1.0 2.0 2.0 2.0
1.25 1.0 2.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0
0.75 0.0 1.0 0.0 1.0 1.0 1.0
0.5 0.0 1.0 0.0 1.0 0.0 0.0
0.25 0.0 1.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0
-0.25 -1.0 0.0 0.0 0.0 0.0 0.0
-0.5 -1.0 0.0 0.0 -1.0 0.0 0.0
-0.75 -1.0 0.0 0.0 -1.0 -1.0 -1.0
-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0
-1.25 -2.0 -1.0 -1.0 -1.0 -1.0 -1.0
-1.5 -2.0 -1.0 -1.0 -2.0 -2.0 -2.0
-1.75 -2.0 -1.0 -1.0 -2.0 -2.0 -2.0
-2.0 -2.0 -2.0 -2.0 -2.0 -2.0 -2.0

*SK = SKShaderの関数
*M = MSLの関数
*GL3 = GLSL ES 3.0の関数

メモ

丸め系の関数は負値を渡したときの戻り値を忘れがち。

floor は小さいほうの整数へ切り捨てる
-1.25-1.0 ではなく -2.0 になる
Swiftの FloatingPointRoundingRule.down の挙動

ceil は大きいほうの整数へ切り上げる
-1.25-2.0 ではなく -1.0 になる
Swiftの FloatingPointRoundingRule.up の挙動

trunc はゼロに近いほうの整数へ丸める
-1.25-2.0 ではなく -1.0 になる
正値では floor と同じ結果、負値では ceil と同じ結果になる
小数部分が .0 になると覚えればよい
Swiftの FloatingPointRoundingRule.towardZero の挙動
GLSL ES 1.0でtruncしたいときは x - fract(abs(x)) * sign(x) や、xがfloatなら x < 0.0 ? ceil(x) : floor(x) など

round は四捨五入する
-0.5-1.00.51.0 になる (※GLSLでは環境依存)
Swiftの FloatingPointRoundingRule.toNearestOrAwayFromZero の挙動

GLSL ES 3.0の roundEven とMSLの rint は四捨五入する
偶数と奇数の境目にある数値(..., -1.5, -0.5, 0.5, 1.5, ...)が偶数側へ丸められる点が round と異なる
-0.50.0-1.5-2.0-2.5-2.0 になる
Swiftの FloatingPointRoundingRule.toNearestOrEven の挙動

Swiftの FloatingPointRoundingRule.awayFromZero の挙動をする関数は無し
x + fract(-abs(x)) * sign(x) や、xがfloatなら x < 0.0 ? floor(x) : ceil(x) など

FloatingPointRoundingRule | Apple Developer Documentation

poteChpoteCh

小数部系

x fract(x) mod(x, 1.0)
*SK *GL
fmod(x, 1.0)
*SK *M
2.0 0.0 0.0 0.0
1.75 0.75 0.75 0.75
1.5 0.5 0.5 0.5
1.25 0.25 0.25 0.25
1.0 0.0 0.0 0.0
0.75 0.75 0.75 0.75
0.5 0.5 0.5 0.5
0.25 0.25 0.25 0.25
0.0 0.0 0.0 0.0
-0.25 0.75 0.75 -0.25
-0.5 0.5 0.5 -0.5
-0.75 0.25 0.25 -0.75
-1.0 0.0 0.0 0.0
-1.25 0.75 0.75 -0.25
-1.5 0.5 0.5 -0.5
-1.75 0.25 0.25 -0.75
-2.0 0.0 0.0 0.0

*SK = SKShaderの関数
*M = MSLの関数
*GL = GLSL ES 1.0/3.0の関数

メモ

小数部系の関数も負値を渡したときの戻り値を忘れがち。

fractmod(x, 1.0) の結果は同じ
-1.25-0.25 ではなく 0.75 になる

fmod(x, 1.0) は負値側の戻り値が mod(x, 1.0) と異なる
-1.250.75 ではなく -0.25 になる

mod(x, y) の計算式は x - y * floor(x / y)
fmod(x, y) の計算式は x - y * trunc(x / y)

poteChpoteCh

二値化

x step(0.0, x) step(x, 0.0)
1.0 1.0 0.0
0.5 1.0 0.0
0.0 1.0 1.0
-0.5 0.0 1.0
-1.0 0.0 1.0

メモ

引数は step(edge, x) の順で、戻り値は x < edge ? 0.0 : 1.0
この公式ドキュメントに書かれている引数の順序と大小の向きが直感と合わなくて書きかたを迷いがち
args1 <= args2 ? 1.0 : 0.0 なので第二引数の方が大きければ1.0、同値の場合も1.0になる

poteChpoteCh

変換行列

拡大縮小 (Scale)

mat2 scale(vec2 _scale) {
    return mat2(
        _scale.x, 0.0,
        0.0, _scale.y
    );
}

scale(vec2(1.5, 0.5)) * coordinates.xy で、座標がX方向に1.5倍、Y方向に0.5倍になる。

変形前 変形後
変形前(Scale) 変形後(Scale)

次のような関数にすると、座標ではなくシェーダーで描画している図形の拡大・縮小になる。
こちらのほうが感覚的に使いやすい場合もある。

mat2 scale(vec2 _scale) {
    return mat2(
        1.0 / _scale.x, 0.0,
        0.0, 1.0 / _scale.y
    );
}

scale(vec2(1.5, 0.5)) * coordinates.xy で、描画している図形がX方向に1.5倍、Y方向に0.5倍になる。

変形前 変形後
変形前(Scale別版) 変形後(Scale別版)

回転 (Rotate)

mat2 rotate(float _angle) {
    return mat2(
        cos(_angle), -sin(_angle),
        sin(_angle),  cos(_angle)
    );
}

rotate(45.0 / 180.0 * 3.1415927) * coordinates.xy で、原点を中心として反時計回りに45度回転する(右手系の座標の場合)。

変形前 変形後
変形前(Rotate) 変形後(Rotate)

剪断 (せん断 / Shear / Skew)

mat2 shear(vec2 _shear) {
    return mat2(
        1.0, _shear.y,
        _shear.x, 1.0
    );
}

shear(vec2(0.5, 0.0)) * coordinates.xy で座標がX方向にずれて coordinates.x += coordinates.y * 0.5 になる。

変形前 変形後
変形前(ShearX) 変形後(ShearX)

shear(vec2(0.0, 0.5)) * coordinates.xy で座標がY方向にずれて coordinates.y += coordinates.x * 0.5 になる。

変形前 変形後
変形前(ShearY) 変形後(ShearY)