スケルトンプログラムへの組み込み

ここでは、実際にスケルトンプログラムにDirectX Graphicsの各処理を組み込む方法を紹介する。この授業ではまず、ウィンドウの大きさ640x480、色数16Bitのフルスクリーン・モードでDirectX Graphicsを使ってみる。

この章で使用するプログラム

スケルトンプログラムへの組み込み

スケルトンプログラムへDirectX Graphicsの各処理を組み込む方法を、順番に解説する。

1.ヘッダファイルの参照、プロトタイプ宣言、グローバル変数の追加

まずはヘッダファイル、このあと作成する予定の関数のプロトタイプ宣言、この後利用する予定のグローバル変数を次のように追加する。

#include <stdio.h>
#include <windows.h>    // WindowsAPIを使用可能にする
#include <windowsx.h>
#include <d3d8.h>       // DirectX8ヘッダファイル
#include <d3dx8.h>      // D3DXヘッダファイル

// マクロ
#define WINMODE TRUE // ウィンドウモードの指定(TRUE:ウィンドウモード/FALSE:フルスクリーン)
#define SCREEN_WIDTH	640	// ウィンドウの幅
#define SCREEN_HEIGHT	480	// ウィンドウの高さ

// プロトタイプ宣言
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);   // Windows関数
BOOL InitApp(HINSTANCE, int);                           // ユーザー関数
HRESULT InitDX8(void);                                  // DirectX8初期化処理
void ReleaseD3D(void);                                  // DirectX8開放処理

// グローバル変数
HWND hWnd;                              // ウィンドウハンドル
char szWinName[] = "Exer002";      // ウィンドウクラス用文字列
char szWinTitle[] = "スケルトンプログラムにDirectX Graphicsを追加する"; // ウィンドウクラス用文字列
LPDIRECT3D8 gl_lpD3d = NULL;            // Direct3D8インターフェイス
LPDIRECT3DDEVICE8 gl_lpD3ddev = NULL;   // Direct3DDevice8インターフェイス
D3DPRESENT_PARAMETERS gl_d3dpp;         // ディスプレイパラメータ

《解説》

1.ヘッダファイルの参照
DirectX8を使用するためには d3d8.hd3dx8.hのヘッダファイルをインクルードしなければならない。
2.プロトタイプ宣言
C言語の授業で学んだように、プログラムで使用する関数は事前にプロトタイプ宣言しなければならない。今回、DirectX8を利用するためにInitDX8関数、ReleaseDX8関数を宣言した。
InitDX8関数の戻り値のデータ型として指定した HRESULT型 は、処理が成功すると定数「S_OK」を失敗すると定数「E_FAIL」を返す。
3.グローバル変数
・関数の外で宣言した変数をグローバル変数(外部変数)と呼び、この変数より下に宣言した関数内で共通に使うことができる。
・gl_lpD3dとgl_lpD3ddevはオブジェクトであり、宣言時に定数「NULL」を代入する。
・これらすべてはプログラマがつけた名前なので、好きな名前でよい。
・LPDIRECT3D8クラス、LPDIRECT3DDEVICE8クラスはDirectX8であらかじめ用意されている(d3d8.h内)。

2.DirectX Graphics初期化用関数の追加

DirectX Graphicsの初期化を行う関数 InitDX8を作成する。以下のプログラムを、プロトタイプ宣言の順番のとおりにInitApp関数の下に作成する。

//-----------------------------------------------------------------------------
// 関数名 : InitDX8() 
// 機能概要: Direct Draw オブジェクトの生成
// 戻り値 : 正常終了のとき:DD_OK、異常終了のとき:エラーコード
//-----------------------------------------------------------------------------
HRESULT InitDX8(void)
{
    D3DDISPLAYMODE  DispMode;	// ディスプレイモード
    HRESULT         hr;

    /* DirectX8オブジェクトの生成 */
    gl_lpD3d = Direct3DCreate8(D3D_SDK_VERSION);
    if( !gl_lpD3d ) {      // オブジェクト生成失敗
	    MessageBox(hWnd, "DirectXD3D8オブジェクト生成失敗", "ERROR", MB_OK);
        return E_FAIL; 
    }

    /* DirectX8のプレゼンテーションパラメータを設定 */

    // ディスプレイデータ格納構造体初期化
    ZeroMemory(&gl_d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    // 現在のディスプレイモードデータ取得
    gl_lpD3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DispMode);
    // バックバッファフォーマットをディスプレイと等価に
    gl_d3dpp.BackBufferFormat       = DispMode.Format;
    // 横ドット幅設定
    gl_d3dpp.BackBufferWidth        = SCREEN_WIDTH;
    // 縦ドット幅設定
    gl_d3dpp.BackBufferHeight       = SCREEN_HEIGHT;
    // バックバッファの数
    gl_d3dpp.BackBufferCount        = 1;
    // フリップの方法(通常はこの定数でよい)
    gl_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
    //
    gl_d3dpp.EnableAutoDepthStencil = TRUE;
    // ステンシルフォーマット
    gl_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    // ウインドウモードの設定
    gl_d3dpp.Windowed               = WINMODE;

    /* デバイスオブジェクトの生成 */

    //高性能なハードウェアデバイスの生成を試みる
    hr = gl_lpD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
        D3DCREATE_HARDWARE_VERTEXPROCESSING, &gl_d3dpp, &gl_lpD3ddev);
    if ( FAILED(hr) ) {
        //ハードウェアデバイスの生成を試みる
        hr = gl_lpD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &gl_d3dpp, &gl_lpD3ddev);
        if ( FAILED(hr) ) {
            //ソフトウェアデバイスの生成を試みる
            hr = gl_lpD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &gl_d3dpp, &gl_lpD3ddev);
            if ( FAILED(hr) ) {
                //--どのデバイスも取得できなかった
			    MessageBox(hWnd, "DirectXデバイス生成失敗", "ERROR", MB_OK);
                return E_FAIL; 
            }
        }
    }

    return S_OK;
}

《解説》

1.Direct3D8インターフェイス生成
・DirectX Graphicsのすべての元となるDirect3D8インターフェイスを生成する。
・何らかの事情により生成できなかったときはエラーメッセージを表示し、エラーコードを返す(InitDX8関数を抜ける)。
2.Direct3D8のプレゼンテーションパラメータを設定
・現在表示中の解像度、色数を取得し、それを元にDirectX8のプレゼンテーションパラメータを設定する。
・プレゼンテーションパラメータは解像度、色数の設定、バックバファの数、表示モードなどである。
・表示モード(d3dpp.Windowed)に「WINMODE」を指定している。これはInitApp関数においてウィンドウを生成する際、ウィンドウ・モード用のウィンドウを生成するか、フルスクリーン・モード用のウィンドウを生成するかを指定するためにマクロで宣言したパラメータである。WINMODEの値が「TRUE」であればウィンドウ・モード、「FALSE」であればフルスクリーン・モードになる。
3.デバイスオブジェクト生成
・使用できるデバイスは動作させる環境により異なる。
・実行する環境ごとに、できるだけ高性能なデバイスを使用したいので高性能なデバイスから生成できるか調べる。チェックは次の順で行う。
  1、高性能なハードウェアデバイス
  2、普通のハードウェアデバイス
  3、ソフトウェアデバイス
 いずれデバイスも生成できなかったときはエラーメッセージを表示し、エラーコードを返す(InitDX8関数を抜ける)。

3.DirectXオブジェクト開放処理の追加

作成したすべてのオブジェクトは、アプリケーション終了時にすべて開放しなければならない。以下のプログラムを、プロトタイプ宣言の順番どおり、InitDX8関数の下に追加する。

//-----------------------------------------------------------------------------
// 関数名 : ReleaseD3D()
// 機能概要: DirectX8オブジェクトの開放
//-----------------------------------------------------------------------------
void ReleaseD3D(void)
{
    //デバイスオブジェクトの開放
    if ( gl_lpD3ddev != NULL ) {
        gl_lpD3ddev->Release();
        gl_lpD3ddev = NULL;
    }
    //DirectX8オブジェクトの開放
    if ( gl_lpD3d != NULL ) {
        gl_lpD3d->Release();
        gl_lpD3d = NULL;
    }
}

《解説》

  1. Direct3D8オブジェクトを開放する。
  2. Direct3D8オブジェクトが増えた場合、この関数に必ず開放処理を追加する。

4.WinMain関数の修正

アプリケーション実行時にDirectX Graphicsの初期化処理を行い、終了時にオブジェクトを開放するよう、WinMain関数を次のように修正する。

//-------------------------------------------------------------------------------------------------
//      メイン関数(エントリーポイント)プログラムはここから始まる
//-------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
    MSG msg;		// メッセージ構造体変数
    HRESULT hr;

    //表示するウィンドウの定義、登録、表示
    if (!InitApp(hThisInst, nWinMode)) return (FALSE);

    // DirectX8の初期化
    hr = InitDX8();
    if ( FAILED(hr) ) return (FALSE);

    // メッセージループ
    // Windowsは「WM_QUIT」メッセージを受けると偽(0)を戻す
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg); // メッセージの解析
        DispatchMessage(&msg);  // メッセージの破棄
    }

    // DirectX8オブジェクトの削除
    ReleaseD3D();

    return msg.wParam;
}

《解説》

  1. ウィンドウを生成したら、DirectX Graphicsの初期化を行う(InitDX8関数を実行)。
  2. アプリケーションが終了(メッセージ・ループを抜ける)したら、Direct3D8オブジェクトを開放する(ReleaseD3D関数を実行)。

※この時点でビルドしてもエラーになるので注意!!


BACK(DirectX Graphicsプログラミングの基礎) NEXT(ビルドの準備)