天天看点

MFC+D3D

1. 新建单文档类型的MFC应用程序

2. 添加三个lib文件:d3d9.lib d3dx9.lib winmm.lib

3. 在D3D9MFCView.h文件中添加如下代码:

包含头文件:#include <d3dx9.h> //88888

添加成员函数和成员变量:

//88888

private:

HRESULT initD3D(

HWND hwnd,

int width,

int height,

bool windowed,

D3DDEVTYPE deviceType);

HRESULT setup(int width, int height);

HRESULT cleanup();

public:

HRESULT update(float timeDelta);

HRESULT render();

private:

IDirect3DDevice9* _device;

D3DPRESENT_PARAMETERS _d3dpp;

ID3DXMesh* _teapot;

public:

virtual void OnInitialUpdate();

afx_msg void OnSize(UINT nType, int cx, int cy);

afx_msg BOOL OnEraseBkgnd(CDC* pDC);

//88888

对应函数实现:

CD3D9MFCView::CD3D9MFCView():_device(0),_teapot(0)

{

// TODO: add construction code here

::ZeroMemory(&_d3dpp,sizeof(_d3dpp));//88888

}

CD3D9MFCView::~CD3D9MFCView()

{

if (_teapot)

_teapot->Release();

if(_device)

_device->Release();

}

HRESULT CD3D9MFCView::initD3D(HWND hwnd,

int width,

int height,

bool windowed,

D3DDEVTYPE deviceType)

{

HRESULT hr = 0;

// Step 1: Create the IDirect3D9 object.

IDirect3D9* d3d9 = 0;

d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

if( !d3d9 )

{

::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);

return E_FAIL;

}

// Step 2: Check for hardware vp.

D3DCAPS9 caps;

d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);

int vp = 0;

if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )

vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;

else

vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

// Step 3: Fill out the D3DPRESENT_PARAMETERS structure.

_d3dpp.BackBufferWidth = width;

_d3dpp.BackBufferHeight = height;

_d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;

_d3dpp.BackBufferCount = 1;

_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;

_d3dpp.MultiSampleQuality = 0;

_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

_d3dpp.hDeviceWindow = hwnd;

_d3dpp.Windowed = windowed;

_d3dpp.EnableAutoDepthStencil = true;

_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;

_d3dpp.Flags = 0;

_d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

_d3dpp.PresentationInterval =

D3DPRESENT_INTERVAL_IMMEDIATE;

// Step 4: Create the device.

hr = d3d9->CreateDevice(

D3DADAPTER_DEFAULT, // primary adapter

deviceType, // device type

hwnd, // window associated with device

vp, // vertex processing

&_d3dpp, // present parameters

&_device); // return created device

if( FAILED(hr) )

{

// try again using a safer configuration.

_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

hr = d3d9->CreateDevice(

D3DADAPTER_DEFAULT,

deviceType,

hwnd,

D3DCREATE_SOFTWARE_VERTEXPROCESSING,

&_d3dpp,

&_device);

if( FAILED(hr) )

{

d3d9->Release(); // done with d3d9 object

::MessageBox(0, "CreateDevice() - FAILED", 0, 0);

return hr;

}

}

d3d9->Release(); // done with d3d9 object

return S_OK;

}

HRESULT CD3D9MFCView::setup(int width, int height)

{

if( _device )

{

// Set view matrix.

D3DXMATRIX V;

D3DXVECTOR3 pos (0.0f, 0.0f, -6.0f);

D3DXVECTOR3 target (0.0f, 0.0f, 0.0f);

D3DXVECTOR3 up (0.0f, 1.0f, 0.0f);

D3DXMatrixLookAtLH(&V, &pos, &target, &up);

_device->SetTransform(D3DTS_VIEW, &V);

// Create the teapot.

if( !_teapot)

D3DXCreateTeapot(_device, &_teapot, 0);

// Use wireframe mode and turn off lighting.

_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

_device->SetRenderState(D3DRS_LIGHTING, false);

// Size the viewport based on window dimensions.

D3DVIEWPORT9 vp = {0, 0, width, height, 0.0f, 1.0f};

_device->SetViewport( &vp );

// Set the projection matrix based on the

// window dimensions.

D3DXMATRIX P;

D3DXMatrixPerspectiveFovLH(

&P,

D3DX_PI * 0.25f,//45-degree field of view

(float)width / (float)height,

1.0f,

1000.0f);

_device->SetTransform(D3DTS_PROJECTION, &P);

}

return S_OK;

}

HRESULT CD3D9MFCView::cleanup()

{

// Nothing to Destroy.

return S_OK;

}

HRESULT CD3D9MFCView::update(float timeDelta)

{

if( _device )

{

//

// Spin the teapot around the y-axis.

//

static float angle = 0.0f;

D3DXMATRIX yRotationMatrix;

D3DXMatrixRotationY(&yRotationMatrix, angle);

_device->SetTransform(D3DTS_WORLD, &yRotationMatrix);

angle += timeDelta;

if(angle >= D3DX_PI * 2.0f)

angle = 0.0f;

}

return S_OK;

}

HRESULT CD3D9MFCView::render()

{

if( _device )

{

//

// Draw the scene.

//

_device->Clear(0, 0,

D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,

0x00000000, 1.0f, 0);

_device->BeginScene();

// Draw the teapot.

_teapot->DrawSubset(0);

_device->EndScene();

_device->Present(0, 0, 0, 0);

}

return S_OK;

}

void CD3D9MFCView::OnInitialUpdate()

{

CView::OnInitialUpdate();

// TODO: Add your specialized code here and/or call the base class

CRect rect;

GetClientRect(&rect);

// Initialize Direct3D (e.g. acquire a IDirect3DDevice9 poniter).

HRESULT hr = initD3D(

GetSafeHwnd(),

rect.right,

rect.bottom,

true,

D3DDEVTYPE_HAL);

if(FAILED(hr))

{

MessageBox("initD3D() - Failed", "Error");

::PostQuitMessage(0);

}

// Setup the application.

hr = setup(rect.right, rect.bottom);

if(FAILED(hr))

{

MessageBox("setup() - Failed", "Error");

::PostQuitMessage(0);

}

}

void CD3D9MFCView::OnSize(UINT nType, int cx, int cy)

{

CView::OnSize(nType, cx, cy);

// TODO: Add your message handler code here

if( _device )

{

HRESULT hr = 0;

// On a resize we must change the dimensions of the

// back buffers to match the new window size.

_d3dpp.BackBufferWidth = cx;

_d3dpp.BackBufferHeight = cy;

// We are about to call Reset, free any resources

// that need to be freed prior to a Reset.

hr = cleanup();

if(FAILED(hr))

{

MessageBox("destroy() - Failed", "Error");

::PostQuitMessage(0);

}

// Reset the flipping chain with the new window dimensions.

// Note that all device states are reset to the default

// after this call.

hr = _device->Reset(&_d3dpp);

if(FAILED(hr))

{

MessageBox("Reset() - Failed", "Error");

::PostQuitMessage(0);

}

// Reinitialize resource and device states since we

// Reset everything.

hr = setup(cx, cy);

if(FAILED(hr))

{

MessageBox("setup() - Failed", "Error");

::PostQuitMessage(0);

}

}

}

BOOL CD3D9MFCView::OnEraseBkgnd(CDC* pDC)

{

// TODO: Add your message handler code here and/or call default

return FALSE;

//return CView::OnEraseBkgnd(pDC);

}

3. 在类CD3D9MFCApp中添加如下代码。

包含头文件:#include "mmsystem.h"//88888

添加重载函数:

BOOL CD3D9MFCApp::OnIdle(LONG lCount)

{

// TODO: Add your specialized code here and/or call the base class

CWinApp::OnIdle(lCount);

CWnd* mainFrame = AfxGetMainWnd();

CD3D9MFCView* cview =

(CD3D9MFCView*)mainFrame->GetWindow(GW_CHILD);

// Save last time.

static float lastTime = (float)timeGetTime();

// Compute time now.

float currentTime = (float)timeGetTime();

// Compute the difference: time elapsed in seconds.

float deltaTime = (currentTime - lastTime) * 0.001f;

// Last time is now current time.

lastTime = currentTime;

cview->update(deltaTime);

cview->render();

return TRUE;

//return CWinApp::OnIdle(lCount);

}

效果如下:

MFC+D3D