Partilhar via


D3DImage チュートリアル ③ C++コードの編集

D3DRenderer.cpp

やっとコーディングに入ります。D3DRenderer.cppを開き、以下の6行をD3DRenderer.hに移し、#include “D3DRenderer.h”と入れ替えます。

#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#pragma warning( disable : 4996 )
#include <strsafe.h>
#pragma warning( default : 4996 )

そして、D3DRenderer.cppの一番下にあるMsgProc()メソッドとwWinMain()メソッドは、実行ファイルのエントリーポイントなので、DLLの場合には不要ですから、削除します

まず、D3DInitの前に以下のメンバ変数とCreateSurcace()メソッドを追加します。

LPDIRECT3DSURFACE9 g_pd3dSurface = NULL;

HRESULT CreateSurface(UINT nWidth, UINT nHeight)
{
  HRESULT hr = g_pd3dDevice->CreateRenderTarget(
               nWidth, nHeight,
D3DFMT_A8R8G8B8, 
D3DMULTISAMPLE_NONE,
0,
               True,
&g_pd3dSurface,
NULL);
  if (SUCCEEDED(hr))
    hr = g_pd3dDevice->
SetRenderTarget(0, g_pd3dSurface);
  return hr;
}

D3DImage() メソッド内のCreateDevice呼び出しの下(// Turn on the zbufferの前)に、追加したCreateSurface()メソッドの呼び出しを追加します。このレンダーターゲットをWPFのD3DImageとして使うことになります。

if (FAILED(CreateSurface(SCREEN_WIDTH, SCREEN_HEIGHT)))
return E_FAIL;

次に、CreateDeviceにフラグを追加します。WPFのレンダリングスレッドから安全にDirect3Dスレッドを呼び出せるようにD3DCREATE_MULTITHREADEDフラグを追加し、WPFでは倍精度浮動小数点を使うのでD3DCREATE_FPU_PRESERVEフラグを追加します。

if( FAILED( g_pD3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING |
D3DCREATE_MULTITHREADED |
D3DCREATE_FPU_PRESERVE,
&d3dpp, &g_pd3dDevice ) ) )

 

次に、Render() メソッドの修正です。背景はWPFで描画するので、レンダリング時の背景を透明にします。また、レンダーターゲット サーフェイスに描画するだけで、フロントバッファへのスワップチェーンは不要なのでPresentメソッドをコメントアウトします。

g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET |
D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB( 0, 0, 0, 0), 1.0f, 0 );

// g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

最後に、整列データ型はマネージ コードでサポートされていないので、SetupMatrices() メソッドのD3DXMATRIXA16をD3DMATRIXに変更します。

D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;

D3DRenderer.h

D3DRenderer.hに以下の宣言を追加します(灰色は先ほどD3DRenderer.cppからコピーした部分)。

#include <Windows.h>
#include <mmsystem.h>
#include <d3d9.h>
#include <d3dx9.h>
#pragma warning( disable : 4996 )
#include <strsafe.h>
#pragma warning ( default : 4996 )

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480

extern LPDIRECT3DSURFACE9 g_pd3dSurface;

#define DXERR_FILE_NOT_FOUND 0x88760389

HRESULT InitD3D(HWND hWnd);
HRESULT InitGeometry();
VOID Render();
VOID Cleanup();

D3DWrapper.cpp

D3DWrapper.cppを以下のように実装します。今のところ引数によるデータのやり取りしかないので、Render以外は、D3DRenderer.hで宣言したメソッドを呼び出すラッパーメソッドを定義するだけです。「::」はC++のグローバルメンバーを指します。

Render()メソッドは描画サイズをWPFに返すために、引数にwidthとheightを加えます。C++なので、クラス定義の終りの「;」も忘れないでください。

D3DRendererプロジェクトを右クリックして、[プロジェクトのみ]→[D3DRendererのみをリビルド]でビルドしてビルドエラーがないかどうか確認してください。

#include "D3DRenderer.h"
#include <vcclr.h>

using namespace System;

namespace D3DMesh
{
  public ref class D3DWrapper
  {
  public:
    IntPtr Initialize(IntPtr hwnd)
    {
      if (SUCCEEDED(::InitD3D((HWND) hwnd.ToPointer())))
        return IntPtr(g_pd3dSurface);
      return IntPtr::Zero;
    }

VOID InitGeometry()
{
::InitGeometry();
}

    VOID Render(int% width, int% height)
    {
      ::Render();
      width = SCREEN_WIDTH;
      height = SCREEN_HEIGHT;
    }

    VOID Cleanup()
    {
      ::Cleanup();
    }
  };

}

つづく