[Direct3D 9.0] 第一个程序 旋转立方体

  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 }
原文地址:https://www.cnblogs.com/wangke1020/p/3672165.html