Tech Notes

w除算の結合律について

久々に小ネタ。現代のGPUにはw除算と呼ばれる仕様が存在するが、これは一種の二項演算として見たときに結合律を満たすのか?という疑問について。

結論から言うと満たす。以下ではその証明を書く。

(2025/3/17追記)シェーダの挙動について不正確な点があったのでリライト

w除算とは

ググれば出てくるのだが端的に書く。

3DCGにおいては3次元空間の座標を画面上の2次元座標に変換しなければならない。この計算において1か所だけどうしても除算が出てくる場面がある。それを自動的にやるのがw除算という機能である。

3次元→2次元の座標変換は基本的に頂点シェーダで行われるのだが、この頂点シェーダは2次元ではなく4次元ベクトルを出力する。このうちxy成分は画面座標に、z成分は奥行き(=重なり順)情報に使われる。そして4つ目のw成分によって行われるのがw除算である。

頂点シェーダの出力したベクトルは最後に全体がそのw成分で割られる。 w除算とはそれだけの機能だ。大抵の頂点シェーダのコードでは行列の乗算(線形)しか行っていないが、遠近法という非線形な効果が起きているのはこのw除算によるものである。

本題

4次元ベクトルに4x4行列をかけた場合、普通の数学ならこうなる。

$$ \begin{pmatrix} A_{11} & A_{12} & A_{13} & A_{14} \\ A_{21} & A_{22} & A_{23} & A_{24} \\ A_{31} & A_{32} & A_{33} & A_{34} \\ A_{41} & A_{42} & A_{43} & A_{44} \\ \end{pmatrix} \begin{pmatrix}x \\ y \\ z \\ w \end{pmatrix} =\begin{pmatrix}A_{11} x + A_{12} y + A_{13} z + A_{14} w \\ A_{21} x + A_{22} y + A_{23} z + A_{24} w \\ A_{31} x + A_{32} y + A_{33} z + A_{34} w \\ A_{41} x + A_{42} y + A_{43} z + A_{44} w\end{pmatrix} $$

が、頂点シェーダの出力であればw除算によってこうなる。

$$ \begin{pmatrix} A_{11} & A_{12} & A_{13} & A_{14} \\ A_{21} & A_{22} & A_{23} & A_{24} \\ A_{31} & A_{32} & A_{33} & A_{34} \\ A_{41} & A_{42} & A_{43} & A_{44} \\ \end{pmatrix}\otimes \begin{pmatrix}x \\ y \\ z \\ w \end{pmatrix}= \begin{pmatrix}x'/w' \\ y'/w' \\ z'/w' \\ w'/w' \end{pmatrix}= \begin{pmatrix}(A_{11} x + A_{12} y + A_{13} z + A_{14}) / (A_{41} x + A_{42} y + A_{43} z + A_{44} w) \\ (A_{21} x + A_{22} y + A_{23} z + A_{24} w) / (A_{41} x + A_{42} y + A_{43} z + A_{44} w) \\ (A_{31} x + A_{32} y + A_{33} z + A_{34} w) / (A_{41} x + A_{42} y + A_{43} z + A_{44} w) \\ 1\end{pmatrix} $$

これを「4x4行列と4次元ベクトルをとって4次元ベクトルを生成する二項演算」として見たとき、その数学的性質はどうなのか?というのが論題だ。

記号の定義

普通の行列のかけ算を「\( \cdot \)」、w除算を伴う行列のかけ算を「\( \otimes \)」で表すとしよう。

4次元ベクトル \(x\) の4番目の成分を \(x_w\) と表すことにすると、二項演算$\otimes$は以下のように表せる。

$A\otimes x = (A\cdot x) / (A \cdot x)_w$

w除算の結合性について

$A,\ B$ を $4\times 4$ 行列、$x$ を $4$次元ベクトルとして、

$(A\cdot B) \otimes x = A \otimes (B \otimes x)$

このような等式が実は一般に成り立つことが言える。 (ゼロ除算が起きない限りにおいて)

証明

$(左辺)$

$=(A\cdot B) \otimes x$

$=(A\cdot B \cdot x) / (A\cdot B \cdot x)_w$

$(右辺)$

$=A \cdot (B\otimes x) = A\otimes ((B\cdot x) / (B\cdot x)_w)$

$=(A\cdot ((B\cdot x) / (B\cdot x)_w)) / (A\cdot ((B\cdot x) / (B\cdot x)_w))_w$

$=(A\cdot B\cdot x) / (B\cdot x)_w / ((A\cdot B\cdot x) / (B\cdot x)_w)_w$

$=(A\cdot B\cdot x) / (B\cdot x)_w / ((A\cdot B\cdot x)_w / (B\cdot x)_w)$

$=(A\cdot B\cdot x) / (A\cdot B\cdot x)_w$

一致することが確認できた。

オマケ

他にも面白い性質が成り立っていないかを考えてみる。

単位元

少々条件を付ければ、単位行列は二項演算$\otimes$においても単位元になる。

$=I\otimes x = (I\cdot x) / (I\cdot x)_w = x/x_w$

$x_w=1$ だと仮定すれば $I\otimes x = x$ が成り立つ。通常、3次元ベクトルに1を付けて拡張し4次元の同次ベクトルとするので、これは真っ当な仮定だろう。

逆元

通常の線形代数における逆行列が二項演算$\otimes$においても逆元になることが、結合法則と先ほどの単位元の考察から容易に導ける。

$A^{-1}\otimes(A\otimes x) = (A^{-1}\cdot A) \otimes x$

$=I\otimes x = x$

この性質を使うとスクリーン座標→ワールド座標という逆変換が簡単にできる。VP行列を掛けてワールド座標→スクリーン座標の変換が行われるのだから、単純にその逆行列を掛ければよい。

分配法則

これはさすがに成り立たない。

$A\otimes (x + y) = A(x+y) / (A(x+y))_w$

$=Ax/(A(x+y))_w+Ay/(A(x+y))_w$

$\neq Ax/(Ax)_w + Ay/(Ay)_w$

スカラ倍

これは値が変わらないという性質を持つ。

ベクトルをスカラ倍しても値は変わらない。

$A \otimes (cx) = Acx / (Acx)_w = Ax / (Ax)_w = A\otimes x$

行列側のスカラ倍も同様である。

$(cA) \otimes x = (cA)x / ((cA)x)_w = Ax / (Ax)_w = A\otimes x$

オマケその2

結合法則をChatGPTに証明させようとしてみたら大した計算もせずに「結合則は成り立たない」と言ってきやがった。 ネットにこういう議論が少ないのだろうか。

公開チャット履歴へのリンク

コメント