WebGLで使う行列演算の備忘録

WebGLで使う行列演算の備忘録

目次

はじめに#

ライブラリを使用せず素の WebGL で書けるようになりたいと思い、最近はいろいろ勉強してます。WebGL を触るうえで行列演算は避けては通れません。WebGL 用の行列演算の既存のライブラリだと glMatrix がありますが、今回は線形代数の勉強も兼ねて自作で作ってみました。(自作といっても、ほぼほぼ OGL の数学演算系をもって来ているだけですが)

足し算などの簡単なのは飛ばして、何をやってるか忘れそうな処理について備忘録的に書いていきます。長くなるので、主に 3x3 行列をみていきます。

数学演算系のコードは以下に置いてます。

webgl-study-note/src/lib/webgl/math at main · nono-k/webgl-study-note
Contribute to nono-k/webgl-study-note development by creating an account on GitHub.
webgl-study-note/src/lib/webgl/math at main · nono-k/webgl-study-note favicon
github.com
webgl-study-note/src/lib/webgl/math at main · nono-k/webgl-study-note

3x3 行列(Mat3)#

3x3 (Mat3)行列のクラスは次のようにしてます。
演算系の関数はMat3Funcで書いています。

Mat3.ts
import * as Mat3Func from "./functions/Mat3Func";
 
export class Mat3 extends Array<number> {
  constructor(
    m00 = 1,
    m01 = 0,
    m02 = 0,
    m10 = 0,
    m11 = 1,
    m12 = 0,
    m20 = 0,
    m21 = 0,
    m22 = 1
  ) {
    super(m00, m01, m02, m10, m11, m12, m20, m21, m22);
  }
  // ...
}

数式で書くと次のような行列表記になります。

M=[m00m10m20m01m11m21m02m12m22]M = \begin{bmatrix} m_{00} & m_{10} & m_{20} \\ m_{01} & m_{11} & m_{21} \\ m_{02} & m_{12} & m_{22} \end{bmatrix}

デフォルト値は単位行列になります。

I=[100010001]I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}

ここからは、Mat3Func内をみていきます。

平行移動(translate)#

平行移動(x,y)を表す行列 T は次のようになります。

T=[10x01y001]T = \begin{bmatrix} 1 & 0 & x \\ 0 & 1 & y \\ 0 & 0 & 1 \end{bmatrix}

移動後の行列M′M'は、次のような行列の掛け算で求まります。

M′=M⋅T=[m00m10m20m01m11m21m02m12m22]⋅[10x01y001]=[m00m10m00x+m10y+m20m01m11m01x+m11y+m21m02m12m02x+m12y+m22]M' = M \cdot T = \begin{bmatrix} m_{00} & m_{10} & m_{20} \\ m_{01} & m_{11} & m_{21} \\ m_{02} & m_{12} & m_{22} \end{bmatrix} \cdot \begin{bmatrix} 1 & 0 & x \\ 0 & 1 & y \\ 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} m_{00} & m_{10} & m_{00}x + m_{10}y + m_{20}\\ m_{01} & m_{11} & m_{01}x + m_{11}y + m_{21} \\ m_{02} & m_{12} & m_{02}x + m_{12}y + m_{22} \end{bmatrix}

以上をコードで書くと次のようになります。

translate
export function translate(out: Mat3, a: Mat3, v: Vec2): Mat3 {
  const a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a10 = a[3],
    a11 = a[4],
    a12 = a[5],
    a20 = a[6],
    a21 = a[7],
    a22 = a[8],
    x = v[0],
    y = v[1];
 
  out[0] = a00;
  out[1] = a01;
  out[2] = a02;
 
  out[3] = a10;
  out[4] = a11;
  out[5] = a12;
 
  out[6] = x * a00 + y * a10 + a20;
  out[7] = x * a01 + y * a11 + a21;
  out[8] = x * a02 + y * a12 + a22;
  return out;
}

回転(rotate)#

角度θ\thetaの回転行列R(θ)R(\theta)は次のようになります。

R(θ)=[cos⁡θ−sin⁡θ0sin⁡θcos⁡θ0001]R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}

回転後の行列M′M'は、次のような行列の掛け算で求まります。

M′=M⋅R(θ)=[m00m10m20m01m11m21m02m12m22]⋅[cos⁡θ−sin⁡θ0sin⁡θcos⁡θ0001]M' = M \cdot R(\theta) = \begin{bmatrix} m_{00} & m_{10} & m_{20} \\ m_{01} & m_{11} & m_{21} \\ m_{02} & m_{12} & m_{22} \end{bmatrix} \cdot \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}

計算すると

M′=[m00cos⁡θ+m10sin⁡θ−m00sin⁡θ+m10cos⁡θm20m01cos⁡θ+m11sin⁡θ−m01sin⁡θ+m11cos⁡θm21m02cos⁡θ+m12sin⁡θ−m02sin⁡θ+m12cos⁡θm22]M' = \begin{bmatrix} m_{00}\cos\theta + m_{10}\sin\theta & -m_{00}\sin\theta + m_{10}\cos\theta & m_{20} \\ m_{01}\cos\theta + m_{11}\sin\theta & -m_{01}\sin\theta + m_{11}\cos\theta & m_{21} \\ m_{02}\cos\theta + m_{12}\sin\theta & -m_{02}\sin\theta + m_{12}\cos\theta & m_{22} \end{bmatrix}

以上をコードで書くと次のようになります。

rotate
export function rotate(out: Mat3, a: Mat3, rad: number): Mat3 {
  const a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a10 = a[3],
    a11 = a[4],
    a12 = a[5],
    a20 = a[6],
    a21 = a[7],
    a22 = a[8],
    s = Math.sin(rad),
    c = Math.cos(rad);
 
  out[0] = c * a00 + s * a10;
  out[1] = c * a01 + s * a11;
  out[2] = c * a02 + s * a12;
 
  out[3] = c * a10 - s * a00;
  out[4] = c * a11 - s * a01;
  out[5] = c * a12 - s * a02;
 
  out[6] = a20;
  out[7] = a21;
  out[8] = a22;
  return out;
}

拡大(scale)#

スケール行列SSは次のようになります。

S=[sx000sy0001]S = \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix}

回転後の行列M′M'は、次のような行列の掛け算で求まります。

M′=M⋅S[m00m10m20m01m11m21m02m12m22]⋅[sx000sy0001]M' = M \cdot S \begin{bmatrix} m_{00} & m_{10} & m_{20} \\ m_{01} & m_{11} & m_{21} \\ m_{02} & m_{12} & m_{22} \end{bmatrix} \cdot \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix}

計算すると

M′=[m00sxm10sym20m01sxm11sym21m02sxm12sym22]M' = \begin{bmatrix} m_{00}s_x & m_{10}s_y & m_{20} \\ m_{01}s_x & m_{11}s_y & m_{21} \\ m_{02}s_x & m_{12}s_y & m_{22} \end{bmatrix}

以上をコードで書くと次のようになります。

scale
export function scale(out: Mat3, a: Mat3, v: Vec2): Mat3 {
  const x = v[0];
  const y = v[1];
 
  out[0] = x * a[0];
  out[1] = x * a[1];
  out[2] = x * a[2];
 
  out[3] = y * a[3];
  out[4] = y * a[4];
  out[5] = y * a[5];
 
  out[6] = a[6];
  out[7] = a[7];
  out[8] = a[8];
  return out;
}

転置行列(transpose)#

転置行列は行と列を入れ替えた行列になります。
行列 M の転置行列は次のようになります。

M=[m00m10m20m01m11m21m02m12m22]⇒MT=[m00m01m02m10m11m12m20m21m22]M = \begin{bmatrix} m_{00} & m_{10} & m_{20} \\ m_{01} & m_{11} & m_{21} \\ m_{02} & m_{12} & m_{22} \end{bmatrix} \Rightarrow M^T = \begin{bmatrix} m_{00} & m_{01} & m_{02} \\ m_{10} & m_{11} & m_{12} \\ m_{20} & m_{21} & m_{22} \end{bmatrix}

コードで書くと次のようになります。

transpose
export function transpose(out: Mat3, a: Mat3): Mat3 {
  if (out === a) {
    // 上書き前に退避
    const a01 = a[1];
    const a02 = a[2];
    const a12 = a[5];
 
    out[1] = a[3];
    out[2] = a[6];
    out[3] = a01;
    out[5] = a[7];
    out[6] = a02;
    out[7] = a12;
  } else {
    out[0] = a[0];
    out[1] = a[3];
    out[2] = a[6];
    out[3] = a[1];
    out[4] = a[4];
    out[5] = a[7];
    out[6] = a[2];
    out[7] = a[5];
    out[8] = a[8];
  }
  return out;
}

ここで、out === aの場合は、対角成分は変わらないので、それ以外の成分を入れ替えます。

行列式(determinant)#

3x3 の行列式は、以下のようになります。

det(M)=m00(m11m22−m12m21)−m01(m12m20−m10m22)+m02(m10m21−m11m20)det(M) = m_{00}(m_{11}m_{22} - m_{12}m_{21}) - m_{01}(m_{12}m_{20} - m_{10}m_{22}) + m_{02}(m_{10}m_{21} - m_{11}m_{20})

コードでは次のようになります。

determinant
export function determinant(a: Mat3): number {
  const a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a10 = a[3],
    a11 = a[4],
    a12 = a[5],
    a20 = a[6],
    a21 = a[7],
    a22 = a[8];
 
  return (
    a00 * (a11 * a22 - a12 * a21) +
    a01 * (a12 * a20 - a10 * a22) +
    a02 * (a10 * a21 - a11 * a20)
  );
}

逆行列(inverse)#

行列 M の逆行列M−1M^{-1}を掛けたときに、単位行列 I になるような行列M−1M^{-1}を逆行列といいます。

M⋅M−1=IM \cdot M^{-1} = I

行列式をdetdetとすると、逆行列M−1M^{-1}は次のようになります。

M−11det[(m11m22−m12m21)(m20m12−m10m22)(m10m21−m20m11)(m02m21−m01m22)(m00m22−m02m20)(m20m01−m00m21)(m01m12−m02m11)(m02m10−m00m12)(m00m11−m01m10)]M^{-1} \frac{1}{det} \begin{bmatrix} (m_{11}m_{22} - m_{12}m_{21}) & (m_{20}m_{12} - m_{10}m_{22}) & (m_{10}m_{21} - m_{20}m_{11}) \\ (m_{02}m_{21} - m_{01}m_{22}) & (m_{00}m_{22} - m_{02}m_{20}) & (m_{20}m_{01} - m_{00}m_{21}) \\ (m_{01}m_{12} - m_{02}m_{11}) & (m_{02}m_{10} - m_{00}m_{12}) & (m_{00}m_{11} - m_{01}m_{10}) \end{bmatrix}

コードで書くと次のようになります。

inverse
export function invert(out: Mat3, a: Mat3): Mat3 {
  const a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a10 = a[3],
    a11 = a[4],
    a12 = a[5],
    a20 = a[6],
    a21 = a[7],
    a22 = a[8];
 
  const b01 = a11 * a22 - a12 * a21;
  const b11 = a12 * a20 - a10 * a22;
  const b21 = a10 * a21 - a11 * a20;
 
  let det = a00 * b01 + a01 * b11 + a02 * b21;
  det = 1.0 / det;
 
  out[0] = b01 * det;
  out[1] = (a02 * a21 - a01 * a22) * det;
  out[2] = (a01 * a12 - a02 * a11) * det;
  out[3] = b11 * det;
  out[4] = (a00 * a22 - a02 * a20) * det;
  out[5] = (a02 * a10 - a00 * a12) * det;
  out[6] = b21 * det;
  out[7] = (a01 * a20 - a00 * a21) * det;
  out[8] = (a00 * a11 - a01 * a10) * det;
  return out;
}

4x4 行列(Mat4)#

4x4 (Mat4)行列のクラスは次のようにしてます。演算系の関数はMat4Funcで書いています。

Mat4
import * as Mat4Func from "./functions/Mat4Func";
 
export class Mat4 extends Array<number> {
  constructor(
    m00 = 1,
    m01 = 0,
    m02 = 0,
    m03 = 0,
    m10 = 0,
    m11 = 1,
    m12 = 0,
    m13 = 0,
    m20 = 0,
    m21 = 0,
    m22 = 1,
    m23 = 0,
    m30 = 0,
    m31 = 0,
    m32 = 0,
    m33 = 1
  ) {
    // 同様にsuper()する
  }
  // ...
}

4x4 行列は数式で書くと次のような行列表記になります。

M=[m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33]M = \begin{bmatrix} m_{00} & m_{10} & m_{20} & m_{30} \\ m_{01} & m_{11} & m_{21} & m_{31} \\ m_{02} & m_{12} & m_{22} & m_{32} \\ m_{03} & m_{13} & m_{23} & m_{33} \end{bmatrix}

デフォルト値は単位行列になります。

I=[1000010000100001]I = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

ここからは、Mat4Func内をみていきます。

平行移動(translate)#

平行移動(x, y , z)を表す行列 T は次のようになります。

T=[100x010y001z0001]T = \begin{bmatrix} 1 & 0 & 0 & x \\ 0 & 1 & 0 & y \\ 0 & 0 & 1 & z \\ 0 & 0 & 0 & 1 \end{bmatrix}

移動後の行列M′M'は、次のような行列の掛け算で求まります。

M′=M⋅T=[m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33]⋅[100x010y001z0001]=[m00m10m20m00x+m10y+m20z+m30m01m11m21m01x+m11y+m21z+m31m02m12m22m02x+m12y+m22z+m32m03m13m23m03x+m13y+m23z+m33]\begin{align} M' = M \cdot T &= \begin{bmatrix} m_{00} & m_{10} & m_{20} & m_{30} \\ m_{01} & m_{11} & m_{21} & m_{31} \\ m_{02} & m_{12} & m_{22} & m_{32} \\ m_{03} & m_{13} & m_{23} & m_{33} \end{bmatrix} \cdot \begin{bmatrix} 1 & 0 & 0 & x \\ 0 & 1 & 0 & y \\ 0 & 0 & 1 & z \\ 0 & 0 & 0 & 1 \end{bmatrix} \notag \\ &= \begin{bmatrix} m_{00} & m_{10} & m_{20} & m_{00}x + m_{10}y + m_{20}z + m_{30}\\ m_{01} & m_{11} & m_{21} & m_{01}x + m_{11}y + m_{21}z + m_{31} \\ m_{02} & m_{12} & m_{22} & m_{02}x + m_{12}y + m_{22}z + m_{32} \\ m_{03} & m_{13} & m_{23} & m_{03}x + m_{13}y + m_{23}z + m_{33} \end{bmatrix} \notag \end{align}

以上をコードで書くと次のようになります。

translate
export function translate(out: Mat4, a: Mat4, v: Vec3): Mat4 {
  const x = v[0],
    y = v[1],
    z = v[2];
 
  if (a === out) {
    out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
    out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
    out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
    out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  } else {
    const a00 = a[0],
      a01 = a[1],
      a02 = a[2],
      a03 = a[3],
      a10 = a[4],
      a11 = a[5],
      a12 = a[6],
      a13 = a[7],
      a20 = a[8],
      a21 = a[9],
      a22 = a[10],
      a23 = a[11];
 
    out[0] = a00;
    out[1] = a01;
    out[2] = a02;
    out[3] = a03;
    out[4] = a10;
    out[5] = a11;
    out[6] = a12;
    out[7] = a13;
    out[8] = a20;
    out[9] = a21;
    out[10] = a22;
    out[11] = a23;
 
    out[12] = a00 * x + a10 * y + a20 * z + a[12];
    out[13] = a01 * x + a11 * y + a21 * z + a[13];
    out[14] = a02 * x + a12 * y + a22 * z + a[14];
    out[15] = a03 * x + a13 * y + a23 * z + a[15];
  }
 
  return out;
}

回転(rotate)#

角度θ\thetaの回転行列R(θ)R(\theta)は次のようになります。

R(θ)=R(\theta) =

以上をコードで書くと次のようになります。

rotate
export function rotate(out: Mat4, a: Mat4, rad: number, axis: Vec3): Mat4 {
  let x = axis[0];
  let y = axis[1];
  let z = axis[2];
 
  let len = Math.hypot(x, y, z);
  len = 1 / len;
  x *= len;
  y *= len;
  z *= len;
 
  const s = Math.sin(rad);
  const c = Math.cos(rad);
  const t = 1 - c;
 
  const a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a03 = a[3],
    a10 = a[4],
    a11 = a[5],
    a12 = a[6],
    a13 = a[7],
    a20 = a[8],
    a21 = a[9],
    a22 = a[10],
    a23 = a[11];
 
  const b00 = x * x * t + c;
  const b01 = y * x * t + z * s;
  const b02 = z * x * t - y * s;
  const b10 = x * y * t - z * s;
  const b11 = y * y * t + c;
  const b12 = z * y * t + x * s;
  const b20 = x * z * t + y * s;
  const b21 = y * z * t - x * s;
  const b22 = z * z * t + c;
 
  out[0] = a00 * b00 + a10 * b01 + a20 * b02;
  out[1] = a01 * b00 + a11 * b01 + a21 * b02;
  out[2] = a02 * b00 + a12 * b01 + a22 * b02;
  out[3] = a03 * b00 + a13 * b01 + a23 * b02;
  out[4] = a00 * b10 + a10 * b11 + a20 * b12;
  out[5] = a01 * b10 + a11 * b11 + a21 * b12;
  out[6] = a02 * b10 + a12 * b11 + a22 * b12;
  out[7] = a03 * b10 + a13 * b11 + a23 * b12;
  out[8] = a00 * b20 + a10 * b21 + a20 * b22;
  out[9] = a01 * b20 + a11 * b21 + a21 * b22;
  out[10] = a02 * b20 + a12 * b21 + a22 * b22;
  out[11] = a03 * b20 + a13 * b21 + a23 * b22;
 
  if (a !== out) {
    out[12] = a[12];
    out[13] = a[13];
    out[14] = a[14];
    out[15] = a[15];
  }
  return out;
}

拡大(scale)#

転置行列(transpose)#

行列式(determinant)#

逆行列(inverse)#

Related Post
「リアルタイムグラフィックスの数学」勉強ログ - 第8章 3Dレンダリング
image

はじめに

「リアルタイムグラフィックスの数学」の第 8 章の 3D レンダリングについての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

テクスチャマッピング

地面とレイの交点を計算し、地面に市松模様をテクスチャとしてマッピングします。市松模様のテクスチャは次のようになります。

float text(vec2 st) {
  return mod(floor(st.s) + floor(st.t), 2.0);
}

ここで 3D 空間のカメラの設定をします。カメラの向きを$\bm{x} = (0, 0, -1)$とし、カメラの上方向を$\bm{y} = (0, 1, 0)$とします。この値に対して外積をとることで、撮影する向きに対する水平方向$(1, 0, 0)$を得ることができます。実際の計算は次のようになります。

Meta Data
公開日:2025-10-11
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第7章 距離とSDF
image

はじめに

「リアルタイムグラフィックスの数学」の第 7 章の距離と SDF についての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

2 次元 SDF

胞体ノイズでは近傍点との距離を返す関数でしたが、近くの「点」ではなく「図形」との距離を返す関数を考えます。ここでは図形との負の値もありうる距離を返す関数を導入します。これがSDF(Signed Distance Function, 符号付き距離関数)となります。

円の SDF

円の SDF について考えてみます。円は中心点 C と半径 r から決まりますが、C からの距離が r より小さければ円の「内部」、r より大きければ円の「外部」となり、r と等しい場合は円の「境界」です。平面上の点 P に対して、円の外部では値は正、内部では値が負とします。これが円の SDF を定めます。

円のSDF

Meta Data
公開日:2025-10-05
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第6章 胞体ノイズ
image

はじめに

「リアルタイムグラフィックスの数学」の第 6 章の胞体ノイズについての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

胞体ノイズとは?

値ノイズと勾配ノイズは格子点でのランダムな値を使ったノイズ関数でした。一方この章で学ぶ胞体ノイズは距離を使ってつくられます。胞体(セル)とは生物の細胞などのことで、胞体ノイズは「近さ」によって空間をバラバラに分割します。

第 1 近傍距離とボロノイ分割

胞体ノイズは空間内に点をバラまいて、各点への距離を測ることで得られますが、バラまかれたこれらの点は特徴点と呼ばれます。ここで特徴点を$A_1,...,A_n$とします。空間内の点 P を定めたとき、P から特徴点$A_i$への距離を$d(P, A_i)$で表すと、すべての特徴点までの距離の最小値は次のように求まります。

$$ \mathrm{min}(d(P, A_1), ... , d(P, A_n)) $$

Meta Data
公開日:2025-09-30
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第5章ノイズの調理法
image

はじめに

「リアルタイムグラフィックスの数学」の第 5 章のノイズの調理法についての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

再帰

再帰関数とは、関数の中で自分自身の関数を呼び出すような関数のことです。GLSL では再帰関数は使えませんが、for 文を使って再帰的な処理を行うことができます。

非整数ブラウン運動(fBM)

1 以下の定数 G に対し、1 変数ノイズ関数 noise(x)の周波数を 2 倍するごとに値を G 倍して、それを足し合わせてみましょう。式にすると次のようになります。

$$ noise(x) + Gnoise(2x) + G^2noise(4x) + ... + G^knoise(2^kx) $$

ここで素材となるノイズ関数 noise(x)はどのような関数でもいいですが、値の範囲を$[-0.5, 0.5]$区画にずらしておきます。このように加工されたノイズ関数は非整数ブラウン運動(fractional Brownian motion, fBM)と呼ばれます。

Meta Data
公開日:2025-09-24
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第4章勾配ノイズ
image

はじめに

「リアルタイムグラフィックスの数学」の第 4 章の勾配ノイズについての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

勾配ノイズとは?

前回は値ノイズについて見てきました。値ノイズは計算量も少なく、簡単につくれるノイズですが、格子で区切っているのでブロック状に見えてしまいますし、ムラが現れやすいです。値ノイズを改善したノイズが勾配ノイズになります。

値ノイズの場合は、格子点での乱数の「値」を使うのに対し、勾配ノイズは乱数のベクトル値を「勾配」として使用します。ノイズ関数でよく使用されるパーリンノイズは、この勾配ノイズの一種であります。この章では、勾配ノイズと 2002 年の Perlin による改良版勾配ノイズ(パーリンノイズ)について見ていきます。

勾配ノイズの構成法

1 変数

値ノイズは乱数値をエルミート補間してつくりました。ここで別の見方として、$h(0) = 0$,$h(1) = 1$,$h'(0) = h'(1) = 0$ を満たすエルミート補間関数$h(x)$に対して、$w(x)$を次のように定義します。

Meta Data
公開日:2025-09-20
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第3章値ノイズ
image

はじめに

「リアルタイムグラフィックスの数学」の第 3 章の値ノイズについての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

値ノイズの構成法

まずは 2 次元の値ノイズの構成法について見てみましょう。

平面上の正方形の4つの頂点(格子点)

平面上の正方形の 4 つの頂点(格子点)を用いて、値ノイズを構成します。各格子点での乱数値、または乱数ベクトルを使って生成されるノイズを格子ノイズと呼びます。格子点の成分は整数になるようにします。点$(x, y)$に対して床値$[]$を使って、$(x, y)$を取り囲むマスの格子点は次の 4 つのベクトルで表します。

Meta Data
公開日:2025-09-16
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第2章疑似乱数
image

はじめに

「リアルタイムグラフィックスの数学」の第 2 章の疑似乱数についての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

レガシー乱数

GLSL ES 1.0 ではビット演算が使えないため、ハッシュ関数ではなくサイン関数を使用した乱数生成が行われていました。The Book of Shaders ではサイン関数を使用した乱数生成の方法が紹介されています。

https://thebookofshaders.com/10/?lan=jp

サイン関数自体には乱数性はないですが、サイン関数の値に大きい値をかけて桁を上げ、fractで小数部分を取り出すことで乱数のように見えることができます。

レガシー乱数の 1 変数と 2 変数のコードは次のようになります。

// 1変数のレガシー乱数
float fractSin11(float x) {
  return fract(1000.0 * sin(x));
}

// 2変数のレガシー乱数
float fractSin21(vec2 xy) {
  return fract(sin(dot(xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
Meta Data
公開日:2025-09-10
Tags:
#GLSL
#数学
#勉強ログ
「リアルタイムグラフィックスの数学」勉強ログ - 第1章補間
image

はじめに

「リアルタイムグラフィックスの数学」の第 1 章の補間についての勉強ログです。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

線形補間とグラデーション

mix 関数について

GLSL における mix 関数は以下のような数式になります。

$$ \bm{a} + x\overrightarrow{AB} = \bm{a} + x(\bm{b} - \bm{a}) = (1 - x)\bm{a} + x\bm{b} $$

これは、線分 AB があり、その線分上を動く 0 以上 1 以下の x に対して、線分 AB を x: (1 - x)に内分する点の位置ベクトルを表しています。上記の式のベクトルをmix(a, b, x)として定義しています。このように 2 点間をつなぐことを補間と呼び、上記の式は線形補間(Linear Interpolation)の公式です。

コード 1.1 のように、赤(1, 0, 0)と青(0, 0, 1)を mix 関数でつなぐことで 2 色のグラデーションを作ることができます。

vec2 RED = vec3(1.0, 0.0, 0.0);
vec3 BLUE = vec3(0.0, 0.0, 1.0);
vec3 col = mix(RED, BLUE, pos.x);

赤と青のグラデーション

Meta Data
公開日:2025-09-07
Tags:
#GLSL
#数学
#勉強ログ
勉強のために「リアルタイムグラフィックスの数学」のGLSLコードを確認できるサイトを作った

はじめに

シェーダに再挑戦したいと思い、「リアルタイムグラフィックスの数学」の本をまた読み直してます。

<AmazonLink imageId="61CP8Asy52L.SY522" linkId="3Iy0agT" title="リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング" author="巴山竜来" />

勉強する際に、本に書いているサンプルコードを Web サイトですぐに確認できるように、Astro と Three.js を使用して GLSL コードを表示するサイトを作成しました。サイトはこちらになります。

リポジトリはこちらになります!

https://github.com/nono-k/book-of-realtime-graphics-math

勉強方法の方針

いったん、本を読みながらローカルの VSCode 上で GLSL コードを書いて確認して、Web サイトに GLSL のコードと実行結果のサムネをアップしていきたいと思います。

また、このブログで勉強した内容を章ごとに残していきたいと思います。以下はリンクになります。

Meta Data
公開日:2025-09-06
Tags:
#GLSL
#数学
読んだ本リスト
誤解学
誤解学
誤解学
人文・思想・社会
著者
西成 活裕
発売日
2014年5月22日

「渋滞学」で著名な西成活裕氏は、誤解のことをこう書く

誤解とは、コミュニケーションの流れにおける渋滞のようなものである。誤解はそれまでの流れの様子を一気に変化させ、関係者にとって好ましくない状態を作り出してしまう

そもそも誤解が発生してしまうメカニズムとは何であるのか。
第二章では誤解の理論を構築していく。

理論構築のためには因果関係を表すモデルを作成し分析する。このモデルをIMV分析と呼ぶ。それぞれ下記の頭文字をとったものだ。

  • Iはintension(真意・意図)
  • Mはmessage(情報)
  • Vはview(見解)

誤解は自分の意図と相手の見解のズレで発生する。つまりI ≠ Vのときだ。

その他にも、自分の意見がどれぐらい保持するのかを表す頑固度K、VとIがどれくらいズレるかという指標、ズレを表す伝達度Gの変数も分析には含まれる。

ここで数理モデルの面白さを感じたのは、頑固度Kと伝達度Gが一定で変化しない条件のときではあるが、二者のコミュニケーションの最終合意がどこに行きつくかがシミュレーションで予測できることだ。

この条件の元だと、先手有利の法則になり、最初に話しかけた方が有利になるとのことだ。
このようなことが理論的に示せるのが興味深いと思った。

もちろん実際には、変数である頑固度や伝達度は会話のやり取りで変化するので、より複雑になるであろう。このことも本書で書かれていたらよかったが、残念ながら本書ではカバーしきれていない。

複雑さまで書かれていないのが不満ではあったが、数理モデルの面白さを知る上での良い入門書ではあるだろう。

関連サイト(外部サイト)
「誤解学」の参考文献一覧

Meta Data
公開日:2026-09-22
Tags:
#人文・思想・社会
本屋という仕事
本屋という仕事
本屋という仕事
本屋
著者
三砂 慶明
発売日
2022年6月14日

日本全国各地の書店員たちが、本について、本屋という仕事についての語る。

ただ本が好きだから売るのではなく、本屋として商売としてどう成り立たせるのか様々な思いが綴られている。

また、ある書店員さんは、本屋の「棚づくり」について語られており、本屋さんの思いがあらわれる場所なのだと感じた。

紙の本が好きだし、本屋という場所が好きなので、これからも微力ながら応援したい場所だ。

Meta Data
公開日:2026-09-22
Tags:
#本屋
鏡映反転――紀元前からの難問を解く
鏡映反転――紀元前からの難問を解く
鏡映反転――紀元前からの難問を解く
心理学
著者
高野 陽太郎
発売日
2015年7月15日

紀元前プラトンからの難問であった鏡映反転の謎について見ていく。
鏡映反転とは、「鏡に映ると左右が反対に見える」現象だ。

実をいうと光学的にいえば、「鏡面に垂直な方向だけを反転し、鏡面と平行な方向は反転しない」となる。
なので、鏡と正対しているときは、前後は反転するが、上下も左右も反転しないといえる。純粋に物理的な観点からみれば、「鏡が左右を反転するのはなぜか?」という問題は存在しないともいえる。

だが、実際に左右が反対に見えるし、それはなぜなのかという疑問が残るだろう。なので、鏡映反転の問題は物理的な問題ではなく、人間の認知の問題となってくる。

いままでに鏡映反転のさまざまな説明が、著名な物理学者や心理学者から出されていたが、どれも矛盾や批判があり、定説がないのが鏡映反転の現象である。自分自身の鏡映反転を説明しようとすると、文字の鏡映反転に矛盾が生じ、逆もしかりである。

そこで著者は、自分自身の鏡映反転と文字の鏡映反転は、それぞれ別の原理から生じると考える。
「表象反転・視点反転・光学反転」の3つの現象からなる多重プロセス理論を提唱する。

4章からは、実験結果をもとに多重プロセス理論の説明を行う。また、理解を深めるために他説の反証なども行っている。

レビューなどにあるように、この多重プロセス理論にも批判はあるようだ。
本書を読んで鏡映反転現象を説明する複雑さを感じる。そもそも鏡映反転という現象が複雑なのだ。理論を単純にすると、説明できない現象が出てきてしまうし、他説とのせめぎ合いもある。

装丁だけ見たら面白サイエンス本だと思ったが、実際には精緻に科学的な説明を行っており、誠実な本でありました。また光学的な現象だと思ったら、心理的認知の話でもあるなど、色彩関連と似たような現象が鏡映反転にもあることを知れてよかったです。

関連サイト(外部サイト)
「鏡映反転――紀元前からの難問を解く」の参考文献一覧

Meta Data
公開日:2026-09-21
Tags:
#心理学
これからの本屋読本
これからの本屋読本
これからの本屋読本
本屋
ビジネス
著者
内沼 晋太郎
発売日
2018年5月25日

「本の惑星」というポットキャストのパーソナリティでもある内沼さんの著書になります。
本屋をめぐる状況と、本の仕入れ方、流通の仕組み、本屋の経営について書いてあります。

前半は本と本屋の魅力について書かれています。
「本が好き」「本屋が好き」とことばにする人が増えたとありますが、今ほど情報に簡単にアクセスできない、昔は「好きだから」ではなく「必要だから」本屋に人が来ていました。けれどいまは、必ずしも生活に必要なものではなくなったことで、逆に「好き」という気持ちが健在化してきたからなのでは、という分析はなるほどなと思いました。

本を売る場所のことばとして、「書店」と「本屋」ということばがありますが、これらの違いにも触れられています。「書店」は空間・場所寄りの意味になり、「本屋」は「屋」の字から、本をそろえて売買する人、本を専門としている人のことで、人寄りのことばになります。

内沼さんは一貫として「本屋」ということばを使っています。本を専門としている人のことも積極的に、広義の「本屋」と呼んでいき、本というものは、そういう人たち抜きには成立しないからです。

このことは、後半の小さな本屋を続ける考え方につながっています。現状、本を売るだけで生計を立てることは難しいでしょう。「本」と「何か」の掛け算の本屋運営のすすめが書かれています。

また、本屋を本業に取り込む考え方や、逆に副業としての本屋について述べられており、だれもが広義の本屋としてのライフワークになれるのだと思いました。

自分としては、このブログでやっているように、読んだ本の紹介を続けていきたいのと、街のシェア本棚や一箱古本市に参加してみたいと思いました。

本が好きな人、いつか本屋をやってみたい人におすすめの1冊になります。

Meta Data
公開日:2026-09-19
Tags:
#本屋
#ビジネス
印刷に恋して
印刷に恋して
印刷に恋して
印刷
著者
松田 哲夫
発売日
2002年1月9日

1997年から2001年の印刷現場の体験レポート。今では見ることがなくなった、活版印刷や手動写植などの技術や職人たちの仕事ぶりが描かれている。表紙にある内澤旬子さんのイラストもステキです。

コロタイプのような写真製版、網点などが好きなことを再確認。
箔押しなどの特殊印刷にも触れられており勉強になった。

本の感想はこちらにも書きました!

Meta Data
公開日:2026-09-18
Tags:
#印刷
「読者」の誕生―活字文化はどのようにして定着したか
「読者」の誕生―活字文化はどのようにして定着したか
「読者」の誕生―活字文化はどのようにして定着したか
文化論
人文・思想・社会
著者
香内 三郎
発売日
2004年12月9日

著者の専攻が、マス・コミュニケーション論とイギリス言論史なのもあり、本書は主に十七世紀のピューリタン革命期イギリスを舞台に近代ジャーナリズムの発展をみていく。

これもメディア論といえるのだろう。メディア論というと、どうしてもデジタルやテレビなどの媒体を連想させるが、手書き文字、パンフレット、活字も対象になる。こうした媒体が人びとの意識をどのように変容させてきたか。それにはキリスト教との関連で見ていかなければ理解できない。

なので、本書の前半で中世初期の「イコン論争」の分析から始まる。そこから偶像崇拝のイメージ論争、聖書の読み方の解釈(字義通りの意味など)などをみていく。

イギリス史では、ミルトンやホッブズ、デフォーなどの論客が対象にした「読者像」を考察し、近代ジャーナリズムの発展を追っていく。


タイトルからの想像と外れて、十七世紀イギリスの話が大半であり、特に宗教についても詳しくないので読み進めるのが大変だった。聖書解釈によって論争が生まれるなんて怖いって思ったり。

著者の専攻なので仕方がないが、「読者」を語るのに十七世紀イギリスばかりを扱っていいのかとも思った。もう少しキリスト教との関連もタイトルに含まれていたら...。

この時代に疎いので勉強になったが、日本の「読者」像を知りたくなったので、この本(近代読者の成立)も次は読んでみよう。

Meta Data
公開日:2026-09-14
Tags:
#文化論
#人文・思想・社会
新しい文章力の教室 苦手を得意に変えるナタリー式トレーニング
新しい文章力の教室 苦手を得意に変えるナタリー式トレーニング
新しい文章力の教室 苦手を得意に変えるナタリー式トレーニング
文章術
著者
唐木 元
発売日
2015年8月6日

文章術に関しての本を読んだことがなかったので、中盤からの基礎的な部分が参考になった。だが問題は、自分の文章を客観的に添削してくれる人がいないことなんだよな。文章を読み返したりしても、違和感や正しくない文章を自分では気付けないのが問題だ。文章術の本を他にも読んでいけば身につくのだろうか。

とりあえず文章術に関しての1冊目としては、悪い本ではないと思いました。
若干上から目線なのは気になる部分ではあるが...
他にも文章術についての本を読んでみよう。

Meta Data
公開日:2026-09-11
Tags:
#文章術
働きたくないイタチと言葉がわかるロボット 人工知能から考える「人と言葉」
働きたくないイタチと言葉がわかるロボット 人工知能から考える「人と言葉」
働きたくないイタチと言葉がわかるロボット 人工知能から考える「人と言葉」
AI
言語学
著者
川添愛
発売日
2017年6月16日

機械学習・ディープラーニング・ベクトル化などの理系と、言語学などの文系が関わってくるこの分野の話は、とても興味があり面白い。「言葉が分かる」ことや「意味が分かる」ということは、普段の生活では意識することがないであろう。だが、人間ではない機械のことを考えると、途端に私たち人間の凄さが現れてくるのが人工知能についての話を読む面白さか。

機械で人間の言語能力を再現しようとするときに、難しくなる要因は、「人間の無意識の能力」にあります。無意識の能力とは、言葉の曖昧性や会話的含み、意味理解など多数あり、本書を読むと私たち自身についても考えさせれることとなります。

また、言語学は何を目的にした学問なのか、この本を読むまで知らなかったのですが、こうした「人間の無意識の能力」を科学的に解明することを目標にしていることを知れたのもよかったです。

「言葉がわかる機械」をめぐるイタチたちの物語と、その物語からの解説といった形になっており、人工知能について誰でも読みやすく工夫されているのもいいですね。

関連サイト(外部サイト)
「働きたくないイタチと言葉がわかるロボット 人工知能から考える「人と言葉」」の参考文献一覧

Meta Data
公開日:2026-09-11
Tags:
#AI
#言語学
インフィニティ・パワー: 宇宙の謎を解き明かす微積分
インフィニティ・パワー: 宇宙の謎を解き明かす微積分
インフィニティ・パワー: 宇宙の謎を解き明かす微積分
サイエンス
数学
著者
スティーヴン・ストロガッツ
発売日
2020年1月27日

高校時代に微積分で挫折した人は多いと思う。無味乾燥な記号操作をして、その意味を理解することなく、暗記して問題を解いてる人もいたのでは。ストロガッツが書くこの本では、一般の人に伝わるように微積分についての歴史的事実、エピソードや活用事例を、ときには数式も交えながら分かりやすく書いてくれる。

数学に縁がない人にも読めるように、大学数学で登場するイプシロン-デルタ論法などは出てこないで、タイトルにある「無限」の威力をで分かりやすく微積分を説明する。

微積分それ自体については知っている知識ではあったし、例えを用いることでかえって分かりづらくなっていると感じたのが難点か。

この本では、数学史のエピソードの話が面白いと思った。

第4章の「微分の夜明け」では、デカルトとフェルマーが出てくるが、この2人は仲が悪かったらしい。というよりも、デカルトがかなり悪い感じに描かれており、こんな人だったなんて知らなかった。

他の同時代の2人の話では、ニュートンとライプニッツの話が出てくる。彼らの微積分への思いつきは別々のルートで到達したという話は面白い。ニュートンは、運動と流れを好んで無限小を否定して定理にたどり着いたのに対し、ライプニッツは無限小を便利な簡略表記と捉え、極限に関する議論を作り直す有効な手段として定理にたどり着いた。

無限小といったものは、現実に存在しないわけで、ライプニッツと彼の学徒たちにとっての無限小は、有用な「心の創作」として存在したという表現が印象的だった。

簡易的なモデルではあるが、自然を数学で表現できること自体、凄いことである。
「無限」もまた存在しないが、数学の発展に寄与したという物語を知れば、数学への苦手意識も減るのではないか。そんな著者の思いから産み出された1冊なので、ぜひ読んでもらって微積分の素晴らしさを実感してもらいたい。

関連サイト(外部サイト)
「インフィニティ・パワー: 宇宙の謎を解き明かす微積分」の参考文献一覧

Meta Data
公開日:2026-09-09
Tags:
#サイエンス
#数学
服飾文化論: 服飾の見かた・読みかた
服飾文化論: 服飾の見かた・読みかた
服飾文化論: 服飾の見かた・読みかた
ファッション
著者
小池 三枝
発売日
1998年4月30日

人間だけが衣服を着ている。衣服には機能や表現も含まれる。

本書では、衣服を人間と動物とを区別するレベルで考えるのではなく、人間存在として長いあいだに培われてきた文化として考えていく。長い時間を経て、衣服を着ることが、人びとの心とどのようにかかわるのかということに焦点をあてている。

「服飾」という語があるが、「飾」とあるように、単に着るものをあらわすだけでなく、美的な意味を文字から読みとることができよう。何らかの楽しみや喜び、記号とされた制度、あるいは感動を見いだすことのできる衣服をとりあげ語っていく。

そこには文学作品に出てくる服飾も、意味を読みとることができる。文字だけの情報でありながら、服飾それ自体の描写で、身につけている人物の年齢・性別・職業・趣味・教養・性癖・経済状態などを示す一種の記号である情報を付与することができ、登場人物を読者に印象づける役割をもつ。

服飾はつねに、着る人とかかわり、また時代の動きとかかわりながら、さまざまな訴えかたをし、さまざまな美を実現するのだ。

ここでとりあがられる事例のほとんどは日本のものとなる。過去において日本人が服飾にいかにこまやかな感情を抱いてきたかを見つめ直すキッカケになるだろう。長い歴史をもつ衣服について、考えさせられる一冊となる。

関連サイト(外部サイト)
「服飾文化論: 服飾の見かた・読みかた」の参考文献一覧

Meta Data
公開日:2026-09-06
Tags:
#ファッション
Info