3D機能で2D描画をする話

DirectX9には2D描画機能が無い。描画はすべて3Dだ。
一応D3DXSpriteが用意されていて、これは内部で3D処理をやっているが、インターフェイスは2D描画として扱える。でもちょっと遅い。もっと高速な2D描画が必要なら、3D機能を使って2D描画することになる。


3D機能で2Dを描画するためのポイントは、座標変換とテクスチャだろう。
座標変換については頂点座標にRHWを追加すれば、3D座標変換処理をすっ飛ばしてスクリーン座標として扱ってくれる。
RHWは同次座標で、3Dでは射影変換で真ん中に寄せるためにZ座標が入るが、この値を直接指定することで変換は終わった、と言うことをDirect3Dに教える。のだと思う。
射影変換後にクリッピング→ビューポート変換となるが、このへんもすっ飛ばすということはクリッピングもされないということで、おそらくこの場合にはラスタライザのあたりで画面外ピクセルを除外しているのだろう。
DXRuby1.1では2D画像も3D空間に描画できるため、RHWは使わずに真面目に座標変換して3D描画している。


テクスチャのほうはちょっと事情が複雑だ。とりあえずマイクロソフトのサイトに丁寧な解説がある。
http://msdn.microsoft.com/ja-jp/library/bb219690(VS.85).aspx
一度読んで理解できるよーな人はさくさくゲームを作ってください。
まあ、ここに書いてあるのは要するにピクセルとテクセルの話だ。
画面にあるピクセルは整数の座標で表される点の集合であり、DirectXのテクスチャは0.0〜1.0で表される画像情報だ。
ピクセルは整数であるため、浮動小数点化しても例えば(0, 0)の座標を表す数字は(0.0, 0.0)にしかならない。隣のピクセルは(1.0, 0.0)だ。ピクセルの中間点は(0.5, 0.0)となる。つまり、左上のピクセルとして表現できる範囲は(-0.5, -0.5)から(0.5, 0.5)となる。
対してテクセルは画像全体の左上が(0.0, 0.0)となり、右上が(1.0, 0.0)となる。例えば2*2のテクスチャ画像とすると、左上の色の中心は(0.25, 0.25)で、右上の色の中心は(0.75, 0.25)だ。
右下の点の色を求める場合、テクスチャ座標の求め方は位置÷テクスチャの幅だから、1/2で0.5となるが、(0.5, 0.5)を取得すると4つの色が均等に合成された真ん中の色、ということになってしまう。
このズレはピクセルとテクセルの座標のズレであって、点の範囲の表現方法が0.5だけズレているためだ。
従って、テクセル座標を計算する場合に位置に0.5足すか、描画する座標を指定するときに0.5引く必要がある。


D3DXSpriteはそのへんの補正もしてくれるみたいだから、よくわからない人で極限まで速度を出したいわけではないなら、それを使うのがやっぱり簡単でよい。
ただ、回転やスケーリングをする場合は行列で指定することになるから、そのあたりの勉強はしたほうがよい。でも初期のDXRubyはD3DXSpriteを使って回転とかしてたが、行列なんて全くわかってなかったので、わからなくても試行錯誤とコピペでなんとかなる。


まあ、3D機能を使って自分で2D描画しようとすると、3Dの仕組みを理解しないといけなくてとても大変だ。
なんとも初心者に優しくない時代になったもんだ、と思う。