DirectXでストアアプリを作成する方法の紹介の第二回です。
前回はプログラムの構造というか基礎の部分を紹介しましたが、実際の描画処理の中身については触れませんでした。
以下のように、CubeRendererクラスのUpdate(更新)とRender(描画)をWhileループで繰り返して描画していくという部分の紹介で終わりました。
while (!m_windowClosed) { if (m_windowVisible) { timer->Update(); CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); m_renderer->Update(timer->Total, timer->Delta); m_renderer->Render(); m_renderer->Present(); // この呼び出しは、表示フレーム レートに同期されます。 } else { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); } }
上記の変数m_rendererはCubeRenderer型です。
それでは描画の実装CubeRenderer(ファイルはCubeRenderer.cpp)を触って立方体の描画を三角形の描画に変えてみましょう。
(今回は描画の変更方法に絞って解説します)
CreateDeviceResourcesメソッド内で初期化を行います。
この中で立方体(Cube)の設定を行い、Updateメソッドで回転を指定。Renderメソッドで描画という流れになります。
立方体の頂点を指定している部分は以下、
VertexPositionColor cubeVertices[] = { {XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f)}, {XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f)}, {XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f)}, {XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f)}, {XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f)}, {XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f)}, {XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f)}, {XMFLOAT3( 0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, };
それぞれ一行が頂点の一つ一つの座標と色情報を表しています。
立方体なので頂点の数は8つです。
各行にはXMFLOAT3が2つ記載されており、最初が頂点の座標をあらわすX、Y、Z軸、2つめが色を表すRGB情報です。
試しに2つめのXMFLOAT3をすべて XMFLOAT3(1.0f, 1.0f, 1.0f)に変更すると真っ白な立方体が描画されます。
VertexPositionColor cubeVertices[] = { {XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3( 0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, };
今回はこれを以下のように書き換えます。
VertexPositionColor cubeVertices[] = { {XMFLOAT3(0.5f, 0.0f, 0.0f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3(0.0f, 0.0f, 0.0f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, {XMFLOAT3(0.0f, 0.5f, 0.0f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, };
三角形を描きたいので頂点は3つです。Cubeという変数名とはそぐわない内容になってしまいましたが、今回はこのまま行きましょう。
色はすべての頂点を白にしましたが、いろいろ書き換えてみてください。
続いて、インデックス情報も書き換えます(インデックスを書き換えないでも三角形は描画されるのですが、何か違います。気になった方は試してみましょう)。
インデックスの指定はデフォルトだと以下のようになっています。
unsigned short cubeIndices[] = { 0,2,1, // -x 1,2,3, 4,5,6, // +x 5,7,6, 0,1,5, // -y 0,5,4, 2,6,7, // +y 2,7,3, 0,4,6, // -z 0,6,2, 1,3,7, // +z 1,7,5, };
これを以下のように書き換えます。
unsigned short cubeIndices[] = { 0,1,2 };
この状態で実行すると三角形が回転されるのですが、なぜか右半分を回転しているときしか描画されません。
これは三角形の表側だけを描画しており、裏側は描画していないためです。
ちょっと踏み込んで三角形の反対側も表示してみましょう。
裏側の描画を行うか行わないか指定することをカリングといいます。
CreateDeviceResourcesメソッドの最後の行に以下の記述を追記します。
D3D11_RASTERIZER_DESC rdc; ZeroMemory(&rdc, sizeof(rdc)); rdc.FillMode = D3D11_FILL_SOLID; rdc.CullMode = D3D11_CULL_FRONT; rdc.FrontCounterClockwise = true; // 表側の設定はCULL_FRONT m_d3dDevice->CreateRasterizerState(&rdc, &m_pRasterizerState); // 裏側の設定はCULL_BACK rdc.CullMode = D3D11_CULL_BACK; m_d3dDevice->CreateRasterizerState(&rdc, &m_pRasterizerStateBack);
m_pRasterizerStateという変数がこのままでは存在しないのでCubeRenderer.hに以下のように記述します。
ID3D11RasterizerState* m_pRasterizerState; ID3D11RasterizerState* m_pRasterizerStateBack;
記述位置はprivate変数の宣言のあたりです(サンプルコード参照)。
最後に描画処理のRenderメソッドに手を加えます。
メソッドの最後、
m_d3dContext->DrawIndexed( m_indexCount, 0, 0 );
を以下のように書き換えます。
m_d3dContext->RSSetState(m_pRasterizerState); m_d3dContext->DrawIndexed( m_indexCount, 0, 0 ); m_d3dContext->RSSetState(m_pRasterizerStateBack); m_d3dContext->DrawIndexed( m_indexCount, 0, 0 );
これで回転する三角形が描画できました。
DirectXのお約束というかD3D11_FILL_SOLIDのような指定が多くて慣れないせいか疲れますね。
ほかにもいろいろ説明すべき処理があるのですが、今回は描画を変える部分のみを解説しました。
今回のサンプルはGitHubで公開しています。
次回はCubeRenderクラスのその他処理を紹介しようと思います。
Please give us your valuable comment