図形を背景に画像を描画

OffscreenSurface に描いた図形を背景に、透明色を設定した Sprite を回転しながら描画します。
DirectX の GetBackBuffer でバックバッファを取得して、CreateOffscreenPlainSurface で画像ファイルのサーフェースを作成します。
Direct3D ではデバイスの設定が難問で、ハードによっては「うまく動かない」かも知れません。

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

プログラムの説明

  1. OffscreenSurface の基本的なプログラムは OffscreenSurface に Jpeg Image をロードする を参照して下さい。
    新規作成で空のプロジェクト(DrawSprite)を作成して drawsprite.cpp をプロジェクトに追加して下さい。
  2. Global Area と Direct3D Object と Sprite の定義です。
    g_pBackBuffer がバックバッファサーフェースで、g_pSurface が背景図形を描画するサーフェースです。
    ImgFile[] が図形の上から描画する画像です。
    透明色(黒)を使った適当な画像を調達してきて下さい。
        // Global Area
        MyD3D               *myd3d        = NULL;       // MyD3D Object Class
        HWND                g_hWnd        = NULL;
        LPDIRECT3DDEVICE9   g_pDEV        = NULL;       // 描写用デバイス
        LPDIRECT3DSURFACE9  g_pBackBuffer = NULL;       // バックバッファ用
        LPDIRECT3DSURFACE9  g_pSurface    = NULL;       // 背景画像サーフェース用
        LPD3DXSPRITE        g_pSprite     = NULL;       // スプライト
        LPDIRECT3DTEXTURE9  g_pTexture    = NULL;       // スプライトに使うテクスチャ
        bool                g_bActive     = false;      // アクティブ状態
        char                ImgFile[]     = "kishi.bmp";
        
  3. WinMain() と CALLBACK はいつもと同じです。
  4. Direct3D を初期化する InitDevices() 関数です。
    MyD3D Object Class をインスタンス化して InitD3D() でインターフェースを取得します。
    Sprite を作成して、テクスチャを入力します。
    LoadTextureBlack() を使うと黒(0,0,0)が透明色に設定されます。
    CreateSurface() で Buffer と同じ形式の OffscreenSurface を生成します。
    DrawSurface() でオフスクリーンサーフェースに背景画像を書きます。
        HRESULT InitDevices(void)
        {   HRESULT  hr;
    
            // Direct3D デバイスの設定
            myd3d= new MyD3D(g_hWnd);
            myd3d->InitD3D(&g_pDEV);
            // スプライト作成
            hr = D3DXCreateSprite(g_pDEV, &g_pSprite);
            if (FAILED(hr))
            {   MessageBox(NULL,"InitDXGraphics D3DXCreateSprite","Sprite Error",MB_OK);
                return  FALSE;
            }
            // テクスチャの読み込み
            g_pTexture= myd3d->LoadTextureBlack(ImgFile);
            // 画像ファイル用オフスクリーンサーフェースの作成
            g_pSurface= myd3d->CreateSurface();
            DrawSurface();          // 図形を描画
            return  TRUE;
        }
        
  5. OffscreenSurface(g_pSurface) に背景に表示する図形を描画します。
    g_pSurface->GetDC(&hDC) で HDC を取得できれば、後は普通の Windows の描画と同じです。
        HRESULT DrawSurface()
        {   HDC             hDC;
            D3DSURFACE_DESC desc;
            HBRUSH          hOldBrush;
            HRESULT         hr;
    
            hr= g_pSurface->GetDC(&hDC);
            if (!FAILED(hr))
            {   g_pSurface->GetDesc(&desc);
                hOldBrush= (HBRUSH)SelectObject(hDC,GetStockObject(BLACK_BRUSH));
                Rectangle(hDC,0,0,desc.Width,desc.Height);
                SelectObject(hDC,GetStockObject(WHITE_BRUSH));
                Rectangle(hDC,50,50,500,400);
                SelectObject(hDC,GetStockObject(LTGRAY_BRUSH));
                Ellipse(hDC,120,120,400,300);
                SelectObject(hDC,hOldBrush);
                g_pSurface->ReleaseDC(hDC);
            }
            else    MessageBox(NULL,"GetDC Error","Surface Error",MB_OK);
            return hr;
        }
        
  6. Render() の処理です。
    Sprite で描画する画像をタイマで回転します。
    また画像を中央に配置するように D3DXMatrixTranslation() で移動します。
    g_pSprite->SetTransform() でワールド座標を設定して描画の準備が完了です。
    g_pDEV->StretchRect() で背景を BackBuffer に描画(転送)します。
    SrcRect が送り側の矩形で、DestRect が受け取り側の矩形です。
    背景が BackBuffer に描画できれば、上から ColorKey を設定した Sprite を回転しながら描画します。
        VOID  Render()
        {   D3DXMATRIX  matWorld,matWork;
            RECT        SrcRect,DestRect;
    
            if (!g_pDEV || !g_bActive)  return;
            D3DXMatrixRotationZ(&matWorld,timeGetTime()/1000.0f);
            D3DXMatrixTranslation(&matWork,258.0f,218.0f,0.0f);
            matWorld= matWorld*matWork;
            g_pSprite->SetTransform(&matWorld);
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(200,150,0),1.0f,0);
            // バックバッファへ描画
            if (FAILED(g_pDEV->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&g_pBackBuffer)))
                MessageBox(NULL,"GetBackBuffer Error","Sprite Error",MB_OK);
            SrcRect= myd3d->GetSurfaceRect(g_pSurface);
            DestRect= myd3d->GetSurfaceRect(g_pSurface);
            g_pDEV->StretchRect(g_pSurface,&SrcRect,g_pBackBuffer,&DestRect,D3DTEXF_NONE);
            // スプライトの描画
            if (SUCCEEDED(g_pDEV->BeginScene()))
            {
                g_pSprite->Begin(D3DXSPRITE_ALPHABLEND);
                g_pSprite->Draw(g_pTexture,NULL,&D3DXVECTOR3(64,64,0),NULL,0xF0808080);
                g_pSprite->End();
                g_pDEV->EndScene();
            }
            g_pDEV->Present(NULL,NULL,NULL,NULL);
            SAFE_RELEASE(g_pBackBuffer);
        }
        
  7. オブジェクトを開放する処理です。
        VOID  Cleanup()
        {   SAFE_RELEASE(g_pSurface);
            SAFE_RELEASE(g_pTexture);
            SAFE_RELEASE(g_pSprite);
            SAFE_DELETE(myd3d);
        }
        

【ヒント】

Back Buffer が取得できないときは Back Buffer を取得して円を描画する を参照して下さい。

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

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

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

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