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
LPDIRECT3DTEXTURE9 g_pTexture
=
0
;
//
贴图
13
14
//
顶点定义
15
#define
D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
16
struct
CUSTOMVERTEX
17
{
18
D3DXVECTOR3 position;
19
D3DCOLOR color;
20
float
u , v;
21
}
;
22
23
//
错误记录
24
void
D3DErr(String strMsg)
25
{
26
MessageBox(
0
, strMsg.c_str() ,
"
错误
"
, MB_OK);
27
}
28
29
//
初始化顶点缓冲区
30
HRESULT InitVB()
31
{
32
//
创建顶点缓冲区
33
if
(FAILED(g_pd3dDevice
->
CreateVertexBuffer(
4
*
sizeof
(CUSTOMVERTEX) ,
0
, D3DFVF_CUSTOMVERTEX , D3DPOOL_DEFAULT ,
&
g_pVB ,
0
)))
34
return
E_FAIL;
35
36
CUSTOMVERTEX
*
pVertecies;
37
//
锁定缓冲区
38
if
(SUCCEEDED(g_pVB
->
Lock(
0
,
0
, (
void
**
)
&
pVertecies ,
0
)))
39
{
40
pVertecies[
0
].position
=
D3DXVECTOR3(
-
1
,
1
,
0
);
41
pVertecies[
1
].position
=
D3DXVECTOR3(
-
1
,
-
1
,
0
);
42
pVertecies[
2
].position
=
D3DXVECTOR3(
1
,
1
,
0
);
43
pVertecies[
3
].position
=
D3DXVECTOR3(
1
,
-
1
,
0
);
44
45
pVertecies[
0
].u
=
0
;
46
pVertecies[
0
].v
=
0
;
47
48
pVertecies[
1
].u
=
0
;
49
pVertecies[
1
].v
=
1
;
50
51
pVertecies[
2
].u
=
1
;
52
pVertecies[
2
].v
=
0
;
53
54
pVertecies[
3
].u
=
1
;
55
pVertecies[
3
].v
=
1
;
56
57
pVertecies[
0
].color
=
0xFFFFFFFF
;
58
pVertecies[
1
].color
=
0xFFFFFFFF
;
59
pVertecies[
2
].color
=
0xFFFFFFFF
;
60
pVertecies[
3
].color
=
0xFFFFFFFF
;
61
g_pVB
->
Unlock();
62
}
63
else
64
{
65
return
E_FAIL;
66
}
67
68
//
载入纹理
69
if
(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice ,
"
..\\..\\Media\\BRICE.JPG
"
,
&
g_pTexture)))
70
{
71
D3DErr(
"
无法载入纹理Brice.jpg
"
);
72
return
E_FAIL;
73
}
74
return
S_OK;
75
}
76
77
//
初始化模型
78
HRESULT InitGeometry()
79
{
80
//
创建顶点缓冲区
81
if
(FAILED(InitVB()))
82
return
E_FAIL;
83
return
S_OK;
84
}
85
86
//
设置矩阵变换
87
void
SetTransform()
88
{
89
90
//
世界变换
91
D3DXMATRIX matWorld , matT1 , matT2 , matR;
92
D3DXMatrixIdentity(
&
matWorld);
93
//
设置世界矩阵
94
g_pd3dDevice
->
SetTransform(D3DTS_WORLD ,
&
matWorld);
95
//
Set up our view matrix. A view matrix can be defined given an eye point,
96
//
a point to lookat, and a direction for which way is up. Here, we set the
97
//
eye five units back along the z-axis and up three units, look at the
98
//
origin, and define "up" to be in the y-direction.
99
//
视口变换
100
D3DXMATRIX matView;
101
D3DXMatrixLookAtLH(
&
matView ,
&
D3DXVECTOR3(
0
,
0
,
-
5
)
102
,
&
D3DXVECTOR3(
0
,
0
,
0
)
103
,
&
D3DXVECTOR3(
0
,
1
,
0
));
104
g_pd3dDevice
->
SetTransform(D3DTS_VIEW ,
&
matView);
105
//
For the projection matrix, we set up a perspective transform (which
106
//
transforms geometry from 3D view space to 2D viewport space, with
107
//
a perspective divide making objects smaller in the distance). To build
108
//
a perpsective transform, we need the field of view (1/4 pi is common),
109
//
the aspect ratio, and the near and far clipping planes (which define at
110
//
what distances geometry should be no longer be rendered).
111
D3DXMATRIXA16 matProj;
112
//
这里我曾经犯了个大错!!把ZNear的参数传0进去了!这样会导致一个很严重的问题。。你试试就知道。但是我想不通为何会出现这个问题。。我笨啊
113
D3DXMatrixPerspectiveFovLH(
&
matProj, D3DX_PI
/
4
,
1.0f
,
1.0f
,
100.0f
);
114
g_pd3dDevice
->
SetTransform( D3DTS_PROJECTION,
&
matProj );
115
116
//
纹理坐标平移
117
D3DXMATRIXA16 matTexture;
118
D3DXMatrixIdentity(
&
matTexture);
119
//
要使用3*3矩阵来平移2D纹理,所以要设置31来平移。不懂为什么要设置31的话看看《计算机图形学》的2D变换那章
120
matTexture._31
=
timeGetTime()
%
3000
/
1500.0f
;
121
g_pd3dDevice
->
SetTransform(D3DTS_TEXTURE0 ,
&
matTexture);
122
123
}
124
125
//
渲染场景
126
void
Render()
127
{
128
if
(g_pd3dDevice)
129
{
130
//
清空场景
131
g_pd3dDevice
->
Clear(
0
,
0
, D3DCLEAR_TARGET
|
D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(
0
,
0
,
0
) ,
1
,
0
);
132
//
开始渲染
133
if
(SUCCEEDED(g_pd3dDevice
->
BeginScene()))
134
{
135
SetTransform();
136
g_pd3dDevice
->
SetTexture(
0
, g_pTexture);
137
//
要想用矩阵来平移2D纹理,必须设置D3DTSS_TEXTURETRANSFORMFLAGS成D3DTTFF_COUNT2
138
g_pd3dDevice
->
SetTextureStageState(
0
, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
139
//
这句在这里可有可无
140
g_pd3dDevice
->
SetTextureStageState(
0
, D3DTSS_TEXCOORDINDEX,
0
);
141
142
g_pd3dDevice
->
SetSamplerState(
0
, D3DSAMP_ADDRESSU , D3DTADDRESS_MIRROR);
143
g_pd3dDevice
->
SetSamplerState(
0
, D3DSAMP_ADDRESSV , D3DTADDRESS_MIRROR);
144
g_pd3dDevice
->
SetRenderState(D3DRS_LIGHTING , FALSE);
145
//
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE , D3DFILL_WIREFRAME);
146
g_pd3dDevice
->
SetStreamSource(
0
, g_pVB ,
0
,
sizeof
(CUSTOMVERTEX));
147
g_pd3dDevice
->
SetFVF(D3DFVF_CUSTOMVERTEX);
148
g_pd3dDevice
->
DrawPrimitive(D3DPT_TRIANGLESTRIP ,
0
,
2
);
149
g_pd3dDevice
->
EndScene();
150
}
151
//
显示
152
g_pd3dDevice
->
Present(
0
,
0
,
0
,
0
);
153
}
154
}
155
156
//
初始化 D3D 设备
157
HRESULT InitD3D(HWND hWnd)
158
{
159
//
创建 D3D Driver
160
if
(NULL
==
(g_pD3D
=
Direct3DCreate9(D3D_SDK_VERSION)))
161
{
162
D3DErr(
"
无法创建Direct3D9设备
"
);
163
return
E_FAIL;
164
}
165
//
获取当前显示模式
166
D3DDISPLAYMODE d3ddm;
167
if
(FAILED(g_pD3D
->
GetAdapterDisplayMode(D3DADAPTER_DEFAULT ,
&
d3ddm)))
168
{
169
D3DErr(
"
无法获取D3D显示器模式
"
);
170
return
E_FAIL;
171
}
172
173
//
获取窗口的大小
174
RECT rect;
175
GetClientRect(hWnd ,
&
rect);
176
177
//
填充参数
178
D3DPRESENT_PARAMETERS d3dpp;
179
memset(
&
d3dpp ,
0
,
sizeof
(d3dpp));
180
d3dpp.BackBufferFormat
=
d3ddm.Format;
181
d3dpp.BackBufferWidth
=
rect.right
-
rect.left;
182
d3dpp.BackBufferHeight
=
rect.bottom
-
rect.top;
183
d3dpp.SwapEffect
=
D3DSWAPEFFECT_DISCARD;
184
d3dpp.Windowed
=
true
;
185
d3dpp.AutoDepthStencilFormat
=
D3DFMT_D16;
186
d3dpp.EnableAutoDepthStencil
=
TRUE;
187
188
//
获取帽子
189
if
(FAILED(g_pD3D
->
GetDeviceCaps(D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL ,
&
g_Caps)))
190
{
191
D3DErr(
"
获取D3D 帽子时发生错误
"
);
192
return
E_FAIL;
193
}
194
195
//
创建D3D设备
196
if
(FAILED(g_pD3D
->
CreateDevice(D3DADAPTER_DEFAULT
197
, D3DDEVTYPE_HAL
198
, hWnd
199
//
检查是否支持硬件顶点处理
200
, g_Caps.DevCaps
&
D3DDEVCAPS_HWTRANSFORMANDLIGHT
?
D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING
201
,
&
d3dpp
202
,
&
g_pd3dDevice
203
)
204
))
205
{
206
D3DErr(
"
创建D3D设备时发生错误
"
);
207
return
E_FAIL;
208
}
209
g_pd3dDevice
->
SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
210
g_pd3dDevice
->
SetRenderState( D3DRS_ZENABLE, TRUE );
211
212
if
(FAILED(InitGeometry()))
213
return
E_FAIL;
214
return
S_OK;
215
}
216
217
//
清空所有占用的资源
218
void
CleanUp()
219
{
220
SAFE_RELEASE(g_pTexture);
221
SAFE_RELEASE(g_pIB);
222
SAFE_RELEASE(g_pVB);
223
SAFE_RELEASE(g_pd3dDevice);
224
SAFE_RELEASE(g_pD3D);
225
}
226
227
228
//
消息处理
229
LRESULT WINAPI MsgProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
230
{
231
switch
(message)
232
{
233
case
WM_DESTROY:
234
CleanUp();
235
PostQuitMessage(
0
);
236
break
;
237
}
238
return
::DefWindowProc(hWnd, message , wParam , lParam);
239
}
240
241
//
Windows 入口
242
int
WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN
int
nShowCmd )
243
{
244
WNDCLASS wndClass;
245
memset(
&
wndClass ,
0
,
sizeof
(wndClass));
246
wndClass.hInstance
=
hInstance;
247
wndClass.lpszClassName
=
"
Tutorial02
"
;
248
wndClass.lpfnWndProc
=
MsgProc;
249
RegisterClass(
&
wndClass);
250
251
//
创建窗口
252
HWND hWnd
=
CreateWindow(
"
Tutorial02
"
,
"
Tutorial02 Texture Scrolling
"
253
, WS_OVERLAPPEDWINDOW ,
0
,
0
,
512
,
512
, GetDesktopWindow()
254
,
0
, wndClass.hInstance ,
0
);
255
//
显示窗口
256
ShowWindow(hWnd , SW_SHOWDEFAULT);
257
UpdateWindow(hWnd);
258
259
//
初始化 D3D 设备
260
if
(SUCCEEDED(InitD3D(hWnd)))
261
{
262
//
消息处理循环
263
MSG msg;
264
memset(
&
msg ,
0
,
sizeof
(msg));
265
while
(msg.message
!=
WM_QUIT)
266
{
267
if
(PeekMessage(
&
msg ,
0
,
0
,
0
, PM_REMOVE))
268
{
269
TranslateMessage(
&
msg);
270
DispatchMessage(
&
msg);
271
}
272
else
273
{
274
Render();
275
}
276
}
277
}
278
//
清空场景
279
CleanUp();
280
281
UnregisterClass(
"
Tutorial02
"
, wndClass.hInstance);
282
283
return
0
;
284
}
|