3DCG で頻出の各種行列について、メモ。
・・・するつもりだったのだが、イマドキの API は一度各種行列の形を決めておけば、行列の中身を知らなくても、どうにかこうにかコーディング自体はできそう。
例えば、Metal であれば、以下のコードの vertxIn.position で示されたモデルの各点は(一度、projectionMatrix などを書いておけば)
float4 position = uniforms.projectionMatrix * uniforms.viewMatrix
* uniforms.modelMatrix * vertexIn.position;
の変換で float4 position に移される。
だから、これをシェーダーに書いておけばいい、という寸法だ。
この時、ややこしいとされている uniforms.projectionMatrix の要素を具体的に知らなくても必須パラメータの設定ができていれば、正しく動作する。
まず、最低限、理解すべきは
・M → V → P の流れ
・M に関しては Translation・Rotatio・Scale を意味する行列の積で表現できる
ことなのだろう。
Swift における行列の取り扱い
というわけで、これ。
let x = simd_double4(x: 10, y: 20, z: 30, w: 40)
let y = simd_double4(x: 1, y: 2, z: 3, w: 4)
/*
A matrix of two columns and four rows:
10 1
20 2
30 3
40 4
*/
let a = simd_double2x4([x, y]) // columns
/*
A matrix of four columns and two rows:
10 20 30 40
1 2 3 4
*/
let b = simd_double4x2(rows: [x, y])
projectionMatrix
これを踏まえて、projectionMatrix p を考える。
let y = 1 / tan(fov * 0.5)
let x = y / aspect
let z = lhs ? far / (far - near) : far / (near - far)
let X = float4( x, 0, 0, 0)
let Y = float4( 0, y, 0, 0)
let Z = lhs ? float4( 0, 0, z, 1) : float4( 0, 0, z, -1)
let W = lhs ? float4( 0, 0, z * -near, 0) : float4( 0, 0, z * near, 0)
let p = simd_float4x4([X, Y, Z, W])//columns
でしょうか。
viewMatrix
これも小理屈がある。
移動・拡大・回転の行列を translateMatrix, scaleMatrix, rotateMatrix としたとき、viewMatrix は
(translateMatrix * scaleMatrix * rotateMatrix).inverse//inverse 逆行列
でいいらしい。
(続く)

