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 }