DirectX9 で Sprite を表示する

DirectX の D3DXCreateSprite で Sprite を生成します。
LPD3DXSPRITE->Draw でアルファブレンディングを設定して描画します。

DirectX8 から「DirectDraw」「Direct3D」と呼ばれていたグラフィックス機能が DirectGraphics として統合されました。
DirectGraphics に含まれる Sprite(2Dグラフィックス)の基本としてアルファブレンディングに挑戦します。

DirectX 9.0 と DirectX 9.0 2003 では Sprite の仕様が違うらしく、関数のパラメータが異なります。
ここでは DirectX 9.0 2003 以降の仕様に基づいてプログラムします。

Direct3D(Sprite も含む)ではデバイスの設定が最初の関門で、ハードウエア(3D ボード)の種類によって微妙にプログラミングが 異なり、相性の悪い場合には非常に苦労する場合があります。(^_^;)
DirectX とハードウエアの構成に付いては DirectX のプロパティを表示 を参照して下さい。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. [ファイル] [新規作成] [プロジェクト]から空のプロジェクト(Sprite)を作成して下さい。
    プロジェクト/既存項目の追加からプログラムファイルとヘッダファイルをプロジェクトに追加して下さい。
    sprite.cpp は、プログラムの説明を参考にして作成して下さい。
    myd3d.h と myd3d.cpp は Object Class Library から取得して下さい。
    ファイル名 ファイルの説明
    sprite.cpp 「プログラムの説明」を参考に作成して下さい
    myd3d.h MyD3D Object Class ヘッダファイル
    myd3d.cpp MyD3D Object Class プログラムファイル
  2. #define と #include と Global Area の定義です。
    必要なヘッダファイルやリンクするライブラリは MyD3D.h で設定しています。
    *myd3d が MyD3D Object Class の定義です。
    g_pSprite が Sprite Object の定義です。
    g_pTexture が Sprite Object で表示するテクスチャです。
    g_bActive はウインドウが Active 状態のフラグです。
    ImgFile[] は表示するイメージファイルです。
    BMP または JPG の適当な画像を調達して来て下さい。
        #define     NAME    "DirectX9 Sprite"
        #include    "MyD3D.h"
    
        // Global Area
        HINSTANCE           g_hInst     = NULL;
        HWND                g_hWnd      = NULL;
        MyD3D               *myd3d      = NULL;     // MyD3D Object Class
        LPDIRECT3DDEVICE9   g_pDEV      = NULL;     // Direct3DDeviceインターフェイス
        LPD3DXSPRITE        g_pSprite   = NULL;     // スプライト
        LPDIRECT3DTEXTURE9  g_pTexture  = NULL;     // テクスチャ
        bool                g_bActive   = false;    // アクティブ状態
        char                ImgFile[]   = "c:\\data\\test\\ffx2s.jpg";
        
  3. WinMain() です。
    ウインドウの生成が終わると InitDXGraphics() で DirectX を初期化します。
    メッセージループの中から Draw() で Sprite を描画します。
        int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
        {   MSG         msg;
            HRESULT     hr;
                 :
                 :
            if (!g_hWnd)  return FALSE;
    
            // DirectX Graphicsの初期化
            hr = InitDXGraphics();
            if (FAILED(hr))
            {   DXTRACE_ERR("WinMain InitDXGraphics", hr);
                UnregisterClass(NAME, g_hInst);
                return FALSE;
            }
            // ウインドウ表示
            ShowWindow(g_hWnd, SW_SHOWNORMAL);
            UpdateWindow(g_hWnd);
            // メッセージ・ループ
            do
            {   if (PeekMessage(&msg,0,0,0,PM_REMOVE))
                {   TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else
                {   // レンダリングの処理
                    Draw();
                }
            } while (msg.message != WM_QUIT);
            UnregisterClass(NAME, g_hInst);
            return msg.wParam;
        }
        
  4. InitDXGraphics() では Direct3D device のインターフェースを取得して Sprite を生成します。
    new MyD3D(g_hWnd) で MyD3D Object Class をインスタンス化します。
    InitD3D() で Direct3D のインターフェースを取得します。
    D3DXCreateSprite() で Sprite を生成します。
    myd3d->LoadTexture() で表示する画像を入力します。
    MyD3D Object Class を使わないで書く方法は【NOTE】で説明します。
        HRESULT InitDXGraphics(void)
        {   HRESULT  hr;
    
            // Direct3D デバイスの設定
            myd3d= new MyD3D(g_hWnd);
            myd3d->InitD3D(&g_pDEV);
            // スプライト生成
            hr = D3DXCreateSprite(g_pDEV, &g_pSprite);
            if (FAILED(hr))
                return DXTRACE_ERR("InitDXGraphics D3DXCreateSprite", hr);
            // テクスチャの読み込み
            g_pTexture= myd3d->LoadTexture(ImgFile);
            return S_OK;
        }
        
  5. Sprite の描画です。
    2003 から Begin() と Draw() の仕様が変わっています。
    Begin(D3DXSPRITE_ALPHABLEND) の D3DXSPRITE_ALPHABLEND がアルファブレンディングの設定です。
    alpha がアルファブレンディング(透明処理)の度合いで 0x0 から 0x1FF までを +3 ずつアップしながら繰り返します。
    このプログラムでは操作していませんが alpha の後が RGB 毎の透明度で、赤・緑・青を個別に設定することもできます。
    アルファブレンディングをしないで単に描画するだけならもっと簡単です。
    単に描画する方法は【NOTE】で説明します。
        HRESULT Draw(void)
        {   // シーンのクリア
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(150,150,150),1.0f,0);
            // シーンの描画開始
            if (SUCCEEDED(g_pDEV->BeginScene()))
            {   // シーンの描画(スプライトの描画)
                static int alpha=0;
                g_pSprite->Begin(D3DXSPRITE_ALPHABLEND);
                g_pSprite->Draw(g_pTexture, NULL, NULL, NULL,
                           D3DCOLOR_ARGB(alpha>255?511-alpha:alpha,255,255,255));
                alpha+=3; alpha &= 0x1FF;
                g_pSprite->End();
                // シーンの描画終了
                g_pDEV->EndScene();
            }
            // シーンの表示
            return g_pDEV->Present(NULL, NULL, NULL, NULL);
        }
        
  6. CALLBACK 関数です。
    Escape キーが押されるとプログラムを終了します。
        LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
        {   HRESULT hr = S_OK;
    
            switch(msg)
            {   case WM_ACTIVATE:
                    g_bActive = (LOWORD(wParam) != 0);
                    break;
                case WM_KEYDOWN:
                    switch(wParam)
                    {   case VK_ESCAPE:
                            PostMessage(hWnd,WM_CLOSE,0,0);
                            break;
                    }
                    break;
                case WM_DESTROY:
                    if (g_pSprite)  g_pSprite->OnLostDevice();
                    CleanupDXGraphics();
                    PostQuitMessage(0);
                    g_hWnd = NULL;
                    return 0;
                }
                return DefWindowProc(hWnd, msg, wParam, lParam);
        }
        
  7. DirectX Graphics の終了処理です。
    取得したインターフェースやオブジェクトは必ず開放して下さい。
        bool CleanupDXGraphics(void)
        {
            SAFE_RELEASE(g_pSprite);
            SAFE_RELEASE(g_pTexture);
            SAFE_DELETE(myd3d);
            return true;
        }
        

【NOTE】

  1. Sprite で表示する画像は、次のコードを使って Texture Surface に入力しています。
    g_pTexture= myd3d->LoadTexture(ImgFile);
    LoadTexture() は MyD3D Object Class に登録されたメンバ関数ですが、メンバ関数を使わないで書くと次のようになります。
        if (FAILED(D3DXCreateTextureFromFile(g_pDEV,File,&g_pTexture)))
        {   MessageBox(NULL,File,"Texture Load Error",MB_OK);
            return E_FAIL;
        }
        
  2. 透明色を設定した PNG 画像を使うと、プログラムで透明色の設定をしなくても透明になるので試してみて下さい。
  3. アルファブレンディングをしないで単に描画するだけならもっと簡単です。
        void Draw(void)
        {
            //黒で塗りつぶして消去
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0,0);
            if (SUCCEEDED(g_pDEV->BeginScene()))
            {   // シーンの描画(スプライトの描画)
                g_pSprite->Begin(0);
                g_pSprite->Draw(g_pTexture, NULL, NULL, NULL, D3DCOLOR_ARGB(0,255,255,255));
                g_pSprite->End();
                // シーンの描画終了
                g_pDEV->EndScene();
            }
            g_pDEV->Present(NULL,NULL,NULL,NULL);
        }
        
  4. このプログラムでは問題にならないのですが、Texture に格納される画像のサイズは「2のべき乗」に調整されます。
    例えば 480*480 の画像は 512*512 で、200*100 の画像は 256*128 で格納されます。
    「2のべき乗」に調整されたく無いときは D3DXCreateTextureFromFileEx() 関数で、サイズを直接設定して入力して下さい。
  5. MyD3D Object Class には、これに対応する次のメンバ関数をサポートしています。
  6. このプログラムでは、デバイスが消失したときに備えて、復元を試みています。
        // Sprite の ResetDevice
        HRESULT ResetSprite(void)
        {   HRESULT hr= S_FALSE;
            if (g_pSprite)  hr= g_pSprite->OnResetDevice();
            return hr;
        }
        

超初心者の方のために全ソースコードを掲載します。 (^_^;)
全ソースコード

超初心者のプログラム入門(DirectX9 game program)