【原创】《DirectX 9 3D 图形程序设计》 Tutorial 02 创建顶点缓冲区容易犯错的地方
13行,#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)是使用变换过的顶点格式,意思是在执行渲染流水线的过程中,不作顶点变换。换言之,可以直接用屏幕象素的单位大小来定义顶点的坐标。再换言之,就是说用这种顶点格式,可以简单的实现Overlay(不知道怎么翻译这个单词)
1
#include
<
D3DX9.h
>
2 #include < string >
3 typedef std:: string String;
4 #define SAFE_RELEASE(o) {if(o){o->Release();o = 0;}}
5
6
7 LPDIRECT3D9 g_pD3D = 0 ; // D3D Driver
8 LPDIRECT3DDEVICE9 g_pd3dDevice = 0 ; // D3D 设备
9 D3DCAPS9 g_Caps = {(D3DDEVTYPE) 0 } ; // D3D 的帽子
10 LPDIRECT3DVERTEXBUFFER9 g_pVB = 0 ; // 顶点缓冲区
11
12 // 顶点定义,使用变换过的顶点坐标格式
13 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
14 struct CUSTOMVERTEX
15 {
16 D3DXVECTOR4 position;
17 D3DCOLOR color;
18 } ;
19
20 // 错误记录
21 void D3DErr(String strMsg)
22 {
23 MessageBox( 0 , strMsg.c_str() , " 错误 " , MB_OK);
24 }
25
26 // 初始化顶点缓冲区
27 HRESULT InitVB()
28 {
29 // 创建顶点缓冲区
30 if (FAILED(g_pd3dDevice -> CreateVertexBuffer( 3 * sizeof (CUSTOMVERTEX) , 0 , D3DFVF_CUSTOMVERTEX , D3DPOOL_DEFAULT , & g_pVB , 0 )))
31 return E_FAIL;
32
33 CUSTOMVERTEX * pVertecies;
34 // 锁定缓冲区
35 if (SUCCEEDED(g_pVB -> Lock( 0 , 3 * sizeof (CUSTOMVERTEX) , ( void ** ) & pVertecies , 0 )))
36 {
37 pVertecies[ 0 ].position = D3DXVECTOR4( 0 , 0 , 0.5 , 1 );
38 pVertecies[ 1 ].position = D3DXVECTOR4( 512 , 0 , 0.5 , 1 );
39 pVertecies[ 2 ].position = D3DXVECTOR4( 0 , 512 , 0.5 , 1 );
40
41 pVertecies[ 0 ].color = D3DCOLOR_XRGB( 255 , 0 , 0 );
42 pVertecies[ 1 ].color = D3DCOLOR_XRGB( 0 , 255 , 0 );
43 pVertecies[ 2 ].color = D3DCOLOR_XRGB( 0 , 0 , 255 );
44
45 g_pVB -> Unlock();
46 }
47 else
48 {
49 return E_FAIL;
50 }
51 return S_OK;
52 }
53
54 // 初始化 D3D 设备
55 HRESULT InitD3D(HWND hWnd)
56 {
57 // 创建 D3D Driver
58 if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
59 {
60 D3DErr( " 无法创建Direct3D9设备 " );
61 return E_FAIL;
62 }
63 // 获取当前显示模式
64 D3DDISPLAYMODE d3ddm;
65 if (FAILED(g_pD3D -> GetAdapterDisplayMode(D3DADAPTER_DEFAULT , & d3ddm)))
66 {
67 D3DErr( " 无法获取D3D显示器模式 " );
68 return E_FAIL;
69 }
70
71 // 获取窗口的大小
72 RECT rect;
73 GetClientRect(hWnd , & rect);
74
75 // 填充参数
76 D3DPRESENT_PARAMETERS d3dpp;
77 memset( & d3dpp , 0 , sizeof (d3dpp));
78 d3dpp.BackBufferFormat = d3ddm.Format;
79 d3dpp.BackBufferWidth = rect.right - rect.left;
80 d3dpp.BackBufferHeight = rect.bottom - rect.top;
81 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
82 d3dpp.Windowed = true ;
83
84 // 获取帽子
85 if (FAILED(g_pD3D -> GetDeviceCaps(D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL , & g_Caps)))
86 {
87 D3DErr( " 获取D3D 帽子时发生错误 " );
88 return E_FAIL;
89 }
90
91 // 创建D3D设备
92 if (FAILED(g_pD3D -> CreateDevice(D3DADAPTER_DEFAULT
93 , D3DDEVTYPE_HAL
94 , hWnd
95 // 检查是否支持硬件顶点处理
96 , g_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING
97 , & d3dpp
98 , & g_pd3dDevice
99 )
100 ))
101 {
102 D3DErr( " 创建D3D设备时发生错误 " );
103 return E_FAIL;
104 }
105
106 // 创建顶点缓冲区
107 if (FAILED(InitVB()))
108 return E_FAIL;
109 return S_OK;
110 }
111
112 // 清空所有占用的资源
113 void CleanUp()
114 {
115 SAFE_RELEASE(g_pVB);
116 SAFE_RELEASE(g_pd3dDevice);
117 SAFE_RELEASE(g_pD3D);
118 }
119
120 // 渲染场景
121 void Render()
122 {
123 if (g_pd3dDevice)
124 {
125 // 清空场景
126 g_pd3dDevice -> Clear( 0 , 0 , D3DCLEAR_TARGET , D3DCOLOR_XRGB( 0 , 0 , 255 ) , 1 , 0 );
127 // 开始渲染
128 if (SUCCEEDED(g_pd3dDevice -> BeginScene()))
129 {
130 g_pd3dDevice -> SetRenderState(D3DRS_LIGHTING , FALSE);
131 g_pd3dDevice -> SetStreamSource( 0 , g_pVB , 0 , sizeof (CUSTOMVERTEX));
132 g_pd3dDevice -> SetFVF(D3DFVF_CUSTOMVERTEX);
133 g_pd3dDevice -> DrawPrimitive(D3DPT_TRIANGLELIST , 0 , 1 );
134 g_pd3dDevice -> EndScene();
135 }
136 // 显示
137 g_pd3dDevice -> Present( 0 , 0 , 0 , 0 );
138 }
139 }
140
141 // 消息处理
142 LRESULT WINAPI MsgProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
143 {
144 switch (message)
145 {
146 case WM_DESTROY:
147 CleanUp();
148 PostQuitMessage( 0 );
149 break ;
150 }
151 return ::DefWindowProc(hWnd, message , wParam , lParam);
152 }
153
154 // Windows 入口
155 int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
156 {
157 WNDCLASS wndClass;
158 memset( & wndClass , 0 , sizeof (wndClass));
159 wndClass.hInstance = hInstance;
160 wndClass.lpszClassName = " Tutorial02 " ;
161 wndClass.lpfnWndProc = MsgProc;
162 RegisterClass( & wndClass);
163
164 // 创建窗口
165 HWND hWnd = CreateWindow( " Tutorial02 " , " Tutorial02 Vertex Buffer "
166 , WS_OVERLAPPEDWINDOW , 0 , 0 , 512 , 512 , GetDesktopWindow()
167 , 0 , wndClass.hInstance , 0 );
168 // 显示窗口
169 ShowWindow(hWnd , SW_SHOWDEFAULT);
170 UpdateWindow(hWnd);
171
172 // 初始化 D3D 设备
173 if (SUCCEEDED(InitD3D(hWnd)))
174 {
175 // 消息处理循环
176 MSG msg;
177 memset( & msg , 0 , sizeof (msg));
178 while (msg.message != WM_QUIT)
179 {
180 if (PeekMessage( & msg , 0 , 0 , 0 , PM_REMOVE))
181 {
182 TranslateMessage( & msg);
183 DispatchMessage( & msg);
184 }
185 else
186 {
187 Render();
188 }
189 }
190 }
191 // 清空场景
192 CleanUp();
193
194 UnregisterClass( " Tutorial02 " , wndClass.hInstance);
195
196 return 0 ;
197 }
2 #include < string >
3 typedef std:: string String;
4 #define SAFE_RELEASE(o) {if(o){o->Release();o = 0;}}
5
6
7 LPDIRECT3D9 g_pD3D = 0 ; // D3D Driver
8 LPDIRECT3DDEVICE9 g_pd3dDevice = 0 ; // D3D 设备
9 D3DCAPS9 g_Caps = {(D3DDEVTYPE) 0 } ; // D3D 的帽子
10 LPDIRECT3DVERTEXBUFFER9 g_pVB = 0 ; // 顶点缓冲区
11
12 // 顶点定义,使用变换过的顶点坐标格式
13 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
14 struct CUSTOMVERTEX
15 {
16 D3DXVECTOR4 position;
17 D3DCOLOR color;
18 } ;
19
20 // 错误记录
21 void D3DErr(String strMsg)
22 {
23 MessageBox( 0 , strMsg.c_str() , " 错误 " , MB_OK);
24 }
25
26 // 初始化顶点缓冲区
27 HRESULT InitVB()
28 {
29 // 创建顶点缓冲区
30 if (FAILED(g_pd3dDevice -> CreateVertexBuffer( 3 * sizeof (CUSTOMVERTEX) , 0 , D3DFVF_CUSTOMVERTEX , D3DPOOL_DEFAULT , & g_pVB , 0 )))
31 return E_FAIL;
32
33 CUSTOMVERTEX * pVertecies;
34 // 锁定缓冲区
35 if (SUCCEEDED(g_pVB -> Lock( 0 , 3 * sizeof (CUSTOMVERTEX) , ( void ** ) & pVertecies , 0 )))
36 {
37 pVertecies[ 0 ].position = D3DXVECTOR4( 0 , 0 , 0.5 , 1 );
38 pVertecies[ 1 ].position = D3DXVECTOR4( 512 , 0 , 0.5 , 1 );
39 pVertecies[ 2 ].position = D3DXVECTOR4( 0 , 512 , 0.5 , 1 );
40
41 pVertecies[ 0 ].color = D3DCOLOR_XRGB( 255 , 0 , 0 );
42 pVertecies[ 1 ].color = D3DCOLOR_XRGB( 0 , 255 , 0 );
43 pVertecies[ 2 ].color = D3DCOLOR_XRGB( 0 , 0 , 255 );
44
45 g_pVB -> Unlock();
46 }
47 else
48 {
49 return E_FAIL;
50 }
51 return S_OK;
52 }
53
54 // 初始化 D3D 设备
55 HRESULT InitD3D(HWND hWnd)
56 {
57 // 创建 D3D Driver
58 if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
59 {
60 D3DErr( " 无法创建Direct3D9设备 " );
61 return E_FAIL;
62 }
63 // 获取当前显示模式
64 D3DDISPLAYMODE d3ddm;
65 if (FAILED(g_pD3D -> GetAdapterDisplayMode(D3DADAPTER_DEFAULT , & d3ddm)))
66 {
67 D3DErr( " 无法获取D3D显示器模式 " );
68 return E_FAIL;
69 }
70
71 // 获取窗口的大小
72 RECT rect;
73 GetClientRect(hWnd , & rect);
74
75 // 填充参数
76 D3DPRESENT_PARAMETERS d3dpp;
77 memset( & d3dpp , 0 , sizeof (d3dpp));
78 d3dpp.BackBufferFormat = d3ddm.Format;
79 d3dpp.BackBufferWidth = rect.right - rect.left;
80 d3dpp.BackBufferHeight = rect.bottom - rect.top;
81 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
82 d3dpp.Windowed = true ;
83
84 // 获取帽子
85 if (FAILED(g_pD3D -> GetDeviceCaps(D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL , & g_Caps)))
86 {
87 D3DErr( " 获取D3D 帽子时发生错误 " );
88 return E_FAIL;
89 }
90
91 // 创建D3D设备
92 if (FAILED(g_pD3D -> CreateDevice(D3DADAPTER_DEFAULT
93 , D3DDEVTYPE_HAL
94 , hWnd
95 // 检查是否支持硬件顶点处理
96 , g_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING
97 , & d3dpp
98 , & g_pd3dDevice
99 )
100 ))
101 {
102 D3DErr( " 创建D3D设备时发生错误 " );
103 return E_FAIL;
104 }
105
106 // 创建顶点缓冲区
107 if (FAILED(InitVB()))
108 return E_FAIL;
109 return S_OK;
110 }
111
112 // 清空所有占用的资源
113 void CleanUp()
114 {
115 SAFE_RELEASE(g_pVB);
116 SAFE_RELEASE(g_pd3dDevice);
117 SAFE_RELEASE(g_pD3D);
118 }
119
120 // 渲染场景
121 void Render()
122 {
123 if (g_pd3dDevice)
124 {
125 // 清空场景
126 g_pd3dDevice -> Clear( 0 , 0 , D3DCLEAR_TARGET , D3DCOLOR_XRGB( 0 , 0 , 255 ) , 1 , 0 );
127 // 开始渲染
128 if (SUCCEEDED(g_pd3dDevice -> BeginScene()))
129 {
130 g_pd3dDevice -> SetRenderState(D3DRS_LIGHTING , FALSE);
131 g_pd3dDevice -> SetStreamSource( 0 , g_pVB , 0 , sizeof (CUSTOMVERTEX));
132 g_pd3dDevice -> SetFVF(D3DFVF_CUSTOMVERTEX);
133 g_pd3dDevice -> DrawPrimitive(D3DPT_TRIANGLELIST , 0 , 1 );
134 g_pd3dDevice -> EndScene();
135 }
136 // 显示
137 g_pd3dDevice -> Present( 0 , 0 , 0 , 0 );
138 }
139 }
140
141 // 消息处理
142 LRESULT WINAPI MsgProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
143 {
144 switch (message)
145 {
146 case WM_DESTROY:
147 CleanUp();
148 PostQuitMessage( 0 );
149 break ;
150 }
151 return ::DefWindowProc(hWnd, message , wParam , lParam);
152 }
153
154 // Windows 入口
155 int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
156 {
157 WNDCLASS wndClass;
158 memset( & wndClass , 0 , sizeof (wndClass));
159 wndClass.hInstance = hInstance;
160 wndClass.lpszClassName = " Tutorial02 " ;
161 wndClass.lpfnWndProc = MsgProc;
162 RegisterClass( & wndClass);
163
164 // 创建窗口
165 HWND hWnd = CreateWindow( " Tutorial02 " , " Tutorial02 Vertex Buffer "
166 , WS_OVERLAPPEDWINDOW , 0 , 0 , 512 , 512 , GetDesktopWindow()
167 , 0 , wndClass.hInstance , 0 );
168 // 显示窗口
169 ShowWindow(hWnd , SW_SHOWDEFAULT);
170 UpdateWindow(hWnd);
171
172 // 初始化 D3D 设备
173 if (SUCCEEDED(InitD3D(hWnd)))
174 {
175 // 消息处理循环
176 MSG msg;
177 memset( & msg , 0 , sizeof (msg));
178 while (msg.message != WM_QUIT)
179 {
180 if (PeekMessage( & msg , 0 , 0 , 0 , PM_REMOVE))
181 {
182 TranslateMessage( & msg);
183 DispatchMessage( & msg);
184 }
185 else
186 {
187 Render();
188 }
189 }
190 }
191 // 清空场景
192 CleanUp();
193
194 UnregisterClass( " Tutorial02 " , wndClass.hInstance);
195
196 return 0 ;
197 }