組み込み関数

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;

マトリックス関数

ベクトル比較

テクスチャ系

詳しくは テクスチャ。サンプリング系の関数:

導関数(fragment shader のみ)

典型例: アンチエイリアスでエッジを描く

// ピクセル単位で一様な太さの線
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+)

パッキング(ES 3.00+)

頻出する自作関数

ハッシュ(疑似ランダム)

// 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 を回避できる。