先に学んだとおり、DirectX Graphicsではポリゴンの描画しか行えない。例えばビットマップファイルなどに用意したの画像を、バック・バッファの任意の位置(座標)に転送する(書き込む)ことはできない。
ただし、画像をポリゴンに貼り付けることはできる。つまり、DirectX Graphicsにおける画像の描画とは、画像を貼り付けたポリゴンをバック・バッファに転送することにより行うのである。
DirectX Graphicsでは、ビットマップ・ファイルをビデオ・メモリ上に読み込んでから利用する。ビデオ・メモリ上に読み込まれた画像データをテクスチャと呼ぶ。また、テクスチャをポリゴンに貼り付けることをテクスチャ・マッピングと呼ぶ。
ここでは、テクスチャの作成方法やテクスチャ・マッピングを利用した描画方法について説明する。
テクスチャ・マッピングを行うには、ポリゴンの頂点の位置にテクスチャ画像のどの位置をマッピングするかを設定しなければならない。このテクスチャ画像の位置をテクスチャ座標と呼ぶ。
DirectX Graphicsでは、テクスチャ画像の左上座標を原点として、横方向をtu、縦方向をtvとし、それぞれ0.0~1.0の浮動小数点(実数)で表現する。つまり、右下座標のテクスチャ座標はtu=1.0、tv=1.0である。
例えば32×32ピクセルのポリゴンにテクスチャを貼り付けたいとき、ポリゴンの頂点A,B,C,Dそれぞれにtu、tvの値を指定することになる。
上図のように頂点A,B,C,Dそれぞれに該当するテクスチャのtu、tvの値を設定すると、次の値になる。
これにより、テクスチャ・マッピングにおいて、テクスチャサイズが縦横何ピクセルなのかを気にする必要はないことが分かる。(ただし、ポリゴンの作成時には、テクスチャのサイズに合わせてポリゴンの大きさを指定しなければならない)
テクスチャは、IDirect3DTexture8インターフェイスで表わし、テクスチャを作成するには、IDirect3DDevice8::CreateTextureメソッドを使う。このメソッドを使ってテクスチャを作成し、その後、テクスチャの画像をテクスチャのサーフェイスに書き込むことでテクスチャを使うことになる。
しかし、Direct3DXユーティリティ・ライブラリには、画像ファイルからテクスチャ画像を簡単に作ることができるライブラリがあらかじめ用意されているため、この講座ではそちらを利用してテクスチャ画像を作成することにする。
テクスチャの作成方法は次のとおり。
四角形ポリゴンを描画するプログラムに、上記修正を行う手順を解説する。前準備として、この画像ファイルをダウンロードし、WinMain.cppファイルと同じ場所に配置すること。
テクスチャ・オブジェクトをグローバル変数として次のように宣言する。
// グローバル変数
HWND hWnd; // ウィンドウハンドル
BOOL g_appActive = FALSE; // ウィンドウの状態
char szWinName[] = "Exer004"; // ウィンドウクラス用文字列
char szWinTitle[] = "DirectX Graphicsでの2D表示"; // ウィンドウクラス用文字列
LPDIRECT3D8 gl_lpD3d = NULL; // Direct3D8インターフェイス
LPDIRECT3DDEVICE8 gl_lpD3ddev = NULL; // Direct3DDevice8インターフェイス
D3DPRESENT_PARAMETERS gl_d3dpp; // ディスプレイパラメータ
LPDIRECT3DTEXTURE8 gl_Texture = NULL; // テクスチャ・オブジェクト
BYTE g_FrameNo = START_INIT; // フレーム選択用
BYTE gl_KeyTbl[256]; // キーボードの状態を格納
TLVERTX VertexDataTbl[4]; // 頂点情報配列
画像データを読み込んでテクスチャを作成する。ファイルから読み込む方法と、リソースから読み込む方法の2通りがあるがここでは、ファイルから読み込んでテクスチャを作成する方法を解説する(リソースから読み込む方法は別項で解説する)。
ウィンドウが復帰した際にテクスチャを再生することを考え、スタート画面で使用するテクスチャをまとめて作成する関数(CreateStartTexture()関数)を作成する。プロトタイプ宣言も行うこと。
この関数を、スタート画面初期化処理(StartInit()関数)から呼び出す。
//----------------------------------------------------------------------------- // 関数名 : CreateStartTexture() // 機能概要: スタート画面用テクスチャの作成・再生成 //----------------------------------------------------------------------------- void CreateStartTexture(void) { HRESULT hr; // キャラクタ1 hr = D3DXCreateTextureFromFile(gl_lpD3ddev, "sample1.bmp", &gl_Texture); if ( FAILED(hr) ) { MessageBox(hWnd, "sample1.bmp をテクスチャとして読み込めませんでした", "ERROR", MB_OK); return; } }
ファイルから画像データを読み込み、テクスチャを作成する。引数は3つ。
Direct3DXで扱うことのできる画像フォーマットは、ビットマップ形式(BMP形式)、TGA形式(α付きビットマップ)、DDS形式(DirectDrawサーフェイス形式)の3種類。これらの画像ファイルからテクスチャ用のサーフェイスを自動的に生成し、サーフェイスに画像を読み込む。
正常に読込ができると、戻り値に定数「D3D_OK」が返るので、それ以外の値ならエラーを表示する。
スタート画面初期化処理関数(StartInit()関数)から、先ほど作成したスタート画面用テクスチャ作成関数(CreateStartTexture()関数)を呼び出す。
//-----------------------------------------------------------------------------
// 関数名 : StartInit()
// 機能概要: スタート画面初期化処理
//-----------------------------------------------------------------------------
void StartInit(void)
{
//--------------------------------------------------- 各変数の初期化
// スタート画面で使用するテクスチャの作成
CreateStartTexture();
// 頂点データを格納する
InitVertex(VertexDataTbl, 100.0f, 100.0f, 400.0f, 400.0f);
//--------------------------------------------------- フレームナンバーセット
g_FrameNo = START_FRAME;
}
テクスチャの各座標を、ポリゴンのどの座標に一致させるかを設定する。
//---------------------------------------------------------------------------------------- // 関数名 : InitVertex() // 機能概要: 頂点データを格納する //---------------------------------------------------------------------------------------- void InitVertex(LPTLVERTEX v, float x1, float y1, float x2, float y2) { //頂点配列をゼロクリア ZeroMemory(v, sizeof(TLVERTX)); //---頂点A1のデータ定義 v[0].x = x1; // 頂点X座標 v[0].y = y1; // 頂点Y座標 v[0].z = 0.0f; // 頂点Z座標 v[0].rhw = 1.0f; // 2Dを扱うときの値 v[0].tu = 0.0f; // テクスチャのX座標 v[0].tv = 0.0f; // テクスチャのY座標 v[0].color = D3DCOLOR_XRGB(255,255,255); // 頂点色 //---頂点A2のデータ定義 v[1].x = x2; v[1].y = y1; v[1].z = 0.0f; v[1].rhw = 1.0f; v[1].tu = 1.0f; v[1].tv = 0.0f; v[1].color = D3DCOLOR_XRGB(255,255,255); //---頂点A3のデータ定義 v[2].x = x2; v[2].y = y2; v[2].z = 0.0f; v[2].rhw = 1.0f; v[2].tu = 1.0f; v[2].tv = 1.0f; v[2].color = D3DCOLOR_XRGB(255,255,255); //---頂点A4のデータ定義 v[3].x = x1; v[3].y = y2; v[3].z = 0.0f; v[3].rhw = 1.0f; v[3].tu = 0.0f; v[3].tv = 1.0f; v[3].color = D3DCOLOR_XRGB(255,255,255); }
頂点データにテクスチャ座標が正しく設定されていれば、テクスチャをデバイスにセットするだけで、テクスチャ・マッピングを行うことができる。よって、ポリゴンを描画する直前に、描画したいテクスチャをデバイスにセットする。
//-----------------------------------------------------------------------------
// 関数名 : StartFrame()
// 機能概要: スタート画面処理
//-----------------------------------------------------------------------------
void StartFrame(void)
{
/* 描画処理 */
// 描画するテクスチャをデバイスにセット
gl_lpD3ddev->SetTexture(0, gl_Texture);
// 四角形ポリゴンをバックバッファに転送
gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, VertexDataTbl, sizeof(TLVERTX));
// リターンキーが押されたら、ゲーム開始
if ( gl_KeyTbl[VK_RETURN] & 0x80 ) g_FrameNo = GAME_INIT;
}
作成したオブジェクトは、プログラム終了時に必ず開放しなければならない。とりあえず、DirectX8オブジェクトの開放処理関数(ReleaseD3D関数)でテクスチャ・オブジェクトを開放するように修正する。
//-----------------------------------------------------------------------------
// 関数名 : ReleaseD3D()
// 機能概要: DirectX8オブジェクトの開放
//-----------------------------------------------------------------------------
void ReleaseD3D(void)
{
// テクスチャの開放
if ( gl_Texture != NULL ) {
gl_Texture->Release();
gl_Texture = NULL;
}
// デバイスオブジェクトの開放
if ( gl_lpD3ddev != NULL ) {
gl_lpD3ddev->Release();
gl_lpD3ddev = NULL;
}
// DirectX8オブジェクトの開放
if ( gl_lpD3d != NULL ) {
gl_lpD3d->Release();
gl_lpD3d = NULL;
}
}
※動作確認
画像データをファイルからではなくリソースから読み込むためには、次のような手順でリソースに画像を格納する必要がある。
プロジェクトを作成したら、次の要領でリソースを作成する。
リソースを作成したら、プログラムを修正してリソースを呼び出すようにする。
D3DXCreateTextureFromResource(gl_lpD3ddev, NULL, "TEX01", &gl_Texture);
プログラムをビルドすると、実行可能ファイル(exeファイル)が作成される。通常は、その実行可能ファイルを別のマシンに配置し、ダブルクリックすればプログラムが実行される。これにより、作成したゲームを配布することができる。
しかし、画像データや音データなどを扱う場合は注意しなければならない。何故なら、それらのファイルをプログラム上でファイル名を直接指定して利用する場合と、リソースとして登録して利用する場合では、データの配布の仕方が違うからだ。
ファイル名を直接指定して画像などのデータファイルを呼び出す場合、配布する際には実行可能ファイルのほかに、すべてのデータファイルを用意しなければならない。しかも、ファイル名を指定する際にはファイルの場所(パス)を指定しなければならないため、その指定したパス以外の場所にデータファイルを配置してしまうと、プログラムから利用することはできない。この章で作成したプログラムの場合、ファイル名を指定する際にパスは指定していないため、配布の際には実行可能ファイルと同じ場所にデータファイルが存在しなければならない。
それに対してデータファイルをリソースで管理する場合、リソースに登録されたデータはすべてビルド時に実行可能ファイルに組み込まれる。よって、いくつデータファイルがあろうと、配布時に必要なファイルは実行可能ファイルだけであり、リソースを作成する元となった各データファイルは必要なくなる。ただし、データファイルが複数ある場合、実行可能ファイルのサイズは大きくなってしまう。
実行可能ファイルのサイズが小さければ、プログラム実行時に読み込むデータ量は少なくて済み、すばやい起動が可能である。しかし、サイズが大きければ、それだけ読み込みに時間がかかってしまう。ただし、一度メモリに読み込んでしまえば2度とハードディスクのアクセスは必要なくなるため、例えばテクスチャを作成する際、ファイルを直接指定している場合はハードディスクから一度メイン・メモリに読み込み、その後、ビデオ・メモリに読み込まれるが、リソースから読み込む場合はプログラム実行時に既にメイン・メモリに読み込まれているため、ビデオ・メモリに読み込むだけでよい。
このように、ファイルを指定する場合とリソースを使用する場合では、それぞれメリットとデメリットが存在する。自分が作りたいゲームの規模と内容に応じてCase by Caseで使い分けよう。
BACK(頂点情報初期化関数について) | NEXT(複数のキャラクタを表示する) |