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);
}
效果如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZucWeqV1MzAjN1czM3ITMfBzLcNTMvwVNwATMwIzLcRnbl1GajFGd0F2LcRXZu5ibkN3YukGavw1LcpDc0RHaiojIsJye.gif)