組み込み関数
GLSL は数学関数が豊富。これを覚えると 3 行で済むコードが沢山ある。 ベクトルにも自動でスカラ関数が要素ごと適用される(component-wise)。
三角関数
| 関数 | 意味 |
|---|---|
sin(x) / cos(x) / tan(x) | 三角関数(ラジアン) |
asin(x) / acos(x) / atan(x) | 逆三角関数 |
atan(y, x) | 2引数版(角度を取り出す) |
sinh(x) / cosh(x) / tanh(x) | 双曲線関数 |
radians(deg) | 度 → ラジアン |
degrees(rad) | ラジアン → 度 |
典型例: 周期的な動き
// -1..1 の周期
float wave = sin(uTime);
// 0..1 の周期
float pulse = sin(uTime) * 0.5 + 0.5;
// 任意周期
float w = sin(uTime * 2.0 * 3.14159 / period);
角度を取り出す
vec2 p = vUv - 0.5;
float angle = atan(p.y, p.x); // -π..π
指数・対数・冪
| 関数 | 意味 |
|---|---|
pow(x, y) | x^y |
exp(x) | e^x |
log(x) | 自然対数 |
exp2(x) | 2^x |
log2(x) | 底 2 の対数 |
sqrt(x) | 平方根 |
inversesqrt(x) | 1 / √x(高速) |
典型例: スペキュラハイライト
// rough = 0..1, より小さいほどシャープなハイライト
float spec = pow(max(dot(N, H), 0.0), shininess);
絶対値・符号・min/max
| 関数 | 意味 |
|---|---|
abs(x) | 絶対値 |
sign(x) | 符号(-1/0/1) |
min(a, b) | 小さい方 |
max(a, b) | 大きい方 |
clamp(x, lo, hi) | lo..hi に収める |
// 0..1 にクランプ
float t = clamp(rawT, 0.0, 1.0);
// ベクトルもまるごと
vec3 col = clamp(c, 0.0, 1.0);
丸め系
| 関数 | 意味 |
|---|---|
floor(x) | 切り捨て |
ceil(x) | 切り上げ |
round(x) | 四捨五入 |
trunc(x) | 0 方向に切り捨て |
fract(x) | 小数部 = x - floor(x) |
mod(x, y) | 剰余 = x - y * floor(x/y) |
典型例: 繰り返し模様
// UV を 4×4 の繰り返しに
vec2 tiled = fract(vUv * 4.0);
// グリッド番号
vec2 cell = floor(vUv * 8.0);
// 縞模様
float stripe = step(0.5, fract(vUv.x * 10.0));
補間関数(最重要)
| 関数 | 意味 |
|---|---|
mix(a, b, t) | 線形補間 a + (b-a) * t |
step(edge, x) | x >= edge なら 1、それ以外 0 |
smoothstep(e0, e1, x) | e0..e1 で滑らかに 0..1(Hermite 補間) |
mix の例
// 2 色の補間
vec3 col = mix(red, blue, vUv.y);
// 条件分岐の代わり(早い)
float v = mix(a, b, step(0.5, x)); // x >= 0.5 なら b、そうでなければ a
// bool 版(ES 3.00)
vec3 col = mix(red, blue, bvec3(isHover));
step の例
// しきい値で 0/1 に二値化
float bin = step(0.5, brightness);
// 矩形の中か(X方向)
float inX = step(0.2, vUv.x) * step(vUv.x, 0.8);
smoothstep の例
smoothstep はアンチエイリアスの相棒。境界をぼかして滑らかにする。
// アンチエイリアスありの円
float d = length(vUv - 0.5);
float c = smoothstep(0.31, 0.29, d); // 0.29 で 1、0.31 で 0
// 滑らかなフェードイン
float t = smoothstep(0.0, 1.0, x);
幾何関数
| 関数 | 意味 |
|---|---|
length(v) | ベクトルの長さ |
distance(a, b) | 2点間距離 |
dot(a, b) | 内積 |
cross(a, b) | 外積(vec3 のみ) |
normalize(v) | 長さを 1 に |
reflect(I, N) | 反射ベクトル |
refract(I, N, eta) | 屈折ベクトル |
faceforward(N, I, Nref) | 視点に向く法線を返す |
reflect の例
vec3 V = normalize(cameraPosition - vWorldPos);
vec3 N = normalize(vNormal);
vec3 R = reflect(-V, N); // ハイライト方向
vec3 envColor = texture(uEnvMap, R).rgb;
マトリックス関数
matrixCompMult(a, b)— 要素ごとの積(普通の*は線形変換なので別物)transpose(m)— 転置inverse(m)— 逆行列determinant(m)— 行列式outerProduct(c, r)— 列×行 の外積
ベクトル比較
lessThan(a, b)— 各要素を比較して bvec を返すlessThanEqual/greaterThan/greaterThanEqual/equal/notEqualany(bv)— いずれかが trueall(bv)— すべて truenot(bv)— 各要素を反転
テクスチャ系
詳しくは テクスチャ。サンプリング系の関数:
texture(sampler, uv)— テクスチャ取得(ES 3.00)texture2D(sampler, uv)— ES 1.00textureLod(sampler, uv, lod)— 明示的な mipmap レベルtextureGrad(sampler, uv, dPdx, dPdy)— 微分指定textureSize(sampler, lod)— テクスチャの寸法
導関数(fragment shader のみ)
dFdx(v)— 隣の x 方向の fragment との差dFdy(v)— y 方向の差fwidth(v)—abs(dFdx) + abs(dFdy)(精度の幅)
典型例: アンチエイリアスでエッジを描く
// ピクセル単位で一様な太さの線
float d = length(vUv - 0.5) - 0.3; // 円までの符号付き距離
float w = fwidth(d) * 1.5;
float c = smoothstep(w, -w, d);
outColor = vec4(vec3(c), 1.0);
整数ビット演算(GLSL ES 3.00+)
bitfieldExtract/bitfieldInsertbitCount/findLSB/findMSBfloatBitsToInt/intBitsToFloat— 型のビット列を再解釈uintBitsToFloat/floatBitsToUint
パッキング(ES 3.00+)
packSnorm2x16(v)/unpackSnorm2x16(u)— vec2 ↔ uintpackUnorm2x16/unpackUnorm2x16packHalf2x16/unpackHalf2x16— half float
頻出する自作関数
ハッシュ(疑似ランダム)
// 1D
float hash11(float p) {
p = fract(p * 0.1031);
p *= p + 33.33;
p *= p + p;
return fract(p);
}
// 2D
float hash21(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}
線形ステップ(境界をぼかさない)
float linearstep(float a, float b, float x) {
return clamp((x - a) / (b - a), 0.0, 1.0);
}
5次 smoothstep(より滑らか)
float smootherstep(float a, float b, float x) {
float t = clamp((x - a) / (b - a), 0.0, 1.0);
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
}
HSV → RGB
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
2D 回転
mat2 rot2(float a) {
float c = cos(a), s = sin(a);
return mat2(c, -s, s, c);
}
ベクトルにスカラ関数を適用
ほとんどの組み込み関数はベクトル全体に要素ごと適用される:
vec3 v = vec3(0.5, 1.0, 1.5);
sin(v); // (sin(0.5), sin(1.0), sin(1.5))
abs(v); // (0.5, 1.0, 1.5)
floor(v); // (0.0, 1.0, 1.0)
clamp(v, 0.0, 1.0); // (0.5, 1.0, 1.0)
混合タイプの引数も OK:
mix(vec3(0.0), vec3(1.0), 0.5); // float の t
mix(vec3(0.0), vec3(1.0), vec3(0.1, 0.5, 0.9)); // 各要素別の t
性能のヒント
pow / exp / log / atan / asin / acos は重い。
可能なら近似や別の関数で置き換える(pow(x, 2.0) → x * x など)。
sqrt も少し重い。距離比較は dot(d, d) < r * r のように2乗で比較すれば sqrt を回避できる。