【原创】《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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197