DirectX Graphicsは2Dのみのモードはなく、すべて3Dで表現される。しかし、3Dの機能を使って2Dの描画を行うことは可能である。この授業では、DirectX Graphicsを使ってシンプルな2Dゲームを製作することを目的としている。ここでは、DirectX Graphicsを使った2Dアプリケーションの作り方を、DirectX Graphicsの初期化から、描画までを順を追って説明する。
DirectX Graphicsアプリケーションは、通常のWin32アプリケーションを作るのと同じように作成する。
DirectXはアプリケーションのクライアント・ウィンドウに描画を行う。アプリケーションでは通常のWin32アプリケーションと同じようにメッセージを処理していく。
DirectX Graphicsには、次の2種類が存在する。
DirectX Graphicsを使ったアプリケーションの処理は、だいたい次のような流れになる。
DirectX Graphicsを初期化する方法を解説する。実際にスケルトンプログラムに組み込むには、エラーチェックなどを行わなければならないが、ここでは初期化処理に必要なもののみを解説する(実際の組み込みは次ページで行う)。
DirectX Graphicsを使うには「d3d8.h」をインクルードする。以前のバージョンで使っていた「d3d.h」を使用するとDirectX7以前のバージョンの機能しか使用できない。
また、Direct3DXの機能を使うときは「d3dx8.h」をインクルードする。
これらは次のような感じで「windows.h」をインクルードした後に記述する。
#include <windows.h>
#include <windowsx.h>
DirectX Graphicsアプリケーションでは、まず最初にIDirect3D8インターフェイスを取得する必要がある。IDirect3D8インターフェイスを利用して、他のデバイスを作成したりデバイスの能力や種類などを調べる。
IDirect3D8インターフェイスを取得するには、Direct3DCreate8関数を使用する。IDirect3D8インターフェイスのポインタはPLDIRECT3D8で表わされ、これを得るには次のように記述する。
LPDIRECT3D8 pD3D;
pD3D = Direct3DCreate8(D3D_SDK_VERSION);
Direct3DCreate8関数の引数は、常に「D3D_SDK_VERSION」を指定する。インターフェイスの取得に成功すると、Direct3DCreate8関数はインターフェイスのポインタを返し、失敗すると「NULL」を返す。
IDirect3D8インターフェイスの取得に成功したら、描画や表示を行うためのデバイスを作成する。
デバイスを作成するとき、使用するグラフィック・アダプタを選び、どのように動作させるかを指定する。また、画面の解像度や色数(ピクセル・フォーマット)なども選択してデバイスを作成する。
DirectX7までは、DirectDrawを使って画面の設定などをしてからデバイスを作成していたが、DirectX8からは、デバイスを作成することで画面などの設定が行われるようになっており、初期化の処理がずいぶん楽になった。
デバイスを作成するには、IDirect3D8::CreateDeviceメソッドを使用する。以下に、ウィンドウモード・アプリケーションの場合のデバイスの作成と、フルスクリーン・アプリケーションの場合のデバイスの作成方法を記述する。
D3DDISPLAYMODE dmode;
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DDEVICE8 pD3DDevice;
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dmode);
ZeroMemory(&d3dppApp, sizeof(d3dpp));
d3dpp.Windowed = TRUE; // ウィンドウ・モード
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCADE;
d3dpp.BackBufferFormat = dmode.Format; // デスクトップのフォーマットを使用
d3dpp.BackBufferCount = 1; // ダブルバッファリングを行う
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // 16Bit Zバッファ作成
pD3D->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd, // アプリケーションのウィンドウ・ハンドル
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&pD3DDevice
);
D3DDISPLAYMODE dmode;
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DDEVICE8 pD3DDevice;
ZeroMemory(&d3dppApp, sizeof(d3dpp));
d3dpp.BackBufferWidth = 640; // 640x480
d3dpp.BackBufferHeight = 480;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; // 32Bit Color
d3dpp.Windowed = FALSE; // フルスクリーン・モード
d3dpp.BackBufferCount = 1; // ダブルバッファリングを行う
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCADE;
d3dpp.FullScreen_refreshRateInHz = 75; // リフレッシュ・レート
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // 16Bit Zバッファ作成
pD3D->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd, // アプリケーションのウィンドウ・ハンドル
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&pD3DDevice
);
これらの例から分かるように、デバイスを作成するには、D3DPRESENT_PARAMETER構造体に「解像度」「ダブル・バッファリングやZバッファの有無とフォーマット」などのようなデバイスの設定をして、CreateDeviceメソッドを呼び出す。また、CreateDeviceメソッドでは他に「使用するグラフィック・アダプタ」「デバイスの種類」(ハードウェアによるサポートの有無、リファレンス・ドライバを使用するかなど)を指定する。
なお、IDirect3DDeviceインターフェイスのポインタは、LPDIRECT3DDEVICE8として定義されている。
CreateDeviceメソッドは、デバイスの作成に成功すると、D3D_OKを返す。
デバイスを作成できたら、画像を画面に表示できるようになる。DirectX GraphicsではIDirect3DDevice8インターフェイスを通じて、デバイスに描画属性などを設定したり描画したりできる。
DirectX Graphicsで描画を開始するには、IDirect3DDevice8::BeginSceneメソッドを呼び出す。描画を終了するときには、IDirect3DDevice8::EndSceneメソッドを呼び出す。BeginSceneとEndSceneで囲まれた間で描画を行う。
通常、描画中の状態を隠すためやちらつきを抑えるためにダブル・バッファリングを行う。この場合、描画はすべてバック・バッファに行われる
バック・バッファはそのままでは見えないので、画面に表示してやる必要がある。これを行うには、IDirect3DDevice8::Presentメソッドを使う。DirectX7までは、フルスクリーン・モードではサーフェイスのフリップを、ウィンドウ・モードではバック・バッファからプライマリ・サーフェイスへコピーすることが必要だったが、DirectX8ではPresentメソッドがこの処理を行うようになった。
pD3DDevice->BeginScene();
//
// ここに描画などの処理を入れる
//
pD3DDevice->EndScene();
pD3DDevice->Present(NULL, NULL, NULL, NULL);
通常、描画を行う前に画面の消去(クリア)を行う。画面の消去とは、画面をある色で塗りつぶすことで、実際にはダブル・バッファリングをしているような場合はバック・バッファの消去になる。
画面の消去を行うには、IDirect3DDevice8::Clearメソッドを使う。Clearメソッドは画面だけでなく、Zバッファやステンシル・バッファを消去(初期化)するのにも使う。
例えば、画面を青く塗りつぶすには、次のように記述する。
pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ZRGB(0,0,255), 0.0, 0);
アプリケーションでは、途中で画面のサイズを変更することがあります。
ウィンドウ・モードではユーザがウィンドウの枠をドラッグするとサイズが変わり、フルスクリーン・モードで解像度を変えたり、ウィンドウ・モードに戻したりということが考えられる。
ウィンドウ・モードのときは、最初にデバイスを作成したときにウィンドウのクライアント領域の大きさに合わせてバック・バッファが作られる。そのため、ウィンドウ・サイズが変更になると、バック・バッファと画面(クライアント領域)の大きさが異なり、Presentメソッドによってバック・バッファを表示すると、拡大または縮小の処理が発生してしまう。
また、フルスクリーン・モードでは解像度を変えたり、ウィンドウ・モードに戻したり(逆の場合も)するときに不都合が起こる。
このような場合、一からデバイスを作り直して初期化の処理をやり直してもいいが、デバイス以外にテクスチャやモデルのデータなども作り直さなければならなくなってしまう。
そこで、IDirect3DDevice8::Resetメソッドを使って、デバイスの設定を変更する。
Resetメソッドは、引数にD3DPRESENT_PARAMETERS構造体のポインタを取る。IDirect3D::CreateDeviceメソッドで設定した要領でこの構造体にデバイスの新しい設定を記述し、Resetメソッドを呼び出すことで、新しい設定に変更できる。
このとき、テクスチャやバック・バッファ、Zバッファなどのサーフェイスや、デバイスから作成されたりソースなどは開放され、新しい設定で作り直される。
アプリケーションを終了する前に、取得したIDirect3DDevice8やIDirect3D8インターフェイスなどをReleaseメソッドを使ってすべて開放する。
Releaseメソッドによってインターフェイスの実態の参照カウンタが1つ減る。これはインターフェイスを取得したときにカウンタが+1されており、Releaseメソッドによってカウンタが0になると実体は開放される。アプリケーションを終了する際には、取得した分だけきっちりReleaseしなければならない。
| BACK(ウィンドウモードを切り替える) | NEXT(スケルトンプログラムへの組み込み) |