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();
}
};
}
つづく