今回は頂点バッファとインデックスバッファを使って矩形の描画をしていきます。
頂点バッファとは?
頂点バッファとは頂点情報の塊のことです。
例えば前回のコードでいえばここです。
const SimpleVertex vertices[4] = { { 10.0f, 10.0f, 0.0f, 1.0f, 0xffffffff }, { 50.0f, 10.0f, 0.0f, 1.0f, 0xffffffff }, { 10.0f, 50.0f, 0.0f, 1.0f, 0xffffffff }, { 50.0f, 50.0f, 0.0f, 1.0f, 0xffffffff }, };
ただ実際に描画するにはこの情報をGPU側に転送する必要があります。
前回使用したDirectX9のDrawPrimitiveUP関数はその部分を簡略化してくれる関数です。
関数内で渡した頂点バッファの情報をGPU側から参照できるメモリにコピーして描画してくれます。
今回は何をするの?というと予めGPU側から参照できるバッファを用意して描画しようということです。
では何故コピーする方法ではダメなのかというと、一番大きな要因はコピーでは処理的に負荷が掛かってしまう事がです。
2Dの単純な矩形であれば特に問題はないですが、3Dモデルの様な頂点数が数千~数万以上あるものになると必須です。
頂点バッファの生成
DirectXにはGPUから参照するためのオブジェクトが用意されています。
先ずはそのオブジェクトを作成して先ほどの頂点バッファを書き込む関数を作っていきます。
// 頂点バッファの生成 IDirect3DVertexBuffer9* CreateVertexBuffer(const void* pVertices, size_t size) { IDirect3DVertexBuffer9* pVertexBuffer; IDirect3DDevice9* pDevice = GetDirect3DDevice(); // 指定したサイズの頂点バッファを作成 if( FAILED(pDevice->CreateVertexBuffer(size, 0, 0, D3DPOOL_MANAGED, &pVertexBuffer, NULL)) ) { return NULL; } void* pData; // バッファをロックしてデータを書き込む if( SUCCEEDED(pVertexBuffer->Lock(0, size, &pData, 0)) ) { memcpy(pData, pVertices, size); pVertexBuffer->Unlock(); } return pVertexBuffer; }
前回もそうでしたがDirectXで何かをする際は主にDirect3Dデバイスを経由して行うことになります。
今回は頂点バッファを生成する処理をデバイスから呼び出しています。
pDevice->CreateVertexBuffer(size, 0, 0, D3DPOOL_MANAGED, &pVertexBuffer, NULL);
CreateVertexBufferはそのまま頂点バッファを生成する処理です。
第一引数のsizeof(Vertex)はバッファサイズを指定しています。
第二引数の使用方法を設定しています。
CPUからの参照を許可するか?等を設定できます。
第三引数は頂点フォーマットを指定できます。
描画時にも設定できるので基本は必要ありません。
第四引数のD3DPOOL_MANAGEDはどのメモリに配置するか指定しています。
状況に応じて変えた方が実行時の効率がいいのですが、D3DPOOL_MANAGEDにしておけば管理は楽になります。
第五引数の&pVertexBufferは生成した頂点バッファの格納先を指定します。
第六引数のNULLは現在使用されていない値です。必ずNULLを指定します。
これで頂点バッファを作成する準備が整いました。
では実際に生成して描画をしてみましょう。
IDirect3DVertexBuffer9* g_pVertexBuffer; // リソースの初期化 bool InitializeResource(void) { const SimpleVertex vertices[8] = { { 10.0f, 10.0f, 0.0f, 1.0f, 0xffff7f7f }, { 50.0f, 10.0f, 0.0f, 1.0f, 0xff7fff7f }, { 10.0f, 50.0f, 0.0f, 1.0f, 0xff7f7fff }, { 50.0f, 50.0f, 0.0f, 1.0f, 0xffffffff }, }; // 頂点バッファの生成 g_pVertexBuffer = CreateVertexBuffer(vertices, sizeof(vertices)); if( g_pVertexBuffer == NULL ){ return false; } return true; } // リソースの解放 void CleanupResource(void) { SAFE_RELEASE(g_pVertexBuffer); }
これでリソースの初期化が出来ました。
前回と全く同じでは面白くないので今回は頂点カラーを少しカラフルに変えています。
合わせて解放処理も忘れないようにしましょう。
次に描画処理を前回の物から少し変えていきます。
// 使用する頂点バッファを設定 pDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(SimpleVertex)); // 描画 pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
前回、DrawPrimitiveUPを呼び出していた箇所を頂点バッファの設定とDrawPrimitiveに変更します。
描画の処理の変更はこれだけです。
それでは実行結果を見てみましょう。
無事にカラフルな矩形が表示されたはずです。
最初のうちは理解しにくい部分が多いかもしれませんが、頂点バッファの描画は以外と簡単なんです。