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
LPDIRECT3DINDEXBUFFER9 g_pIB
=
0
;
//
索引缓冲区
12
13
//
顶点定义
14
#define
D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL )
15
struct
CUSTOMVERTEX
16
{
17
D3DXVECTOR3 position;
18
D3DXVECTOR3 normal;
19
}
;
20
21
//
错误记录
22
void
D3DErr(String strMsg)
23
{
24
MessageBox(
0
, strMsg.c_str() ,
"
错误
"
, MB_OK);
25
}
26
27
//
初始化顶点缓冲区
28
HRESULT InitVB()
29
{
30
//
创建顶点缓冲区
31
if
(FAILED(g_pd3dDevice
->
CreateVertexBuffer(
50
*
2
*
sizeof
(CUSTOMVERTEX) ,
0
, D3DFVF_CUSTOMVERTEX , D3DPOOL_DEFAULT ,
&
g_pVB ,
0
)))
32
return
E_FAIL;
33
34
CUSTOMVERTEX
*
pVertecies;
35
//
锁定缓冲区
36
if
(SUCCEEDED(g_pVB
->
Lock(
0
,
0
, (
void
**
)
&
pVertecies ,
0
)))
37
{
38
for
(
int
i
=
0
; i
<
100
; i
+=
2
)
39
{
40
float
theta
=
2
*
D3DX_PI
*
i
/
(
50
-
1
);
41
//
根据圆的方程 x = x' + r * sin(θ)
42
//
y = y' + r * cos(θ)
43
//
求解圆
44
pVertecies[i].position
=
D3DXVECTOR3(sinf(theta) ,
1
, cosf(theta));
45
pVertecies[i].normal
=
D3DXVECTOR3(sinf(theta) ,
0
, cosf(theta));
46
47
pVertecies[i
+
1
].position
=
D3DXVECTOR3(sinf(theta) ,
-
1
, cosf(theta));
48
pVertecies[i
+
1
].normal
=
D3DXVECTOR3(sinf(theta) ,
0
, cosf(theta));
49
50
}
51
g_pVB
->
Unlock();
52
}
53
else
54
{
55
return
E_FAIL;
56
}
57
return
S_OK;
58
}
59
60
//
初始化模型
61
HRESULT InitGeometry()
62
{
63
//
创建顶点缓冲区
64
if
(FAILED(InitVB()))
65
return
E_FAIL;
66
return
S_OK;
67
}
68
69
//
设置矩阵变换
70
void
SetTransform()
71
{
72
73
//
世界变换
74
D3DXMATRIX matWorld , matT1 , matT2 , matR;
75
D3DXMatrixIdentity(
&
matWorld);
76
DWORD dwTime
=
timeGetTime();
77
//
角度
78
float
fAngle
=
2
*
D3DX_PI
*
(dwTime
%
3000
)
/
3000.0f
;
79
80
//
平移到原点
81
D3DXMatrixTranslation(
&
matT1 ,
-
0.5
,
-
1
,
0
);
82
//
Z旋转
83
D3DXMatrixRotationZ(
&
matR , sin(fAngle));
84
//
移动到原来的位置
85
D3DXMatrixTranslation(
&
matT2 ,
0.5
/**/
/*
- 3 * (dwTime % 5000) / 5000.0f
*/
,
1
,
0
);
86
//
平移到原点再旋转
87
matWorld
=
matT1
*
matR;
88
//
平移回原来的位置
89
matWorld
*=
matT2;
90
91
92
//
放大缩小
93
D3DXMatrixScaling(
&
matWorld , abs(sin(
2
*
D3DX_PI
*
(dwTime
%
3000
)
/
3000.0f
)) , abs(sin(
2
*
D3DX_PI
*
(dwTime
%
3000
)
/
3000.0f
)) , abs(sin(
2
*
D3DX_PI
*
(dwTime
%
3000
)
/
3000.0f
)));
94
//
设置缩放点
95
matWorld._41
=
(
1.0f
-
matWorld._11)
*
0.5
;
//
x
96
matWorld._42
=
(
1.0f
-
matWorld._22)
*
0.5
;
//
y
97
matWorld._43
=
(
1.0f
-
matWorld._33)
*
0
;
//
z
98
99
100
//
设置世界矩阵
101
g_pd3dDevice
->
SetTransform(D3DTS_WORLD ,
&
matWorld);
102
//
Set up our view matrix. A view matrix can be defined given an eye point,
103
//
a point to lookat, and a direction for which way is up. Here, we set the
104
//
eye five units back along the z-axis and up three units, look at the
105
//
origin, and define "up" to be in the y-direction.
106
//
视口变换
107
D3DXMATRIX matView;
108
D3DXMatrixLookAtLH(
&
matView ,
&
D3DXVECTOR3(
0
,
3
,
-
5
)
109
,
&
D3DXVECTOR3(
0
,
0
,
0
)
110
,
&
D3DXVECTOR3(
0
,
1
,
0
));
111
g_pd3dDevice
->
SetTransform(D3DTS_VIEW ,
&
matView);
112
//
For the projection matrix, we set up a perspective transform (which
113
//
transforms geometry from 3D view space to 2D viewport space, with
114
//
a perspective divide making objects smaller in the distance). To build
115
//
a perpsective transform, we need the field of view (1/4 pi is common),
116
//
the aspect ratio, and the near and far clipping planes (which define at
117
//
what distances geometry should be no longer be rendered).
118
D3DXMATRIXA16 matProj;
119
D3DXMatrixPerspectiveFovLH(
&
matProj, D3DX_PI
/
4
,
1.0f
,
1.0f
,
100.0f
);
120
g_pd3dDevice
->
SetTransform( D3DTS_PROJECTION,
&
matProj );
121
}
122
123
//
设置灯光
124
void
SetupLight()
125
{
126
//
Set up a material. The material here just has the diffuse and ambient
127
//
colors set to yellow. Note that only one material can be used at a time.
128
//
set up lights
129
D3DXVECTOR3 vecDir;
130
//
创建一个平行光
131
D3DLIGHT9 light;
132
ZeroMemory(
&
light,
sizeof
(D3DLIGHT9) );
133
light.Type
=
D3DLIGHT_DIRECTIONAL;
//
平行光
134
light.Diffuse.r
=
0.0f
;
135
light.Diffuse.g
=
1.0f
;
//
红色
136
light.Diffuse.b
=
0.0f
;
137
vecDir
=
D3DXVECTOR3(
10
,
10
,
-
10
);
//
方向是从0,0,0指向10,10,-10
138
139
//
正规化向量,就是说把向量长度正规化成1,方向不变!好处是光照运算时的误差会降到最小(纯属我的理解,不知道正确与否)
140
D3DXVec3Normalize( (D3DXVECTOR3
*
)
&
light.Direction,
&
vecDir );
141
//
设置0号光照为此灯光参数
142
g_pd3dDevice
->
SetLight(
0
,
&
light );
143
144
//
开启0号光照
145
g_pd3dDevice
->
LightEnable(
0
, TRUE );
146
//
开启光照系统
147
g_pd3dDevice
->
SetRenderState( D3DRS_LIGHTING, TRUE );
148
149
D3DXVECTOR3 vecPos2;
150
//
一个点光源
151
D3DLIGHT9 light2;
152
ZeroMemory(
&
light2,
sizeof
(D3DLIGHT9) );
153
light2.Type
=
D3DLIGHT_POINT;
//
点光源
154
light2.Diffuse.r
=
0.9f
;
//
红色
155
light2.Diffuse.g
=
0.0f
;
156
light2.Diffuse.b
=
0.0f
;
157
158
//
位置,随着时间的推移,围绕Y轴周围的圆圈旋转,根据圆的方程来建立的sinf和cosf函数
159
light2.Position
=
D3DXVECTOR3(
10
*
sinf(timeGetTime()
/
350.0f
) ,
160
10
,
161
10
*
cosf(timeGetTime()
/
350.0f
) );
162
163
light2.Range
=
15
;
164
light2.Attenuation0
=
1.0f
;
165
g_pd3dDevice
->
SetLight(
1
,
&
light2 );
166
g_pd3dDevice
->
LightEnable(
1
, TRUE );
167
168
//
开启光照系统(纯属多余!开启一次就行了!)
169
g_pd3dDevice
->
SetRenderState( D3DRS_LIGHTING, TRUE );
170
171
//
最后,开启环境光
172
g_pd3dDevice
->
SetRenderState( D3DRS_AMBIENT,
0x00202020
);
173
174
D3DMATERIAL9 mtrl;
175
ZeroMemory(
&
mtrl,
sizeof
(D3DMATERIAL9) );
176
mtrl.Diffuse.r
=
mtrl.Ambient.r
=
1.0f
;
177
mtrl.Diffuse.g
=
mtrl.Ambient.g
=
1.0f
;
178
mtrl.Diffuse.b
=
mtrl.Ambient.b
=
0.0f
;
179
mtrl.Diffuse.a
=
mtrl.Ambient.a
=
1.0f
;
180
//
设置物体的材质
181
g_pd3dDevice
->
SetMaterial(
&
mtrl );
182
183
}
184
185
//
渲染场景
186
void
Render()
187
{
188
if
(g_pd3dDevice)
189
{
190
//
清空场景
191
g_pd3dDevice
->
Clear(
0
,
0
, D3DCLEAR_TARGET
|
D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(
0
,
0
,
0
) ,
1
,
0
);
192
//
开始渲染
193
if
(SUCCEEDED(g_pd3dDevice
->
BeginScene()))
194
{
195
SetTransform();
196
SetupLight();
197
g_pd3dDevice
->
SetRenderState(D3DRS_AMBIENT , D3DCOLOR_XRGB(
64
,
64
,
64
));
198
g_pd3dDevice
->
SetStreamSource(
0
, g_pVB ,
0
,
sizeof
(CUSTOMVERTEX));
199
g_pd3dDevice
->
SetFVF(D3DFVF_CUSTOMVERTEX);
200
g_pd3dDevice
->
DrawPrimitive(D3DPT_TRIANGLESTRIP ,
0
,
2
*
50
-
2
);
201
g_pd3dDevice
->
EndScene();
202
}
203
//
显示
204
g_pd3dDevice
->
Present(
0
,
0
,
0
,
0
);
205
}
206
}
207
208
//
初始化 D3D 设备
209
HRESULT InitD3D(HWND hWnd)
210
{
211
//
创建 D3D Driver
212
if
(NULL
==
(g_pD3D
=
Direct3DCreate9(D3D_SDK_VERSION)))
213
{
214
D3DErr(
"
无法创建Direct3D9设备
"
);
215
return
E_FAIL;
216
}
217
//
获取当前显示模式
218
D3DDISPLAYMODE d3ddm;
219
if
(FAILED(g_pD3D
->
GetAdapterDisplayMode(D3DADAPTER_DEFAULT ,
&
d3ddm)))
220
{
221
D3DErr(
"
无法获取D3D显示器模式
"
);
222
return
E_FAIL;
223
}
224
225
//
获取窗口的大小
226
RECT rect;
227
GetClientRect(hWnd ,
&
rect);
228
229
//
填充参数
230
D3DPRESENT_PARAMETERS d3dpp;
231
memset(
&
d3dpp ,
0
,
sizeof
(d3dpp));
232
d3dpp.BackBufferFormat
=
d3ddm.Format;
233
d3dpp.BackBufferWidth
=
rect.right
-
rect.left;
234
d3dpp.BackBufferHeight
=
rect.bottom
-
rect.top;
235
d3dpp.SwapEffect
=
D3DSWAPEFFECT_DISCARD;
236
d3dpp.Windowed
=
true
;
237
d3dpp.AutoDepthStencilFormat
=
D3DFMT_D16;
238
d3dpp.EnableAutoDepthStencil
=
TRUE;
239
240
//
获取帽子
241
if
(FAILED(g_pD3D
->
GetDeviceCaps(D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL ,
&
g_Caps)))
242
{
243
D3DErr(
"
获取D3D 帽子时发生错误
"
);
244
return
E_FAIL;
245
}
246
247
//
创建D3D设备
248
if
(FAILED(g_pD3D
->
CreateDevice(D3DADAPTER_DEFAULT
249
, D3DDEVTYPE_HAL
250
, hWnd
251
//
检查是否支持硬件顶点处理
252
, g_Caps.DevCaps
&
D3DDEVCAPS_HWTRANSFORMANDLIGHT
?
D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING
253
,
&
d3dpp
254
,
&
g_pd3dDevice
255
)
256
))
257
{
258
D3DErr(
"
创建D3D设备时发生错误
"
);
259
return
E_FAIL;
260
}
261
g_pd3dDevice
->
SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
262
g_pd3dDevice
->
SetRenderState( D3DRS_ZENABLE, TRUE );
263
264
if
(FAILED(InitGeometry()))
265
return
E_FAIL;
266
return
S_OK;
267
}
268
269
//
清空所有占用的资源
270
void
CleanUp()
271
{
272
SAFE_RELEASE(g_pIB);
273
SAFE_RELEASE(g_pVB);
274
SAFE_RELEASE(g_pd3dDevice);
275
SAFE_RELEASE(g_pD3D);
276
}
277
278
279
//
消息处理
280
LRESULT WINAPI MsgProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
281
{
282
switch
(message)
283
{
284
case
WM_DESTROY:
285
CleanUp();
286
PostQuitMessage(
0
);
287
break
;
288
}
289
return
::DefWindowProc(hWnd, message , wParam , lParam);
290
}
291
292
//
Windows 入口
293
int
WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN
int
nShowCmd )
294
{
295
WNDCLASS wndClass;
296
memset(
&
wndClass ,
0
,
sizeof
(wndClass));
297
wndClass.hInstance
=
hInstance;
298
wndClass.lpszClassName
=
"
Tutorial02
"
;
299
wndClass.lpfnWndProc
=
MsgProc;
300
RegisterClass(
&
wndClass);
301
302
//
创建窗口
303
HWND hWnd
=
CreateWindow(
"
Tutorial02
"
,
"
Tutorial02 Lighting
"
304
, WS_OVERLAPPEDWINDOW ,
0
,
0
,
512
,
512
, GetDesktopWindow()
305
,
0
, wndClass.hInstance ,
0
);
306
//
显示窗口
307
ShowWindow(hWnd , SW_SHOWDEFAULT);
308
UpdateWindow(hWnd);
309
310
//
初始化 D3D 设备
311
if
(SUCCEEDED(InitD3D(hWnd)))
312
{
313
//
消息处理循环
314
MSG msg;
315
memset(
&
msg ,
0
,
sizeof
(msg));
316
while
(msg.message
!=
WM_QUIT)
317
{
318
if
(PeekMessage(
&
msg ,
0
,
0
,
0
, PM_REMOVE))
319
{
320
TranslateMessage(
&
msg);
321
DispatchMessage(
&
msg);
322
}
323
else
324
{
325
Render();
326
}
327
}
328
}
329
//
清空场景
330
CleanUp();
331
332
UnregisterClass(
"
Tutorial02
"
, wndClass.hInstance);
333
334
return
0
;
335
}
|