icon前回の記事では簡単な2D表示について取り扱った。今回は3D表示について取り扱う。3D表示とは言っても、2Dのときと大きく変わることはない。WebGLはそもそも3Dグラフィックス用のAPIなのだ。よってせいぜいシェーダを少し書き換えて、ちょっとした行列操作が加わる程度の違いになる。プログラムが横書きである以上、縦に並べることができないので、横書きにしているだけである。よって、数学の教科書に載っている座標変換行列の例と全く同じように考えればよい。Coordinate)WebGLで使用する座標はxyzwの4次元ベクトルである。後述する平行移動を行列の積であらわそうとすると、どうしても1次元増やす必要があるのだ。wは単なるダミーなのかというと、必ずしもそうではない。WebGLでは最終的にxyzの値をwで割ることにしている。z/w)ということになる。Coordinate)と呼ばれている。同次座標は、w=1なら単なる3次元ベクトルと同じようにみなすことができる。w≠1のときについては、wの値は、主に遠近感を表現するのに使用される。遠くの頂点に大きなwを設定することで、「遠くの物ほど小さく見える」という現象を再現することができるのだ。行優先(Row-major)と列優先(Column-major)数学には存在しないプログラミング特有の問題として、行列を行優先・列優先のどちらで表現するのか、というものがある。プログラム上では、行列は2次元配列ではなく1次元の配列として表す。DartではFloat32Listを使用する。行列を1次元配列に落とし込むとき、1行目、2行目、と行ごとに並べていくのか、あるいは1列目、2列目、と列ごとに並べていくかということが問題になる。このとき1行目、2行目...と並べていく方式を行優先、1列目、2列目...と並べていく方式を列優先と呼ぶ。以下のような行列Aを考える。WebGLでは行列の表現に列優先を用いる。3D描画のための座標変換3Dグラフィックスを画面に表示するには、ちょっとした決まり事がある。どんなデータを用意してどう使うかはユーザの自由ではあるが、最終的には一定のルールに従ったデータに変換する必要がある。NDC)WebGLでは、座標を正規化デバイス座標と呼ばれる座標に収める必要がある。正規化デバイス座標はそれぞれの軸が-1.0から1.0までの値を取る座標だ。正規化デバイス座標は左手座標系(Z軸のプラス方向が奥)を採用している。正規化デバイス座標(NDC)これが、たったひとつの決まり事である。最終的に正規化デバイス座標にさえ収まっていれば、何をしてもかまわない。現実問題として、正規化デバイス座標をそのまま扱うのは困難だ。よって、独自の扱いやすい座標に変換行列を掛け合わせて、正規化デバイス座標へ落とし込むのが一般的な手法になる。前回の記事で、WebGLでは主に右手座標系を用いると述べたが、最終出力である正規化デバイス座標とは逆の座標系を選択していることになる。Z軸を反転させなければならず、少し不自然だ。これに対する理由としては「そういう慣習だから」と答えるほかない。参考書やライブラリの多くが右手座標系をデフォルトとしているので、従っておくのが楽でいいだろう。左右両方に対応しているライブラリや、左手座標系をデフォルトとするフレームワークも存在するので、そのときどきの環境に合わせた選択をしよう。一般に、3Dモデルはそれぞれ自分中心のオブジェクト座標を持っている。モデリングソフトなどでも、3Dモデルはオブジェクト座標を基準に作成する。モデルはオブジェクト座標に配置されるモデルがひとつだけなら何も問題は起こらない。複数のモデルを同じ空間に配置する場合はどうだろうか。オブジェクト座標は自分自身のことしか考慮しておらず、モデルが複数になると同じ場所に重なり合ってしまい、破綻する。よって複数のモデルを配置するときは、それぞれのモデルのオブジェクト座標を「世界」の空間、ワールド座標に配置する必要がある。これを実現する変換行列は、モデル変換行列と呼ばれている。3つから構成されている。拡大縮小・回転でサイズや角度を決めて、平行移動でワールド空間座標へ配置するという手順が一般的だ。平行移動(Translation)3Dグラフィックスでは、平行移動も掛け算として表すのが一般的だ。平行移動量をそれぞれTx、Ty、Tzとしたときの平行移動行列は、となる。妙なことをしていなければこの時点でのwの値は1になるので、これで本当に平行移動になるのか理解できないときは、手計算してみるといい。プログラム上での表記は列優先になることには注意したい。以下にDartで記述した例を記しておく。拡大縮小行列は、となる。Sz倍しているだけだ。回転行列(Rotation)これは少しややこしい。Z軸周りの回転について考えてみよう。点Pを原点周りにθラジアン回転し、点P’へうつす変換を考える。rsinθ)と表すことができる。rsin(α+θ))と表せる。