5-1 Direct3D9について

ここからは音ゲーとちょっと離れ、どんなゲームにも必要な描画部分の作り方を説明します。

このサイトでは描画にDirect3Dのバージョン9を使用します。

なぜこの9を使用するかと言うと、現在Direct3Dには1~12までのバージョンがありますが、
Direct3D9までは対応OSがとても多くWin2000にも対応していたり、
テクスチャのロード関数やポリゴン描画を行う関数が用意されていたりと、
初心者にとって扱いやすいためです。

逆に10以上はこれまでのDirect3Dと考え方や作り方がまったく異なっており、
ある程度3Dの知識を知らないとポリゴンの表示すら出来なったりします。
さらに対応するOSにも制限があり最低でもVista以降が必要となるため、
要求仕様が少し高くなってしまいます。

これらのことからDirect3Dの中で簡単に扱える最後のバージョンということで、
ここではDirect3D9を使った描画方法について説明します。

ちなみに最近のグラフィックボードはDirect3D11対応などと書かれていたりしますが、
Direct3D9はこのDirect3D11を使ってエミュレートで動作しています。
このためDirect3D9は逆にそのハードウェアの機能をフルで使えない、
またエミュレートのオーバーヘッドにより処理が遅くなってしまうという問題がありますが、
実際にはDirect3D11対応のハードウェアの方がDirect3D9に対応したものより速度が桁違いに速いため、
エミュレーションだとしてもDirect3D9専用のハードウェアより高速に動作します。
このため速度をあまり求めないソフトであれば、特にグラフィックボードに合わせて
対応したDirect3Dのバージョンを使わなければならないと言った制限はありません。

なお、Direct3D10以降はOpenGLのようにシェーダーを自分で作る必要がありますが、
シェーダーに詳しければ自分でDirect3D10以降に対応したライブラリ作ることで、
このサイトで紹介している描画ライブラリと置き換えることも出来ます。

またOpenGL用の描画ライブラリを作れば、そのままiOSやAndroid向けに移植することも可能なので、
まずは資料も豊富なDirect3Dを勉強するのが一番早いと思います。


■2Dと3Dの比較

昔のスプライトと言われる描画方法とは、8x8などの小さなドット絵をキャラクターROMなどに保存しておき、
ビデオチップがこれらを重ねて表示するといったものでした。

当時はチップやメモリは高価だったため、画像枚数やサイズ、また同時に画面に表示出来る枚数などに制限があったりして、
表示的な演出を行おうとしてもあまり大したことは出来ませんでした。
※FCでよくあったチラつきはこのスプライト数の問題

また、画像を回転したり半透明にしたりといったことも出来なかったため、
始めから回転済みのドット絵を何枚も用意するなどして、擬似的に回転アニメーション行ったりしていました。
このため画像の作成だけでかなりの労力を費やしたり、画像が増える分メモリを多く使用するため、
あまり動きが多いゲームは作れませんでした。

ドットの例


これは昔作ったHEART&GUITAR R2.5のドット絵ですが、半透明を表現するため1ドットずつ空けて塗っていました。
また光るアニメーションも1枚1枚手書きでドットで作っていたため、当時はドット打ち職人がとても重宝されていたわけです。



これに対して現在の3Dによる描画では画像は特にドット絵で描く必要も無く、
フルカラーの画像を回転したり半透明にしたりといったことが簡単に出来るようになっています。
しかもこの処理は全てグラフィックボードが行うためとても高速です。

以下に2Dと3Dでの表現の違いのサンプルを用意しました。

2Dでのサンプル(Photoshop使用) 3Dでのサンプル(Photoshop使用)

何が違うかというと一目瞭然。
光っている部分で2Dの方では抜きドットの量を変えることで半透明を表現していますが、
3Dの方では1ドット単位でうまく背景と合成されています。

さらによーくキャラクターのふちを見てみると・・・

2Dでのサンプル(Photoshop使用) 3Dでのサンプル(Photoshop使用)

2Dの方では主線と背景がはっきりと分かれておりジャギ(ギザギザ)が目立ちますが、
3Dの方では主線がきれいにぼかしがかかり、きれいに背景と溶け込んでいます。


このように3Dを使えば簡単にクオリティを上げることが出来るわけですが、
昔と違いスマフォでさえ3Dが普通に動くレベルまでスペックが上がっているので、
もはやスプライトでゲームを作るというのは今どきありえません。

このため、このサイトでもこれに習って3Dを使ってゲームを作ることになるので、
以降は3Dの概要から実際にDirect3Dを使って描画を行うまでを説明していきます。

ちなみに描画の概念はOpenGLでも一緒なので、ここでの説明はそのままOpenGLでも役に立つと思われます。
※ここで説明しているDirect3DのライブラリをOpenGLに移植出来れば、ゲームのソースコードがそのまま使えます


■3Dの基礎

ここでは3Dを2Dとして利用する最低限の知識を説明したいと思います。
実は3Dについてはあんまり詳しい方では無いので、ところどころアバウトですw

まず3Dというのは2Dと違い奥行きという概念があります。
下の図を見てください。

これは2Dの描画のサンプルで、各画像を四角形の画像と見た場合に、
画面左上を(0,0)原点とした場合のその画像の左上の座標の位置をXとYで指定して描画するやり方です。

次に下の図を見てください。

これが3Dの描画のサンプルで、XとYにさらに奥行きとしてZが追加されています。

原点に対して各画像(ここでは平面ですが通常は物体となる)を任意の位置におきますが、
この空間をワールド座標と言い、ワールド座標の0,0,0を原点としてそこを基点に物体を配置しています。


さらに重要な要素としてカメラという概念があります。

カメラとは自分がどこの場所から見るのかと実際にどこを見ているのか、
さらにカメラの画角(視野の広さ)というのが必要になります。
なお、これもワールド座標上での位置として定義します。
※カメラは実は上方向という概念があり、これは実際にカメラから見た結果がスクリーン画面での上方向になる向きです。
 例えばワールド内を上下左右前後の全方向に回転するような場合は正しく計算する必要がありますが、
 一般的に上空を上とするようなゲームならば常にY軸を上とすれば問題ありません。

カメラのサンプルとして下の図を見てください。

カメラの位置と見ている位置 カメラから見た画像

水色のボックスが自分がどの位置から見ているのかを表現したもので、
黄色の四角(の中心)が実際にどこを見ているのかということになります。

3Dではカメラの位置、画角と表示方向の奥行きの範囲、物体の位置をそれぞれ指定の関数に与えてやることで、
最終的に右側のようなカメラから見た画面として描画を行ってくれます。


ちなみに2Dでは奥行きの表現(重なり順)には描画する順番が重要ですが、
3Dでは描画順は関係なく自動的にグラフィックボード側で奥行きを考えて描画してくれます。

これはZバッファと呼ばれる手法で、Zバッファとは1ピクセルごとにメモリが確保されていて、
まず今描画したピクセルのZ値(カメラからその点までの距離)を記録します。
このとき次に描くピクセルが以前書いたZ値より手前であれば描画を行い、
描画されたら同時に今回のZ値も更新しますが、もし後方だった場合はスキップされ描画は行いません。

以下は先に赤の板を描画した後に青の板を描画した場合ですが、赤の描画では赤が全て表示されますが、
そのあと青を描画すると左側は赤より手前なので描画されますが、右側は赤より奥なので描画はされません。

面が他の面と被っている場合
※赤は実際には半透明ではありません
赤を描画 青を描画

これで描画順を考えなくても勝手に判断して正しく描画してくれます。


なお、これは完全な不透明画像を表示した場合の話ですが、問題は半透明を使った画像の場合で、
描画時に奥行き判定にて奥だった場合はそもそも描画がされないため表示自体無かったことになります。
この場合はやはり必ず奥にある画像から順番に表示していく必要があるので、
半透明な物体を表示するのは結構大変です。


これで3Dの概念の説明は終わりですが、まとめると3Dとは物体の位置とカメラ位置から
最終的に画面上の位置、つまりスクリーン座標を求める
というのが醍醐味となります。
ちなみにこの位置の計算を自前でやらなければならないのがDirect3D10以上やOpenGLであり、
Direct3D9まではこれらの処理を行うための関数が用意されています。

なおこのサイトでは2D表示しか行わないため始めからスクリーン座標を指定して表示を行うので、
上記の3D描画の概念はほとんど関係ありません。
ここで紹介した内容はあくまでも参考として記憶の片隅にでも覚えて置いてください。


■右手系と左手系

3Dで何かを作る時にはこの右手系と左手系、つまり「座標系」という言葉をよく耳にします。

これは簡単に言うとZの向きが手前に来るほど大きくなるのか、奥に行くほど大きくなるのかということです。
またここではまだ詳しく説明しませんが、ポリゴン面の表と裏がそれぞれ逆転します。




このように3Dにはなぜ2種類の座標が存在するのかについてはよく分かりませんが、
3Dモデルを作るソフト(3dsMaxやMayaなど)では、この座標系が種類ごとにまちまちだったりします。
そのため始めに使うソフトにあわせて座標系を決めておく必要があります。

ちなみにDirect3Dは通常は左手系を使うようなのですが、今はどちらも使えるようで、
移植性も含めてこのサイトでは右手系で説明しています。
※OpenGLは右手系なので相性がいいはず

この座標系は次章以降のポリゴンを作る部分に少しだけ関わって来るので、
座標系という考え方が常にあるものだということだけ覚えておきましょう。

なお、2Dでもポリゴン面の表と裏が逆転してしまうと場合によっては表示がされなくなります。
Direct3Dの設定で両面表示、表だけ描画、裏だけ描画といった指定も出来るので、
描画速度が重要ならばなるべく片面だけ描画するように設定することで最適化が可能です。

それと片面だけの描画をカリングすると言いますが、
間違って覚えている人も居るみたいですがカリングは消える方を指すので、
表面だけを表示するということは裏面をカリングすると言います。