ポリゴン描画(三角形)

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

最も簡単なポリゴン

DirectX Graphicsでの最も少ない頂点情報で表現されるポリゴンは三角形であり、3個の頂点情報だけで描画できる。DirectX Graphicsにおけるポリゴンの最小単位は三角形となっている。

ポリゴンの頂点座標は(x、y、z)で表わされる。3つの頂点座標を用意し、それぞれの頂点を線で結べば三角形ができる。作成された三角形は次のような特徴を持つ。

つまり、3つの頂点の奥行きをすべて同じ値にすれば、2Dの画像になることが分かる。

三角形ポリゴンを表示してみる

では実際に三角形ポリゴンをウィンドウに表示する方法を解説する。手順は次のとおり。

  1. 頂点座標を格納する変数(配列)を宣言・・・三角形なので要素数は3
  2. 頂点座標をセット
  3. ポリゴンを描画

4章1で作成したプログラム(このページの上からもダウンロードできる)を上記手順どおりに編集し、三角形ポリゴンを表示してみる。

1.頂点座標を格納する変数(配列)を宣言

頂点座標を扱うために必要なものを準備する。

// マクロ
#define WINMODE FALSE // ウィンドウモードの指定(TRUE:ウィンドウモード/FALSE:フルスクリーン)
#define SCREEN_WIDTH	640	// ウィンドウの幅
#define SCREEN_HEIGHT	480	// ウィンドウの高さ
/* ゲームの状態を識別する(フレーム番号) */
#define START_INIT     0
#define START_FRAME    1
#define GAME_INIT      10
#define GAME_FRAME     11
/* 頂点フォーマット(基本形)*/
#define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)

// 構造体の宣言
/* 頂点構造体 */
typedef struct _TLVERTEX {
    float           x, y, z;                //位置情報
    float           rhw;                    //頂点変換値
    D3DCOLOR        color;                  //頂点カラー
    float           tu, tv;                 //テクスチャ座標
} TLVERTX, *LPTLVERTEX;

// プロトタイプ宣言
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);   // Windows関数
BOOL InitApp(HINSTANCE, int);                           // ユーザー関数
HRESULT InitDX8(void);                                  // DirectX8初期化処理
void ReleaseD3D(void);                                  // DirectX8開放処理
void ResetWindow(void);                                 // ウィンドウ再生成処理
BOOL UpdateFrame(void);                                 // ゲームメイン処理
void StartInit(void);                                   // スタート画面初期化処理
void StartFrame(void);                                  // スタート画面処理

// グローバル変数
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;         // ディスプレイパラメータ
BYTE g_FrameNo = START_INIT;            // フレーム選択用
BYTE gl_KeyTbl[256];                    // キーボードの状態を格納
TLVERTX VertexDataTbl[3];               // 頂点情報配列

《解説:マクロの宣言》

《解説:構造体の宣言》

《解説:頂点情報配列の宣言》

2.頂点座標をセット

1で作成した構造体の型を持つ構造体変数(要素数3の配列)を宣言し、頂点座標をセットする。今後の使い勝手を考え、頂点座標セット用の関数を作成した。

// プロトタイプ宣言
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);   // Windows関数
BOOL InitApp(HINSTANCE, int);                           // ユーザー関数
HRESULT InitDX8(void);                                  // DirectX8初期化処理
void ReleaseD3D(void);                                  // DirectX8開放処理
void ResetWindow(void);                                 // ウィンドウ再生成処理
BOOL UpdateFrame(void);                                 // ゲームメイン処理
void StartInit(void);                                   // スタート画面初期化処理
void StartFrame(void);                                  // スタート画面処理
void InitVertex(LPTLVERTEX);                            // 頂点情報格納
・
・
・
//----------------------------------------------------------------------------------------
// 関数名 : InitVertex() 
// 機能概要: 頂点データを格納する
//----------------------------------------------------------------------------------------
void InitVertex(LPTLVERTEX v)
{
    //頂点配列をゼロクリア
    ZeroMemory(v, sizeof(TLVERTX));
    //---頂点A1のデータ定義
    v[0].x      =  100.0f;                     // 頂点X座標
    v[0].y      =  100.0f;                     // 頂点Y座標
    v[0].z      =  0.0f;                       // 頂点Z座標
    v[0].rhw    =  1.0f;                       // 2Dを扱うときの値
    v[0].color  =  D3DCOLOR_XRGB(0,0,255);     // 頂点色
    //---頂点A2のデータ定義
    v[1].x      =  200.0f;
    v[1].y      =  200.0f;
    v[1].z      =  0.0f;
    v[1].rhw    =  1.0f;
    v[1].color  =  D3DCOLOR_XRGB(0,0,255);
    //---頂点A3のデータ定義
    v[2].x      =  0.0f;
    v[2].y      =  200.0f;
    v[2].z      =  0.0f;
    v[2].rhw    =  1.0f;
    v[2].color  =  D3DCOLOR_XRGB(0,0,255);
}

《解説》

3.ポリゴンを描画

セットした頂点情報を持つポリゴンを描画する。現在のプログラムにはスタート処理しかないため、スタート画面初期化処理で頂点座標をセットし、スタート画面処理でポリゴンを描画する。

//-----------------------------------------------------------------------------
// 関数名 : StartInit()
// 機能概要: スタート画面初期化処理
//-----------------------------------------------------------------------------
void StartInit(void)
{

    //--------------------------------------------------- 各変数の初期化
    // 頂点データを格納する
    InitVertex(VertexDataTbl);

    //--------------------------------------------------- フレームナンバーセット
    g_FrameNo = START_FRAME;

}

//-----------------------------------------------------------------------------
// 関数名 : StartFrame()
// 機能概要: スタート画面処理
//-----------------------------------------------------------------------------
void StartFrame(void)
{
    // 頂点フォーマットを設定
    gl_lpD3ddev->SetVertexShader(FVF_TLVERTEX);
    // 三角形ポリゴンをバックバッファに転送
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 1, VertexDataTbl, sizeof(TLVERTX));

    // リターンキーが押されたら、ゲーム開始
    if ( gl_KeyTbl[VK_RETURN] & 0x80 ) g_FrameNo = GAME_INIT;

}

《解説》

《解説2:DrawPrimitiveUPメソッドの構文》

HRESULT DrawPrimitiveUP(
	D3DPRIMITIVETYPE PrimitiveType,
	UINT PrimitiveCount,
	CONST void* pVertexStriamZeroData,
	UINT VertexStreamZeroStride
);
PrimitiveType
描画するプリミティブ(ポリゴン)の種類を指定する
PrimitiveCount
描画するプリミティブの数を指定する。三角形のときは三角形の数
pVertexStriamZeroData
描画するプリミティブの頂点データ配列の先頭アドレスを指定する。この位置からPrimitiveCount分だけ描画する
VertexStreamZeroStride
頂点データ構造体のバイト数を指定する

※動作確認

  1. (1)で作成したプログラムに上記修正を行い、青い三角形が表示されることを確認する
  2. ポリゴンの頂点座標を変更し、思い通りの場所に思い通りの形で三角形が表示されるかどうかを確認する
  3. ポリゴンの頂点色を変更し、色が変わるかどうかを確認する

プログラムの無駄を省く

頂点情報を元にポリゴンを描画するには、頂点情報データの構造をデバイスにセットしてから描画しなければならない。

// 頂点フォーマットを設定
gl_lpD3ddev->SetVertexShader(FVF_TLVERTEX);
// 三角形ポリゴンをバックバッファに転送
gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 1, VertexDataTbl, sizeof(TLVERTX));

しかし、頂点情報データ構造(構造体)自身はゲーム・ループ中に変更されることはありえない。よって、頂点フォーマットの設定はシーン開始直後に行えばよい。つまり、スタート画面処理やゲーム画面処理で行うのではなく、UpdateFrame関数内で実行すればよい。

《UpdateFrame関数》

//-----------------------------------------------------------------------------
// 関数名 : UpdateFrame()
// 機能概要: ゲームメイン処理
//-----------------------------------------------------------------------------
BOOL UpdateFrame(void)
{

    /* 現在のキー情報を取得 */
    if ( !GetKeyboardState(gl_KeyTbl) ) {
        MessageBox(hWnd, "キー情報の取得に失敗", "ERROR", MB_OK);
        return (FALSE);
    }

    /* 画面のクリア */
    gl_lpD3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 0.0, 0);
    /* シーン開始 */
    gl_lpD3ddev->BeginScene();
    /* 頂点フォーマットを設定 */
    gl_lpD3ddev->SetVertexShader(FVF_TLVERTEX);

    /* 処理の振り分け */
    switch ( g_FrameNo ) {
        case START_INIT:
            // スタート画面を表示する前に実行する初期化関数を実行
            StartInit();
        case START_FRAME:
            // スタート画面表示処理関数を実行
            StartFrame();
            break;
        case GAME_INIT:
            // ゲーム画面を表示する前に実行する初期化関数を実行
        case GAME_FRAME:
            // ゲーム画面表示処理関数を実行
            break;
        default:
            MessageBox(hWnd, "g_FrameNoの値が例外です。", "ERROR", MB_OK);
            return (FALSE);
    }

    /* シーン終了 */
    gl_lpD3ddev->EndScene();
    /* フリップ */
    gl_lpD3ddev->Present(NULL, NULL, NULL, NULL);

    return (TRUE);
}

《StartFrame関数》

//-----------------------------------------------------------------------------
// 関数名 : StartFrame()
// 機能概要: スタート画面処理
//-----------------------------------------------------------------------------
void StartFrame(void)
{
    /* 描画処理 */
    // 三角形ポリゴンをバックバッファに転送
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 1, VertexDataTbl, sizeof(TLVERTX));

    // リターンキーが押されたら、ゲーム開始
    if ( gl_KeyTbl[VK_RETURN] & 0x80 ) g_FrameNo = GAME_INIT;

}

《解説》

※上記修正を行い、正しく表示されることを確認すること!!


BACK(ポリゴンについて) NEXT(ポリゴンの描画(四角形))