Direct3D入门知识及怎么样搭建框架?
学习一样东西,最好能够从最基础做起。学习D3D,笔者并不赞同直接继承SDK Sample的CD3DApplication,然后override那几个虚函数,因为这样会让初学者对D3D更感神秘,因此我们需要从头开始,不用害怕,其实一点都不难:)
一、Win32 SDK框架
看过Petzold的《Windows程序设计》的朋友应该知道创建窗口的固定步骤。而利用Win32 SDK搭建D3D框架只不过是在这些步骤中加入一些调料罢了。具体步骤如下:
1、注册窗体类;
2、创建窗口;
3、创建消息处理函数;
4、显示窗口;
5、初始化D3D、初始化资源数据(如:顶点向量、纹理等);
6、进入消息循环,用PeekMessage处理消息,以便在空闲时进行渲染。
2、创建窗口;
3、创建消息处理函数;
4、显示窗口;
5、初始化D3D、初始化资源数据(如:顶点向量、纹理等);
6、进入消息循环,用PeekMessage处理消息,以便在空闲时进行渲染。
而初始化D3D又分下面四个步骤:
1、创建IDirect3D9[1]对象;
2、检查硬件性能,判断硬件是否支持特定的功能;
3、填充D3DPRESENT_PARAMETERS结构;
4、利用第3步中的结构体对象创建D3D设备(由于该步骤需要窗体的句柄,所以初始化D3D必须放在显示窗口之后)。
2、检查硬件性能,判断硬件是否支持特定的功能;
3、填充D3DPRESENT_PARAMETERS结构;
4、利用第3步中的结构体对象创建D3D设备(由于该步骤需要窗体的句柄,所以初始化D3D必须放在显示窗口之后)。
下面是框架代码:
000001//
000002// 全局变量
000003//
000004
000005IDirect3DDevice9* Device = 0;
000006
000007
000008bool InitD3D(
000009HINSTANCE hInstance,
000010int width, int height,
000011bool windowed,
000012D3DDEVTYPE deviceType,
000013IDirect3DDevice9** device)
000014{
000015WNDCLASS wc;
000016
000017wc.style = CS_HREDRAW | CS_VREDRAW;
000018wc.lpfnWndProc = (WNDPROC)WndProc;
000019wc.cbClsExtra = 0;
000020wc.cbWndExtra = 0;
000021wc.hInstance = hInstance;
000022wc.hIcon = LoadIcon(0, IDI_APPLICATION);
000023wc.hCursor = LoadCursor(0, IDC_ARROW);
000024wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
000025wc.lpszMenuName = 0;
000026wc.lpszClassName = "Direct3D9App";
000027// 注册窗口类
000028if( !RegisterClass(&wc) )
000029{
000030MessageBox(0, "RegisterClass() - FAILED", 0, 0);
000031return false;
000032}
000033
000034HWND hwnd = 0;
000035// 创建窗口
000036hwnd = CreateWindow("Direct3D9App", "Direct3D9App",
000037WS_EX_TOPMOST,
0000380, 0, width, height,
0000390 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);
000040
000041if( !hwnd )
000042{
000043MessageBox(0, "CreateWindow() - FAILED", 0, 0);
000044return false;
000045}
000046// 显示窗口
000047ShowWindow(hwnd, SW_SHOW);
000048UpdateWindow(hwnd);
000049
000050//
000051// 初始化D3D
000052//
000053
000054HRESULT hr = 0;
000055
000056// 步骤1:创建IDirect3D9对象。
000057
000058IDirect3D9* d3d9 = 0;
000059 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
000060
000061 if( !d3d9 )
000062{
000063MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
000064return false;
000065}
000066
000067// 步骤2:检查硬件性能(这里只检查了是否支持顶点的硬件处理)
000068
000069D3DCAPS9 caps;
000070d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
000071
000072int vp = 0;
000073if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
000074vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
000075else
000076vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
000077
000078// 步骤3:填充D3DPRESENT_PARAMETERS结构(参数说明请参考MSDN)
000079
000080D3DPRESENT_PARAMETERS d3dpp;
000081d3dpp.BackBufferWidth = width;
000082d3dpp.BackBufferHeight = height;
000083d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
000084d3dpp.BackBufferCount = 1;
000085d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
000086d3dpp.MultiSampleQuality = 0;
000087d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
000088d3dpp.hDeviceWindow = hwnd;
000089d3dpp.Windowed = windowed;
000090d3dpp.EnableAutoDepthStencil = true;
000091d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
000092d3dpp.Flags = 0;
000093d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
000094d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
000095
000096// 步骤4:创建D3D设备
000097
000098hr = d3d9->CreateDevice(
000099D3DADAPTER_DEFAULT, // 主设备
000100deviceType, // 设备类型
000101hwnd, // 分配给设备的窗口句柄
000102vp, // 顶点处理方式
000103 &d3dpp, // 表现参数
000104 device); // 返回创建的设备
000105
000106if( FAILED(hr) )
000107{
000108// 如果创建失败,采用16为深度缓存试试
000109d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
000110
000111hr = d3d9->CreateDevice(
000112D3DADAPTER_DEFAULT,
000113deviceType,
000114hwnd,
000115vp,
000116&d3dpp,
000117device);
000118
000119if( FAILED(hr) )
000120{
000121d3d9->Release();
000122MessageBox(0, "CreateDevice() - FAILED", 0, 0);
000123return false;
000124}
000125}
000126
000127d3d9->Release();
000128
000129return true;
000130}
000131
000132// 消息循环
000133int MsgLoop()
000134{
000135MSG msg;
000136ZeroMemory(&msg, sizeof(MSG));
000137
000138while(msg.message != WM_QUIT)
000139{
000140if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
000141{
000142TranslateMessage(&msg);
000143DispatchMessage(&msg);
000144}
000145else
000146 {
000147Display();// 渲染
000148 }
000149 }
000150 return msg.wParam;
000151}
000152
000153
000154//
000155// 框架函数
000156//
000157
000158bool Setup()
000159{
000160// 你可以在此初始化顶点向量、载入纹理等
000161
000162return true;
000163}
000164
000165void Cleanup()
000166{
000167// 清除在Setup中载入的资源
000168}
000169
000170bool Display()
000171{
000172if( Device ) // 只有当设备有效时才能渲染
000173{
000174// 在此填入渲染代码
000175}
000176return true;
000177}
000178
000179//
000180// 窗口处理函数
000181//
000182LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
000183{
000184switch( msg )
000185{
000186case WM_DESTROY:
000187PostQuitMessage(0);
000188break;
000189
000190case WM_KEYDOWN:
000191if( wParam == VK_ESCAPE )
000192DestroyWindow(hwnd);
000193break;
000194}
000195return DefWindowProc(hwnd, msg, wParam, lParam);
000196}
000197
000198//
000199// 程序入口
000200//
000201int WINAPI WinMain(HINSTANCE hinstance,
000202 HINSTANCE prevInstance,
000203 PSTR cmdLine,
000204 int showCmd)
000205{
000206if(!InitD3D(hinstance,
000207640, 480, true, D3DDEVTYPE_HAL, &Device))
000208{
000209MessageBox(0, "InitD3D() - FAILED", 0, 0);
000210return 0;
000211}
000212
000213if(!Setup())
000214{
000215MessageBox(0, "Setup() - FAILED", 0, 0);
000216return 0;
000217}
000218
000219MsgLoop();
000220
000221Cleanup();
000222
000223Device->Release();
000224
000225return 0;
000226}
000002// 全局变量
000003//
000004
000005IDirect3DDevice9* Device = 0;
000006
000007
000008bool InitD3D(
000009HINSTANCE hInstance,
000010int width, int height,
000011bool windowed,
000012D3DDEVTYPE deviceType,
000013IDirect3DDevice9** device)
000014{
000015WNDCLASS wc;
000016
000017wc.style = CS_HREDRAW | CS_VREDRAW;
000018wc.lpfnWndProc = (WNDPROC)WndProc;
000019wc.cbClsExtra = 0;
000020wc.cbWndExtra = 0;
000021wc.hInstance = hInstance;
000022wc.hIcon = LoadIcon(0, IDI_APPLICATION);
000023wc.hCursor = LoadCursor(0, IDC_ARROW);
000024wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
000025wc.lpszMenuName = 0;
000026wc.lpszClassName = "Direct3D9App";
000027// 注册窗口类
000028if( !RegisterClass(&wc) )
000029{
000030MessageBox(0, "RegisterClass() - FAILED", 0, 0);
000031return false;
000032}
000033
000034HWND hwnd = 0;
000035// 创建窗口
000036hwnd = CreateWindow("Direct3D9App", "Direct3D9App",
000037WS_EX_TOPMOST,
0000380, 0, width, height,
0000390 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);
000040
000041if( !hwnd )
000042{
000043MessageBox(0, "CreateWindow() - FAILED", 0, 0);
000044return false;
000045}
000046// 显示窗口
000047ShowWindow(hwnd, SW_SHOW);
000048UpdateWindow(hwnd);
000049
000050//
000051// 初始化D3D
000052//
000053
000054HRESULT hr = 0;
000055
000056// 步骤1:创建IDirect3D9对象。
000057
000058IDirect3D9* d3d9 = 0;
000059 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
000060
000061 if( !d3d9 )
000062{
000063MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
000064return false;
000065}
000066
000067// 步骤2:检查硬件性能(这里只检查了是否支持顶点的硬件处理)
000068
000069D3DCAPS9 caps;
000070d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
000071
000072int vp = 0;
000073if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
000074vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
000075else
000076vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
000077
000078// 步骤3:填充D3DPRESENT_PARAMETERS结构(参数说明请参考MSDN)
000079
000080D3DPRESENT_PARAMETERS d3dpp;
000081d3dpp.BackBufferWidth = width;
000082d3dpp.BackBufferHeight = height;
000083d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
000084d3dpp.BackBufferCount = 1;
000085d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
000086d3dpp.MultiSampleQuality = 0;
000087d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
000088d3dpp.hDeviceWindow = hwnd;
000089d3dpp.Windowed = windowed;
000090d3dpp.EnableAutoDepthStencil = true;
000091d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
000092d3dpp.Flags = 0;
000093d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
000094d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
000095
000096// 步骤4:创建D3D设备
000097
000098hr = d3d9->CreateDevice(
000099D3DADAPTER_DEFAULT, // 主设备
000100deviceType, // 设备类型
000101hwnd, // 分配给设备的窗口句柄
000102vp, // 顶点处理方式
000103 &d3dpp, // 表现参数
000104 device); // 返回创建的设备
000105
000106if( FAILED(hr) )
000107{
000108// 如果创建失败,采用16为深度缓存试试
000109d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
000110
000111hr = d3d9->CreateDevice(
000112D3DADAPTER_DEFAULT,
000113deviceType,
000114hwnd,
000115vp,
000116&d3dpp,
000117device);
000118
000119if( FAILED(hr) )
000120{
000121d3d9->Release();
000122MessageBox(0, "CreateDevice() - FAILED", 0, 0);
000123return false;
000124}
000125}
000126
000127d3d9->Release();
000128
000129return true;
000130}
000131
000132// 消息循环
000133int MsgLoop()
000134{
000135MSG msg;
000136ZeroMemory(&msg, sizeof(MSG));
000137
000138while(msg.message != WM_QUIT)
000139{
000140if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
000141{
000142TranslateMessage(&msg);
000143DispatchMessage(&msg);
000144}
000145else
000146 {
000147Display();// 渲染
000148 }
000149 }
000150 return msg.wParam;
000151}
000152
000153
000154//
000155// 框架函数
000156//
000157
000158bool Setup()
000159{
000160// 你可以在此初始化顶点向量、载入纹理等
000161
000162return true;
000163}
000164
000165void Cleanup()
000166{
000167// 清除在Setup中载入的资源
000168}
000169
000170bool Display()
000171{
000172if( Device ) // 只有当设备有效时才能渲染
000173{
000174// 在此填入渲染代码
000175}
000176return true;
000177}
000178
000179//
000180// 窗口处理函数
000181//
000182LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
000183{
000184switch( msg )
000185{
000186case WM_DESTROY:
000187PostQuitMessage(0);
000188break;
000189
000190case WM_KEYDOWN:
000191if( wParam == VK_ESCAPE )
000192DestroyWindow(hwnd);
000193break;
000194}
000195return DefWindowProc(hwnd, msg, wParam, lParam);
000196}
000197
000198//
000199// 程序入口
000200//
000201int WINAPI WinMain(HINSTANCE hinstance,
000202 HINSTANCE prevInstance,
000203 PSTR cmdLine,
000204 int showCmd)
000205{
000206if(!InitD3D(hinstance,
000207640, 480, true, D3DDEVTYPE_HAL, &Device))
000208{
000209MessageBox(0, "InitD3D() - FAILED", 0, 0);
000210return 0;
000211}
000212
000213if(!Setup())
000214{
000215MessageBox(0, "Setup() - FAILED", 0, 0);
000216return 0;
000217}
000218
000219MsgLoop();
000220
000221Cleanup();
000222
000223Device->Release();
000224
000225return 0;
000226}
二、MFC框架
利用MFC,我们不用写一行代码就可以创建一个窗体,这是MFC封装了那些繁琐而固定的窗口创建代码,这样我们只需要初始化D3D就可以了。下面是通过不带文档的SDI作为示例来创建D3D的框架,具体步骤如下:
1、将InitD3D、Setup、Cleanup、Display作为CMainFrame的成员函数,其中InitD3D需被应用程序类调用,应该将其置为public,其余为内部函数;
2、在应用程序类(CWinApp的子类)的InitInstance()中显示窗口之后,对D3D进行初始化;
3、override Run(),其实,这里就是消息循环;
2、在应用程序类(CWinApp的子类)的InitInstance()中显示窗口之后,对D3D进行初始化;
3、override Run(),其实,这里就是消息循环;
这里需要注意:
填充D3DPRESENT_PARAMETERS时,BackBufferWidth和BackBufferHeight最好设置为客户区大小,hDeviceWindow设置为视窗口的句柄m_wndView.m_hWnd,最重要的是Windowed[2]一定要置为true,否则会产生“无效调用”的错误。
下面是实际代码,该代码渲染了一个带贴图的旋转正方体:
000001// MFCD3D.cpp : 定义应用程序的类行为。
000002//
000003
000004#include "stdafx.h"
000005#include "MFCD3D.h"
000006#include "MainFrm.h"
000007#include <mmsystem.h>
000008
000009#ifdef _DEBUG
000010#define new DEBUG_NEW
000011#endif
000012
000013
000014// CMFCD3DApp
000015
000016BEGIN_MESSAGE_MAP(CMFCD3DApp, CWinApp)
000017ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
000018END_MESSAGE_MAP()
000019
000020
000021// CMFCD3DApp 构造
000022
000023CMFCD3DApp::CMFCD3DApp()
000024{
000025// TODO: 在此处添加构造代码,
000026// 将所有重要的初始化放置在 InitInstance 中
000027}
000028
000029
000030// 唯一的一个 CMFCD3DApp 对象
000031
000032CMFCD3DApp theApp;
000033
000034// CMFCD3DApp 初始化
000035
000036BOOL CMFCD3DApp::InitInstance()
000037{
000038// 如果一个运行在 Windows XP 上的应用程序清单指定要
000039// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
000040//则需要 InitCommonControls()。否则,将无法创建窗口。
000041InitCommonControls();
000042
000043CWinApp::InitInstance();
000044
000045// 初始化 OLE 库
000046if (!AfxOleInit())
000047{
000048AfxMessageBox(IDP_OLE_INIT_FAILED);
000049return FALSE;
000050}
000051AfxEnableControlContainer();
000052// 标准初始化
000053// 如果未使用这些功能并希望减小
000054// 最终可执行文件的大小,则应移除下列
000055// 不需要的特定初始化例程
000056// 更改用于存储设置的注册表项
000057// TODO: 应适当修改该字符串,
000058// 例如修改为公司或组织名
000059SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
000060// 若要创建主窗口,此代码将创建新的框架窗口
000061// 对象,然后将其设置为应用程序的主窗口对象
000062CMainFrame* pFrame = new CMainFrame;
000063if (!pFrame)
000064return FALSE;
000065m_pMainWnd = pFrame;
000066// 创建并加载带有其资源的框架
000067pFrame->LoadFrame(IDR_MAINFRAME,
000068WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
000069NULL);
000070// 唯一的一个窗口已初始化,因此显示它并对其进行更新
000071pFrame->ShowWindow(SW_SHOW);
000072pFrame->UpdateWindow();
000073// 仅当存在后缀时才调用 DragAcceptFiles,
000074// 在 SDI 应用程序中,这应在 ProcessShellCommand 之后发生
000075// D3D初始化
000076return pFrame->InitD3D();
000077}
000078
000079
000080// CMFCD3DApp 消息处理程序
000081
000082
000083
000084// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
000085
000086class CAboutDlg : public CDialog
000087{
000088public:
000089CAboutDlg();
000090
000091// 对话框数据
000092enum { IDD = IDD_ABOUTBOX };
000093
000094protected:
000095virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
000096
000097// 实现
000098protected:
000099DECLARE_MESSAGE_MAP()
000100};
000101
000102CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
000103{
000104}
000105
000106void CAboutDlg::DoDataExchange(CDataExchange* pDX)
000107{
000108CDialog::DoDataExchange(pDX);
000109}
000110
000111BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
000112END_MESSAGE_MAP()
000113
000114// 用于运行对话框的应用程序命令
000115void CMFCD3DApp::OnAppAbout()
000116{
000117CAboutDlg aboutDlg;
000118aboutDlg.DoModal();
000119}
000120
000121
000122// CMFCD3DApp 消息处理程序
000123
000124
000125int CMFCD3DApp::Run()
000126{
000127MSG msg;
000128::ZeroMemory(&msg, sizeof(MSG));
000129
000130static float lastTime = (float)timeGetTime();
000131
000132while(msg.message != WM_QUIT)
000133{
000134if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
000135{
000136::TranslateMessage(&msg);
000137::DispatchMessage(&msg);
000138}
000139else
000140{
000141float currTime = (float)timeGetTime();
000142float timeDelta = (currTime - lastTime)*0.001f;
000143lastTime = currTime;
000144
000145((CMainFrame*)m_pMainWnd)->Render(timeDelta);
000146}
000147 }
000148return CWinApp::Run();
000149}
000002//
000003
000004#include "stdafx.h"
000005#include "MFCD3D.h"
000006#include "MainFrm.h"
000007#include <mmsystem.h>
000008
000009#ifdef _DEBUG
000010#define new DEBUG_NEW
000011#endif
000012
000013
000014// CMFCD3DApp
000015
000016BEGIN_MESSAGE_MAP(CMFCD3DApp, CWinApp)
000017ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
000018END_MESSAGE_MAP()
000019
000020
000021// CMFCD3DApp 构造
000022
000023CMFCD3DApp::CMFCD3DApp()
000024{
000025// TODO: 在此处添加构造代码,
000026// 将所有重要的初始化放置在 InitInstance 中
000027}
000028
000029
000030// 唯一的一个 CMFCD3DApp 对象
000031
000032CMFCD3DApp theApp;
000033
000034// CMFCD3DApp 初始化
000035
000036BOOL CMFCD3DApp::InitInstance()
000037{
000038// 如果一个运行在 Windows XP 上的应用程序清单指定要
000039// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
000040//则需要 InitCommonControls()。否则,将无法创建窗口。
000041InitCommonControls();
000042
000043CWinApp::InitInstance();
000044
000045// 初始化 OLE 库
000046if (!AfxOleInit())
000047{
000048AfxMessageBox(IDP_OLE_INIT_FAILED);
000049return FALSE;
000050}
000051AfxEnableControlContainer();
000052// 标准初始化
000053// 如果未使用这些功能并希望减小
000054// 最终可执行文件的大小,则应移除下列
000055// 不需要的特定初始化例程
000056// 更改用于存储设置的注册表项
000057// TODO: 应适当修改该字符串,
000058// 例如修改为公司或组织名
000059SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
000060// 若要创建主窗口,此代码将创建新的框架窗口
000061// 对象,然后将其设置为应用程序的主窗口对象
000062CMainFrame* pFrame = new CMainFrame;
000063if (!pFrame)
000064return FALSE;
000065m_pMainWnd = pFrame;
000066// 创建并加载带有其资源的框架
000067pFrame->LoadFrame(IDR_MAINFRAME,
000068WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
000069NULL);
000070// 唯一的一个窗口已初始化,因此显示它并对其进行更新
000071pFrame->ShowWindow(SW_SHOW);
000072pFrame->UpdateWindow();
000073// 仅当存在后缀时才调用 DragAcceptFiles,
000074// 在 SDI 应用程序中,这应在 ProcessShellCommand 之后发生
000075// D3D初始化
000076return pFrame->InitD3D();
000077}
000078
000079
000080// CMFCD3DApp 消息处理程序
000081
000082
000083
000084// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
000085
000086class CAboutDlg : public CDialog
000087{
000088public:
000089CAboutDlg();
000090
000091// 对话框数据
000092enum { IDD = IDD_ABOUTBOX };
000093
000094protected:
000095virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
000096
000097// 实现
000098protected:
000099DECLARE_MESSAGE_MAP()
000100};
000101
000102CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
000103{
000104}
000105
000106void CAboutDlg::DoDataExchange(CDataExchange* pDX)
000107{
000108CDialog::DoDataExchange(pDX);
000109}
000110
000111BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
000112END_MESSAGE_MAP()
000113
000114// 用于运行对话框的应用程序命令
000115void CMFCD3DApp::OnAppAbout()
000116{
000117CAboutDlg aboutDlg;
000118aboutDlg.DoModal();
000119}
000120
000121
000122// CMFCD3DApp 消息处理程序
000123
000124
000125int CMFCD3DApp::Run()
000126{
000127MSG msg;
000128::ZeroMemory(&msg, sizeof(MSG));
000129
000130static float lastTime = (float)timeGetTime();
000131
000132while(msg.message != WM_QUIT)
000133{
000134if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
000135{
000136::TranslateMessage(&msg);
000137::DispatchMessage(&msg);
000138}
000139else
000140{
000141float currTime = (float)timeGetTime();
000142float timeDelta = (currTime - lastTime)*0.001f;
000143lastTime = currTime;
000144
000145((CMainFrame*)m_pMainWnd)->Render(timeDelta);
000146}
000147 }
000148return CWinApp::Run();
000149}
000001// MainFrm.cpp : CMainFrame 类的实现
000002//
000003
000004#include "stdafx.h"
000005#include "MFCD3D.h"
000006
000007#include "MainFrm.h"
000008
000009#ifdef _DEBUG
000010#define new DEBUG_NEW
000011#endif
000012
000013const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_TEX1;
000014
000015// CMainFrame
000016
000017IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
000018
000019BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
000020ON_WM_CREATE()
000021ON_WM_SETFOCUS()
000022ON_WM_DESTROY()
000023END_MESSAGE_MAP()
000024
000025
000026// CMainFrame 构造/析构
000027
000028CMainFrame::CMainFrame()
000029: m_d3dDevice(NULL)
000030 ,m_pVB(NULL)
000031 , m_pIB(NULL)
000032 , m_pTex(NULL)
000033{
000034// TODO: 在此添加成员初始化代码
000035}
000036
000037CMainFrame::~CMainFrame()
000038{
000039}
000040
000041
000042int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
000043{
000044if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
000045return -1;
000046// 创建一个视图以占用框架的工作区
000047if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
000048CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
000049{
000050TRACE0("未能创建视图窗口/n");
000051return -1;
000052}
000053
000054if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
000055| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
000056!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
000057{
000058TRACE0("未能创建工具栏/n");
000059return -1; // 未能创建
000060}
000061// TODO: 如果不需要工具栏可停靠,则删除这三行
000062m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
000063EnableDocking(CBRS_ALIGN_ANY);
000064DockControlBar(&m_wndToolBar);
000065
000066return 0;
000067}
000068
000069BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
000070{
000071if( !CFrameWnd::PreCreateWindow(cs) )
000072return FALSE;
000073// TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或
000074// 样式
000075
000076cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
000077 | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
000078
000079cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
000080cs.lpszClass = AfxRegisterWndClass(0);
000081return TRUE;
000082}
000083
000084
000085// CMainFrame 诊断
000086
000087#ifdef _DEBUG
000088void CMainFrame::AssertValid() const
000089{
000090CFrameWnd::AssertValid();
000091}
000092
000093void CMainFrame::Dump(CDumpContext& dc) const
000094{
000095CFrameWnd::Dump(dc);
000096}
000097
000098#endif //_DEBUG
000099
000100
000101// CMainFrame 消息处理程序
000102
000103void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/)
000104{
000105// 将焦点前移到视图窗口
000106m_wndView.SetFocus();
000107}
000108
000109BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
000110{
000111// 让视图第一次尝试该命令
000112if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
000113return TRUE;
000114
000115// 否则,执行默认处理
000116return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
000117}
000118
000119// 初始化D3D
000120BOOL CMainFrame::InitD3D(void)
000121{
000122ASSERT(IsWindow(m_wndView.m_hWnd));
000123// 初始化Direct3D9
000124// Step1.获得IDirect3D9接口
000125IDirect3D9* _d3d9;
000126_d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
000127if(!_d3d9)
000128{
000129::AfxMessageBox(_T("Get Interface of Direct3D Failed!") , MB_ICONSTOP);
000130return FALSE;
000131}
000132// Step2.检查显卡能力
000133D3DCAPS9 caps;
000134_d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT ,
000135D3DDEVTYPE_HAL ,
000136&caps);
000137int vp = 0;
000138if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
000139vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
000140else
000141vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
000142// Step3.填充D3DPRESENT_PARAMETERS
000143D3DPRESENT_PARAMETERS d3dpp;
000144CRect rect;
000145GetClientRect(&rect);
000146ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
000147d3dpp.BackBufferWidth = rect.Width();
000148d3dpp.BackBufferHeight = rect.Height();
000149d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
000150d3dpp.BackBufferCount = 1;
000151d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
000152d3dpp.MultiSampleQuality = 0;
000153d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
000154d3dpp.hDeviceWindow = m_wndView.m_hWnd;
000155d3dpp.Windowed = true;// 一定要为true
000156d3dpp.EnableAutoDepthStencil = true;
000157d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
000158d3dpp.Flags = 0;
000159d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
000160d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
000161
000162// Step4.创建Direct3D设备
000163HRESULT hr;
000164hr = _d3d9->CreateDevice(D3DADAPTER_DEFAULT ,
000165D3DDEVTYPE_HAL ,
000166m_wndView.m_hWnd ,
000167vp ,
000168&d3dpp ,
000169&m_d3dDevice);
000170if(FAILED(hr))
000171{
000172switch(hr)
000173{
000174case D3DERR_DEVICELOST:
000175AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_DEVICELOST>") , MB_ICONSTOP);
000176break;
000177case D3DERR_INVALIDCALL:
000178AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_INVALIDCALL>") , MB_ICONSTOP);
000179break;
000180case D3DERR_NOTAVAILABLE:
000181AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_NOTAVAILABLE>") , MB_ICONSTOP);
000182break;
000183case D3DERR_OUTOFVIDEOMEMORY:
000184AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_OUTOFVIDEOMEMORY>") , MB_ICONSTOP);
000185break;
000186}
000187_d3d9->Release();
000188return FALSE;
000189}
000190_d3d9->Release();
000191// Direct3D9初始化完成
000192// 装载资源
000193Setup();
000194return TRUE;
000195}
000196
000197// 装载资源
000198BOOL CMainFrame::Setup(void)
000199{
000200// 创建顶点缓冲区和索引缓冲
000201m_d3dDevice->CreateVertexBuffer(36 * sizeof(Vertex) ,
000202D3DUSAGE_WRITEONLY ,
000203Vertex::FVF ,
000204D3DPOOL_MANAGED ,
000205&m_pVB ,
0002060);
000207// 填充顶点缓冲区
000208Vertex* pVertices;
000209m_pVB->Lock(0 , 0 , (void**)&pVertices , 0);
000210
000211// 前面
000212pVertices[0] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 0.0f);
000213pVertices[1] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000214pVertices[2] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000215pVertices[3] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 0.0f);
000216pVertices[4] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000217pVertices[5] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000218// 后面
000219pVertices[6] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000220pVertices[7] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000221pVertices[8] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 1.0f);
000222pVertices[9] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000223pVertices[10] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 1.0f);
000224pVertices[11] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000225// 上面
000226pVertices[12] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000227pVertices[13] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000228pVertices[14] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 1.0f);
000229pVertices[15] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000230pVertices[16] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 1.0f);
000231pVertices[17] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 1.0f);
000232// 下面
000233pVertices[18] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 0.0f);
000234pVertices[19] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 0.0f);
000235pVertices[20] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000236pVertices[21] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 0.0f);
000237pVertices[22] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000238pVertices[23] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000239// 左面
000240pVertices[24] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000241pVertices[25] = Vertex(-1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000242pVertices[26] = Vertex(-1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000243pVertices[27] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000244pVertices[28] = Vertex(-1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000245pVertices[29] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000246// 右面
000247pVertices[30] = Vertex(1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000248pVertices[31] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000249pVertices[32] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000250pVertices[33] = Vertex(1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000251pVertices[34] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000252pVertices[35] = Vertex(1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000253
000254
000255m_pVB->Unlock();
000256
000257// 创建纹理
000258D3DXCreateTextureFromFile(m_d3dDevice , _T("bbq.jpg") , &m_pTex);
000259m_d3dDevice->SetTexture(0 , m_pTex);
000260
000261m_d3dDevice->SetSamplerState(0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR);
000262m_d3dDevice->SetSamplerState(0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR);
000263m_d3dDevice->SetSamplerState(0 , D3DSAMP_MIPFILTER , D3DTEXF_POINT);
000264// 摄像机位置
000265D3DXVECTOR3 pos(0.0f , 0.0f , -5.0f);
000266D3DXVECTOR3 tag(0.0f , 0.0f , 0.0f);
000267D3DXVECTOR3 up(0.0f , 1.0f , 0.0f);
000268D3DXMATRIX v;
000269D3DXMatrixLookAtLH(&v , &pos , &tag , &up);
000270m_d3dDevice->SetTransform(D3DTS_VIEW , &v);
000271
000272// 设置投影矩阵
000273D3DXMATRIX proj;
000274CRect rect;
000275GetClientRect(&rect);
000276D3DXMatrixPerspectiveFovLH(&proj , D3DX_PI * 0.5f ,
000277(float)rect.Width()/(float)rect.Height() ,
0002781.0f ,
0002791000.0f);
000280m_d3dDevice->SetTransform(D3DTS_PROJECTION , &proj);
000281
000282// 设置渲染状态
000283m_d3dDevice->SetRenderState(D3DRS_LIGHTING , false);
000284m_d3dDevice->SetRenderState(D3DRS_CULLMODE , D3DCULL_NONE);
000285
000286return TRUE;
000287}
000288
000289// 渲染
000290void CMainFrame::Render(float timeDelta)
000291{
000292if(m_d3dDevice) // Only use Device methods if we have a valid device.
000293{
000294// 旋转正方体
000295D3DXMATRIX Rx , Ry;
000296// 在x方向旋转45度
000297D3DXMatrixRotationX(&Rx , 3.14f / 4.0f);
000298// 每一帧增加y
000299static float y = 0.0f;
000300D3DXMatrixRotationY(&Ry , y);
000301y += timeDelta;
000302// 当绕y轴旋转的角度达到360度时,置y为0
000303if(y >= 6.28f) y = 0.0f;
000304// 组合两个方向上的旋转
000305D3DXMATRIX p = Rx * Ry;
000306m_d3dDevice->SetTransform(D3DTS_WORLD , &p);
000307
000308// 绘制场景
000309m_d3dDevice->Clear(0 , 0 , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 0x000000ff , 1.0f , 0);
000310// 开始
000311m_d3dDevice->BeginScene();
000312{
000313m_d3dDevice->SetStreamSource(0 , m_pVB , 0 , sizeof(Vertex));
000314m_d3dDevice->SetFVF(Vertex::FVF);
000315m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST , 0 , 12);
000316}
000317m_d3dDevice->EndScene();
000318// 结束
000319m_d3dDevice->Present(0 , 0 , 0 , 0);
000320}
000321}
000322
000323// 清除资源
000324void CMainFrame::CleanUp(void)
000325{
000326m_pVB->Release();
000327m_pTex->Release();
000328}
000329
000330void CMainFrame::OnDestroy()
000331{
000332CFrameWnd::OnDestroy();
000333
000334CleanUp();
000335
000336m_d3dDevice->Release();
000337}
000002//
000003
000004#include "stdafx.h"
000005#include "MFCD3D.h"
000006
000007#include "MainFrm.h"
000008
000009#ifdef _DEBUG
000010#define new DEBUG_NEW
000011#endif
000012
000013const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_TEX1;
000014
000015// CMainFrame
000016
000017IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
000018
000019BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
000020ON_WM_CREATE()
000021ON_WM_SETFOCUS()
000022ON_WM_DESTROY()
000023END_MESSAGE_MAP()
000024
000025
000026// CMainFrame 构造/析构
000027
000028CMainFrame::CMainFrame()
000029: m_d3dDevice(NULL)
000030 ,m_pVB(NULL)
000031 , m_pIB(NULL)
000032 , m_pTex(NULL)
000033{
000034// TODO: 在此添加成员初始化代码
000035}
000036
000037CMainFrame::~CMainFrame()
000038{
000039}
000040
000041
000042int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
000043{
000044if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
000045return -1;
000046// 创建一个视图以占用框架的工作区
000047if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
000048CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
000049{
000050TRACE0("未能创建视图窗口/n");
000051return -1;
000052}
000053
000054if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
000055| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
000056!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
000057{
000058TRACE0("未能创建工具栏/n");
000059return -1; // 未能创建
000060}
000061// TODO: 如果不需要工具栏可停靠,则删除这三行
000062m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
000063EnableDocking(CBRS_ALIGN_ANY);
000064DockControlBar(&m_wndToolBar);
000065
000066return 0;
000067}
000068
000069BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
000070{
000071if( !CFrameWnd::PreCreateWindow(cs) )
000072return FALSE;
000073// TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或
000074// 样式
000075
000076cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
000077 | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
000078
000079cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
000080cs.lpszClass = AfxRegisterWndClass(0);
000081return TRUE;
000082}
000083
000084
000085// CMainFrame 诊断
000086
000087#ifdef _DEBUG
000088void CMainFrame::AssertValid() const
000089{
000090CFrameWnd::AssertValid();
000091}
000092
000093void CMainFrame::Dump(CDumpContext& dc) const
000094{
000095CFrameWnd::Dump(dc);
000096}
000097
000098#endif //_DEBUG
000099
000100
000101// CMainFrame 消息处理程序
000102
000103void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/)
000104{
000105// 将焦点前移到视图窗口
000106m_wndView.SetFocus();
000107}
000108
000109BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
000110{
000111// 让视图第一次尝试该命令
000112if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
000113return TRUE;
000114
000115// 否则,执行默认处理
000116return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
000117}
000118
000119// 初始化D3D
000120BOOL CMainFrame::InitD3D(void)
000121{
000122ASSERT(IsWindow(m_wndView.m_hWnd));
000123// 初始化Direct3D9
000124// Step1.获得IDirect3D9接口
000125IDirect3D9* _d3d9;
000126_d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
000127if(!_d3d9)
000128{
000129::AfxMessageBox(_T("Get Interface of Direct3D Failed!") , MB_ICONSTOP);
000130return FALSE;
000131}
000132// Step2.检查显卡能力
000133D3DCAPS9 caps;
000134_d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT ,
000135D3DDEVTYPE_HAL ,
000136&caps);
000137int vp = 0;
000138if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
000139vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
000140else
000141vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
000142// Step3.填充D3DPRESENT_PARAMETERS
000143D3DPRESENT_PARAMETERS d3dpp;
000144CRect rect;
000145GetClientRect(&rect);
000146ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
000147d3dpp.BackBufferWidth = rect.Width();
000148d3dpp.BackBufferHeight = rect.Height();
000149d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
000150d3dpp.BackBufferCount = 1;
000151d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
000152d3dpp.MultiSampleQuality = 0;
000153d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
000154d3dpp.hDeviceWindow = m_wndView.m_hWnd;
000155d3dpp.Windowed = true;// 一定要为true
000156d3dpp.EnableAutoDepthStencil = true;
000157d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
000158d3dpp.Flags = 0;
000159d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
000160d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
000161
000162// Step4.创建Direct3D设备
000163HRESULT hr;
000164hr = _d3d9->CreateDevice(D3DADAPTER_DEFAULT ,
000165D3DDEVTYPE_HAL ,
000166m_wndView.m_hWnd ,
000167vp ,
000168&d3dpp ,
000169&m_d3dDevice);
000170if(FAILED(hr))
000171{
000172switch(hr)
000173{
000174case D3DERR_DEVICELOST:
000175AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_DEVICELOST>") , MB_ICONSTOP);
000176break;
000177case D3DERR_INVALIDCALL:
000178AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_INVALIDCALL>") , MB_ICONSTOP);
000179break;
000180case D3DERR_NOTAVAILABLE:
000181AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_NOTAVAILABLE>") , MB_ICONSTOP);
000182break;
000183case D3DERR_OUTOFVIDEOMEMORY:
000184AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_OUTOFVIDEOMEMORY>") , MB_ICONSTOP);
000185break;
000186}
000187_d3d9->Release();
000188return FALSE;
000189}
000190_d3d9->Release();
000191// Direct3D9初始化完成
000192// 装载资源
000193Setup();
000194return TRUE;
000195}
000196
000197// 装载资源
000198BOOL CMainFrame::Setup(void)
000199{
000200// 创建顶点缓冲区和索引缓冲
000201m_d3dDevice->CreateVertexBuffer(36 * sizeof(Vertex) ,
000202D3DUSAGE_WRITEONLY ,
000203Vertex::FVF ,
000204D3DPOOL_MANAGED ,
000205&m_pVB ,
0002060);
000207// 填充顶点缓冲区
000208Vertex* pVertices;
000209m_pVB->Lock(0 , 0 , (void**)&pVertices , 0);
000210
000211// 前面
000212pVertices[0] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 0.0f);
000213pVertices[1] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000214pVertices[2] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000215pVertices[3] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 0.0f);
000216pVertices[4] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000217pVertices[5] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000218// 后面
000219pVertices[6] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000220pVertices[7] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000221pVertices[8] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 1.0f);
000222pVertices[9] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000223pVertices[10] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 1.0f);
000224pVertices[11] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000225// 上面
000226pVertices[12] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000227pVertices[13] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000228pVertices[14] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 1.0f);
000229pVertices[15] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000230pVertices[16] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 1.0f);
000231pVertices[17] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 1.0f);
000232// 下面
000233pVertices[18] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 0.0f);
000234pVertices[19] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 0.0f);
000235pVertices[20] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000236pVertices[21] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 0.0f);
000237pVertices[22] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000238pVertices[23] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000239// 左面
000240pVertices[24] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000241pVertices[25] = Vertex(-1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000242pVertices[26] = Vertex(-1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000243pVertices[27] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000244pVertices[28] = Vertex(-1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000245pVertices[29] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000246// 右面
000247pVertices[30] = Vertex(1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000248pVertices[31] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000249pVertices[32] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000250pVertices[33] = Vertex(1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000251pVertices[34] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000252pVertices[35] = Vertex(1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000253
000254
000255m_pVB->Unlock();
000256
000257// 创建纹理
000258D3DXCreateTextureFromFile(m_d3dDevice , _T("bbq.jpg") , &m_pTex);
000259m_d3dDevice->SetTexture(0 , m_pTex);
000260
000261m_d3dDevice->SetSamplerState(0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR);
000262m_d3dDevice->SetSamplerState(0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR);
000263m_d3dDevice->SetSamplerState(0 , D3DSAMP_MIPFILTER , D3DTEXF_POINT);
000264// 摄像机位置
000265D3DXVECTOR3 pos(0.0f , 0.0f , -5.0f);
000266D3DXVECTOR3 tag(0.0f , 0.0f , 0.0f);
000267D3DXVECTOR3 up(0.0f , 1.0f , 0.0f);
000268D3DXMATRIX v;
000269D3DXMatrixLookAtLH(&v , &pos , &tag , &up);
000270m_d3dDevice->SetTransform(D3DTS_VIEW , &v);
000271
000272// 设置投影矩阵
000273D3DXMATRIX proj;
000274CRect rect;
000275GetClientRect(&rect);
000276D3DXMatrixPerspectiveFovLH(&proj , D3DX_PI * 0.5f ,
000277(float)rect.Width()/(float)rect.Height() ,
0002781.0f ,
0002791000.0f);
000280m_d3dDevice->SetTransform(D3DTS_PROJECTION , &proj);
000281
000282// 设置渲染状态
000283m_d3dDevice->SetRenderState(D3DRS_LIGHTING , false);
000284m_d3dDevice->SetRenderState(D3DRS_CULLMODE , D3DCULL_NONE);
000285
000286return TRUE;
000287}
000288
000289// 渲染
000290void CMainFrame::Render(float timeDelta)
000291{
000292if(m_d3dDevice) // Only use Device methods if we have a valid device.
000293{
000294// 旋转正方体
000295D3DXMATRIX Rx , Ry;
000296// 在x方向旋转45度
000297D3DXMatrixRotationX(&Rx , 3.14f / 4.0f);
000298// 每一帧增加y
000299static float y = 0.0f;
000300D3DXMatrixRotationY(&Ry , y);
000301y += timeDelta;
000302// 当绕y轴旋转的角度达到360度时,置y为0
000303if(y >= 6.28f) y = 0.0f;
000304// 组合两个方向上的旋转
000305D3DXMATRIX p = Rx * Ry;
000306m_d3dDevice->SetTransform(D3DTS_WORLD , &p);
000307
000308// 绘制场景
000309m_d3dDevice->Clear(0 , 0 , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 0x000000ff , 1.0f , 0);
000310// 开始
000311m_d3dDevice->BeginScene();
000312{
000313m_d3dDevice->SetStreamSource(0 , m_pVB , 0 , sizeof(Vertex));
000314m_d3dDevice->SetFVF(Vertex::FVF);
000315m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST , 0 , 12);
000316}
000317m_d3dDevice->EndScene();
000318// 结束
000319m_d3dDevice->Present(0 , 0 , 0 , 0);
000320}
000321}
000322
000323// 清除资源
000324void CMainFrame::CleanUp(void)
000325{
000326m_pVB->Release();
000327m_pTex->Release();
000328}
000329
000330void CMainFrame::OnDestroy()
000331{
000332CFrameWnd::OnDestroy();
000333
000334CleanUp();
000335
000336m_d3dDevice->Release();
000337}
效果图:
[Groov0V]
__________________________
[1] 这里以Direct3D 9.0为例。
[2]该参数表示是否全屏(仅在Win32 SDK框架中有效)。
[2]该参数表示是否全屏(仅在Win32 SDK框架中有效)。
本文地址:http://www.45fan.com/a/question/68584.html