1 #include <Windows.h>
2 #include <d3d9.h>
3 #include <D3DX10math.h>
4 #include <strsafe.h>
5 //全局变量
6
7 LPDIRECT3D9 d3D9 = NULL; // IDirect3D9接口指针,用于获得物理设备信息和创建IDirect3DDeivce9接口。
8 LPDIRECT3DDEVICE9 d3dDevice = NULL; // 代表显示3d图形的物理设备的C++对象。
9 LPDIRECT3DVERTEXBUFFER9 vertexBuffer = NULL; // 顶点缓存,用于存储顶点坐标。
10 LPDIRECT3DINDEXBUFFER9 indexBuffer = NULL; // 索引缓存,用于存储组成各个三角形的顶点的索引
11
12 struct Vertex // 三维中顶点结构
13 {
14 float x, y, z;
15 };
16
17 //初始化 Direct3D
18 BOOL InitD3D(HWND hwnd)
19 {
20 if( NULL == (d3D9 = Direct3DCreate9(D3D_SDK_VERSION))) // 该初始化函数保证应用程序通过正确的头文件被生成。
21 return E_FAIL;
22
23
24
25 D3DCAPS9 caps; //device capabilitites
26 d3D9->GetDeviceCaps( // 获取设备信息
27 D3DADAPTER_DEFAULT, //Adapter 指定获取哪个显示适配器的特性
28 D3DDEVTYPE_HAL, // 设备类型 硬件设备:D3DDEVTYPE_HAL 软件设备:D3DDEVTYPE_REF
29 &caps); //返回填充后的D3DCAPS9结构。
30
31 int vp = 0; //代表是否支持硬件顶点处理
32 if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) //显卡是否支持硬件几何转换和光源计算
33 {
34 vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //支持,硬件方式处理顶点
35 }
36 else
37 {
38 vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //软件方式处理顶点
39 }
40
41 D3DPRESENT_PARAMETERS d3dparam; // 这个结构用于设定我们将要创建的IDirect3DDevice9对象的一些特性
42 ZeroMemory(&d3dparam, sizeof(d3dparam));
43 d3dparam.BackBufferWidth = 800; //后备缓冲表面的宽度
44 d3dparam.BackBufferHeight = 600; //后备缓冲表面的高度
45 d3dparam.BackBufferFormat = D3DFMT_A8R8G8B8; //后备缓冲表面的像素格式
46 d3dparam.BackBufferCount = 1; // 后备表面的个数
47 d3dparam.MultiSampleType = D3DMULTISAMPLE_NONE; //全屏抗锯齿的类型
48 d3dparam.MultiSampleQuality = 0; //全屏抗锯齿的质量等级
49 d3dparam.SwapEffect = D3DSWAPEFFECT_DISCARD; // 指定表面在交换链中是如何被交换的
50 d3dparam.hDeviceWindow = hwnd; // 窗口句柄
51 d3dparam.Windowed = true; //是否窗口模式
52 d3dparam.EnableAutoDepthStencil = true; // 深度/模板缓冲
53 d3dparam.AutoDepthStencilFormat = D3DFMT_D24S8; //深度/模板缓冲的等级
54 d3dparam.Flags = 0; // 一些附加特性
55 d3dparam.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //刷新率
56 d3dparam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //属于D3DPRESENT 成员,又有两个常用标志,其余请查SDK:
57
58 //创建IDirect3DDevcie9对象
59 if(FAILED(d3D9->CreateDevice(
60 D3DADAPTER_DEFAULT, //adapter
61 D3DDEVTYPE_HAL, //设备类型
62 hwnd, //窗口句柄
63 vp, //顶点处理方式
64 &d3dparam, &d3dDevice)))
65 {
66 return E_FAIL;
67 }
68 return true;
69 }
70
71 // 创建顶点缓存
72 bool InitVertexBuffer()
73 {
74
75 // 初始化正方体的8顶点
76 Vertex vertex[] =
77 {
78 {-1.0f, -1.0f, -1.0f},
79 {-1.0f, 1.0f, -1.0f},
80 {1.0f, 1.0f, -1.0f},
81 {1.0f, -1.0f, -1.0f},
82 {-1.0f, -1.0f, 1.0f},
83 {-1.0f, 1.0f, 1.0f},
84 {1.0f, 1.0f, 1.0f},
85 {1.0f, -1.0f, 1.0f}
86 };
87 if(FAILED(d3dDevice->CreateVertexBuffer( //创建顶点缓存
88 8*sizeof(Vertex), // 分配给缓存的字节大小
89 0, //指定关于怎样使用缓存的额外信息
90 D3DFVF_XYZ, // 存储杂牌缓存中的顶点格式
91 D3DPOOL_DEFAULT, //缓存放置在哪一个内存池中
92 &vertexBuffer, //返回创建好的顶点缓存的指针
93 NULL))) // 没有使用
94 {
95 return false;
96 }
97 Vertex *vetices;
98 vertexBuffer->Lock(0, 0, (void**)&vetices, 0); //锁存整个缓存
99 memcpy(vetices, vertex, sizeof(vertex)); //想缓存里写顶点
100 vertexBuffer->Unlock(); //解锁缓存
101 return true;
102 }
103
104 //设置照相机和投影
105 void SetupMatrices()
106 {
107
108 D3DXMATRIXA16 matWorld;
109 UINT iTime = timeGetTime() % 1000; //旋转
110 FLOAT fAngle = iTime * ( 2.0f * D3DX_PI ) / 1000.0f;
111 D3DXMatrixRotationY( &matWorld, fAngle ); //绕Y坐标旋转matWorord矩阵
112 d3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); //切换到世界坐标系中
113
114 D3DXVECTOR3 position(5.0f, 5.0f, -5.0f); //虚拟照相机坐标
115 D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); // 目标物体坐标
116 D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); //正上方坐标
117 D3DXMATRIX v;
118 D3DXMatrixLookAtLH(&v, &position, &target, &up); //计算视图坐标系的变换矩阵
119
120 d3dDevice->SetTransform(D3DTS_VIEW, &v); //视图坐标系变换
121
122
123 D3DXMATRIX proj; //投影矩阵
124 //计算投影矩阵
125 D3DXMatrixPerspectiveFovLH(&proj,
126 D3DX_PI*0.5f, //视野角度
127 800.0/600.0, //宽高比
128 1.0f, //前裁剪面距离
129 1000.0f); //后裁剪面距离
130 d3dDevice->SetTransform(D3DTS_PROJECTION, &proj); //设置投影变换
131 d3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); //以线框模式渲染物体
132 }
133
134 //初始化索引缓存
135 bool InitIntextBuffer()
136 {
137 d3dDevice->CreateIndexBuffer(36*sizeof(WORD),
138 D3DUSAGE_WRITEONLY,
139 D3DFMT_INDEX16, //指定索引的大小
140 D3DPOOL_MANAGED,
141 &indexBuffer,
142 0);
143 WORD* indices = 0;
144 indexBuffer->Lock(0, 0, (void**)&indices, 0);
145
146 //前面
147 indices[0] = 0; indices[1] = 1; indices[2] = 2;
148 indices[3] = 0; indices[4] = 2; indices[5] = 3;
149 // 背面
150 indices[6] = 4; indices[7] = 6; indices[8] = 5;
151 indices[9] = 4; indices[10] = 7; indices[11] = 6;
152
153 // 左面
154 indices[12] =4; indices[13] =5; indices[14] = 1;
155 indices[15] = 4; indices[16] = 1; indices[17] = 0;
156
157 // 右面
158 indices[18] = 3; indices[19] = 2; indices[20] =6;
159 indices[21] = 3; indices[22] = 6; indices[23] =7;
160 //顶面
161 indices[24] = 1; indices[25] = 5; indices[26] =6;
162 indices[27] = 1; indices[28] = 6; indices[29] = 2;
163 //底面
164 indices[30] =4; indices[31] = 0; indices[32] =3;
165 indices[33] = 4; indices[34] = 3; indices[35] = 7;
166
167 indexBuffer->Unlock();
168
169
170
171 return true;
172 }
173
174 //释放COM资源
175 bool CleanUp()
176 {
177 if(indexBuffer != NULL)
178 indexBuffer->Release();
179 if(vertexBuffer != NULL)
180 vertexBuffer->Release();
181 if(d3dDevice != NULL)
182 d3dDevice->Release();
183 if(d3D9 != NULL)
184 d3D9->Release();
185 return true;
186 }
187
188 //渲染
189 bool Render()
190 {
191
192
193 d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
194 if(SUCCEEDED(d3dDevice->BeginScene())) //开始场景绘制
195 {
196 SetupMatrices(); //设置照相机和投影
197
198 // 设置资源流与一个顶点缓存挂钩
199 d3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(Vertex));
200 d3dDevice->SetIndices(indexBuffer); //设置索引缓存
201 d3dDevice->SetFVF(D3DFVF_XYZ); //设置顶点格式
202
203 //使用索引来绘制图元
204 d3dDevice->DrawIndexedPrimitive(
205 D3DPT_TRIANGLELIST, //图元类型
206 0, //一个基本数字,在调用中用它去加上索引
207 0, //将被引用的最小索引值
208 8, //顶点数
209 0, //开始渲染的开始索引点
210 12); //绘制图元的个数
211 d3dDevice->EndScene(); //结束场景绘制
212 }
213 d3dDevice->Present(NULL, NULL, NULL, NULL); //翻转表面
214 return true;
215 }
216
217
218 //消息处理函数
219 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
220 {
221 switch( msg )
222 {
223 case WM_DESTROY:
224 CleanUp();
225 PostQuitMessage( 0 );
226 return 0;
227 }
228
229 return DefWindowProc( hwnd, msg, wParam, lParam );
230 }
231
232 //main函数
233 INT WINAPI wWinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPWSTR lpCmdLine, __in int nShowCmd )
234 {
235 UNREFERENCED_PARAMETER(hInstance);
236 WNDCLASSEX wc = {
237 sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
238 GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
239 L"Cubedemo", NULL
240 };
241 RegisterClassEx(&wc);
242
243 HWND hwnd = CreateWindow(L"CubeDemo", L"CubeDemo",
244 WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);
245
246 if(InitD3D(hwnd))
247 {
248 if(InitVertexBuffer() && InitIntextBuffer())
249 {
250 ShowWindow(hwnd, SW_SHOWDEFAULT);
251 UpdateWindow(hwnd);
252 MSG msg;
253 ZeroMemory(&msg, sizeof(msg));
254 while(msg.message != WM_QUIT)
255 {
256 if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
257 {
258 TranslateMessage(&msg);
259 DispatchMessage(&msg);
260 }
261 else
262 {
263 Render();
264 }
265 }
266
267 }
268 }
269 UnregisterClass(L"CubeDemo", wc.hInstance);
270 return 0;
271
272 }