今回は、DirectX の初期化を行います。
ソースは、次のものです
今回から、DirectX を使うので、それらの定義ファイルである、
#include <d3d8.h> #include <d3dx8.h>
インクルードして下さい。
なお、今回のプロジェクトでは、すでに設定済みですが、d3d8.lib、d3dx8.lib、winmm.lib を
[プロジェクト]-[設定]-[リンク]-[オブジェクト/ライブラリ モジュール(L)]に追加してください。
今回、次のものを静的変数に追加します。
static LPDIRECT3D8 s_lpD3D = NULL; static LPDIRECT3DDEVICE8 s_lpD3DDEV = NULL; static D3DPRESENT_PARAMETERS s_d3dpp;
これらは、今回使用するインターフェースのポインタ等ですが、こんな物を使うんだと思って、 使っていく中で、おいおい分かっていけばいいのではないでしょうか。
で、初期化関数です。InitD3D() にまとめました。
Winmain の CreateWindow で、ウィンドウを作成した後に呼び出します。
成功したら、ウィンドウの表示をして、メインループを回すようにします。
SUCCEEDED は HRESULT型の結果の成功、失敗を調べる関数です。
SUCCEEDED(hr) では、hr が S_OK の時に、成功と判定し、if 文は先に進みます。
HWND hWnd = CreateWindow(..............);
if(hWnd == NULL) return 0;
if(SUCCEEDED(InitD3D(hWnd))){ // ★★★★★ Direct3D の初期化
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG msg;
while (!s_end)
{
// .... メインループ処理
}
}
InitD3D() の流れは、
Direct3DCreate8 : Direct3D オブジェクトを作成 ↓ s_d3dpp を 適当なフォーマットに設定 ↓ CreateDevice : Direct3D デバイスの作成
になります。
s_d3dpp で、解像度を設定したり、Z バッファの設定をします。
今回は、CreateDevice で、T&L や シェーディングがハードウェアでできるかどうかトライしています。
実際の中身は、次のようになっています。
//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Direct3D の初期化
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
// Direct3D オブジェクトを作成
if (NULL == (s_lpD3D = Direct3DCreate8(D3D_SDK_VERSION))){
MessageBox(NULL,"Direct3D の作成に失敗しました。",CAPTION,MB_OK | MB_ICONSTOP);
return E_FAIL;
}
// 現在の画面モードを取得
D3DDISPLAYMODE d3ddm;
if( FAILED( s_lpD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) return E_FAIL;
// Direct3D 初期化パラメータの設定
ZeroMemory(&s_d3dpp, sizeof(D3DPRESENT_PARAMETERS));
s_d3dpp.BackBufferCount = 1;
if (FULLSCREEN){
s_d3dpp.Windowed = FALSE;
s_d3dpp.BackBufferWidth = WIDTH;
s_d3dpp.BackBufferHeight = HEIGHT;
}else{
s_d3dpp.Windowed = TRUE;
s_d3dpp.BackBufferWidth = 0;
s_d3dpp.BackBufferHeight = 0;
}
// ウインドウ : 現在の画面モードを使用
s_d3dpp.BackBufferFormat = d3ddm.Format;
s_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
s_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
s_d3dpp.hDeviceWindow = hWnd;
// Z バッファの自動作成
s_d3dpp.EnableAutoDepthStencil = TRUE;
s_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// デバイスの作成 - T&L HAL
if (FAILED(s_lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,&s_d3dpp,&s_lpD3DDEV))){
// 失敗したので HAL で試行
if (FAILED(s_lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&s_d3dpp,&s_lpD3DDEV))){
// 失敗したので REF で試行
if (FAILED(s_lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&s_d3dpp,&s_lpD3DDEV))){
// 結局失敗した
MessageBox(NULL,"Direct3D の初期化に失敗しました。",CAPTION,MB_OK | MB_ICONSTOP);
return E_FAIL;
}
}
}
return S_OK;
}
さらに、メインループも追加します。
DirectX の描画は、BeginScene で始まり、EndScene で終わります。
BeginScene の前に、画面(とZバッファ)をきれいにするために塗りつぶしています。
イベントが無い時は、常に描画しますが、その描画対象は、
実際のディスプレイではありません。
常に画面で描いていると描いている途中が見えるので、見えないように、
描画用と表示用のメモリをビデオカードのメモリもしくはメインメモリに用意して、
描画し終わったら、現在表示している画面といれ替えます。
次は、今まで表示していたメモリ上に画面を作っています。
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
// メッセージの処理
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
// ★★★★★ Direct3D の描画
// バックバッファと Z バッファをクリア
s_lpD3DDEV->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0);
// シーン開始
s_lpD3DDEV->BeginScene();
// ポリゴン描画などの処理
// シーン終了
s_lpD3DDEV->EndScene();
if (FAILED(s_lpD3DDEV->Present(NULL,NULL,NULL,NULL)))
s_lpD3DDEV->Reset(&s_d3dpp);// バックバッファをプライマリバッファにコピー
}
最後に、使ったメモリーを開放します。
WinMain の一番最後に追加します。
今回は、Direct3DCreate8, CreateDevice で確保した、s_lpD3DDEV、s_lpD3DD のメモリを開放します。
RELEASE(s_lpD3DDEV);
RELEASE(s_lpD3D);
RELEASE はDirectX を使っている人なら、ほとんどの人が使っているマクロで、メモリの多重開放を防止します。
DirectX 系のオブジェクトは、RELEASE (その中の Release()) で開放することは覚えて置いてください。
なお、これは main.h にあります。