微软的的东西还是很庞大,很复杂,很不好用....但是看到directX自带的那些sample的时候,还是果断呆掉了,我想说,我也要做出这个!
接着是花了将近一天的时间完成来搞定微软的这一套图形开发的环境。
准备工作:
win7旗舰版 vs2008 express(比较轻量) directX 9.0SDK 网上能下到得最新版的是2010年的那个版本,微软官网下载不了。
接下来可以动手了。
1)先把VS2008装好,下载好镜像之后大小不到1G。
用驱动精灵装载,然后运行,选择visual c++,大概20分钟搞定。
2)装directX的sdk,500多M,双击运行,一路下一步就可以。
3)启动VS,添加sdk的头文件和库文件。
Tools-Options-Project and Solutions-VC++ Directories里面
添加DirectX安装目录下的Include到Include
添加DirectX安装目录下的Lib/X86到Include
4)接下来我们来运行一个初始化窗口的示例
新建一个win32项目,记得勾选空项目,然后新建一个main.cpp,代码如下:
////////////////////////////////////////////////////////////////////////////////////////////////// // // File: d3dinit.cpp // // Author: Frank Luna (C) All Rights Reserved // // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 // // Desc: Demonstrates how to initialize Direct3D, how to use the book's framework // functions, and how to clear the screen to black. Note that the Direct3D // initialization code is in the d3dUtility.h/.cpp files. // ////////////////////////////////////////////////////////////////////////////////////////////////// #include "d3dUtility.h" // // Globals // IDirect3DDevice9* Device = 0; // // Framework Functions // bool Setup() { // Nothing to setup in this sample. return true; } void Cleanup() { // Nothing to cleanup in this sample. } bool Display(float timeDelta) { if( Device ) // Only use Device methods if we have a valid device. { // Instruct the device to set each pixel on the back buffer black - // D3DCLEAR_TARGET: 0x00000000 (black) - and to set each pixel on // the depth buffer to a value of 1.0 - D3DCLEAR_ZBUFFER: 1.0f. Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0); // Swap the back and front buffers. Device->Present(0, 0, 0, 0); } return true; } // // WndProc // LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); } // // WinMain // int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { if(!d3d::InitD3D(hinstance, 640, 480, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, "InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) { ::MessageBox(0, "Setup() - FAILED", 0, 0); return 0; } d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; }
d3dUtility.h
////////////////////////////////////////////////////////////////////////////////////////////////// // // File: d3dinit.cpp // // Author: Frank Luna (C) All Rights Reserved // // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 // // Desc: Demonstrates how to initialize Direct3D, how to use the book's framework // functions, and how to clear the screen to black. Note that the Direct3D // initialization code is in the d3dUtility.h/.cpp files. // ////////////////////////////////////////////////////////////////////////////////////////////////// #include "d3dUtility.h" // // Globals // IDirect3DDevice9* Device = 0; // // Framework Functions // bool Setup() { // Nothing to setup in this sample. return true; } void Cleanup() { // Nothing to cleanup in this sample. } bool Display(float timeDelta) { if( Device ) // Only use Device methods if we have a valid device. { // Instruct the device to set each pixel on the back buffer black - // D3DCLEAR_TARGET: 0x00000000 (black) - and to set each pixel on // the depth buffer to a value of 1.0 - D3DCLEAR_ZBUFFER: 1.0f. Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0); // Swap the back and front buffers. Device->Present(0, 0, 0, 0); } return true; } // // WndProc // LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); } // // WinMain // int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { if(!d3d::InitD3D(hinstance, 640, 480, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, "InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) { ::MessageBox(0, "Setup() - FAILED", 0, 0); return 0; } d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; }
////////////////////////////////////////////////////////////////////////////////////////////////// // // File: d3dUtility.cpp // // Author: Frank Luna (C) All Rights Reserved // // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 // // Desc: Provides utility functions for simplifying common tasks. // ////////////////////////////////////////////////////////////////////////////////////////////////// #include "d3dUtility.h" bool d3d::InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9** device) { // // Create the main application window. // WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)d3d::WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = "Direct3D9App"; if( !RegisterClass(&wc) ) { ::MessageBox(0, "RegisterClass() - FAILED", 0, 0); return false; } HWND hwnd = 0; hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App", WS_EX_TOPMOST, 0, 0, width, height, 0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); if( !hwnd ) { ::MessageBox(0, "CreateWindow() - FAILED", 0, 0); return false; } ::ShowWindow(hwnd, SW_SHOW); ::UpdateWindow(hwnd); // // Init D3D: // HRESULT hr = 0; // Step 1: Create the IDirect3D9 object. IDirect3D9* d3d9 = 0; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if( !d3d9 ) { ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0); return false; } // Step 2: Check for hardware vp. D3DCAPS9 caps; d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps); int vp = 0; if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Step 3: Fill out the D3DPRESENT_PARAMETERS structure. D3DPRESENT_PARAMETERS d3dpp; d3dpp.BackBufferWidth = width; d3dpp.BackBufferHeight = height; d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hwnd; d3dpp.Windowed = windowed; d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Step 4: Create the device. hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, // primary adapter deviceType, // device type hwnd, // window associated with device vp, // vertex processing &d3dpp, // present parameters device); // return created device if( FAILED(hr) ) { // try again using a 16-bit depth buffer d3dpp.AutoDepthStencilFormat = D3DFMT_D16; hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if( FAILED(hr) ) { d3d9->Release(); // done with d3d9 object ::MessageBox(0, "CreateDevice() - FAILED", 0, 0); return false; } } d3d9->Release(); // done with d3d9 object return true; } int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) ) { MSG msg; ::ZeroMemory(&msg, sizeof(MSG)); static float lastTime = (float)timeGetTime(); while(msg.message != WM_QUIT) { if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { float currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; }
项目上右击->属性->连接器->输入->附加依赖项中添加d3d9.lib d3dx9.lib winmm.lib
确认和编译,运行,结果如下:
6)运行一下sdk中的sample
找到sdk中的sample文件夹,选一个对应得vs2008项目文件,例如这个MultiAnimation。
打开之后直接F5,编译运行。如果能够编译成功,那么环境可以确定配置成功了。
可能遇到的问题:
1)首先得确认sdk和vs的版本,理论上vs2008或者vs2005会比较好一些,之前我一直用的是2010,编译的时候总是出bug,无解。
sdk最好选最新的版本,主要是文档比较齐全。
2)遇到无法解释某个函数或变量,检查对应的库或头文件是否包含进来。
3)编译会提示cannot convert wchar to LPCSTR之类的提示.这个是因为使用了Unicode的原因(在DirectX的示例文件中都使用了Unicode).解决方案有下面几种:
-按alt-f7打开配置文件,在Configuration Property中的General菜单中,Character Set选择Not set,把所有的字符串前面的L都取消.因为L".."是宏(具体参见MSDN)
-如果想继续使用Unicode,可以使用下面的方法:把Character Set选择为Unicode,所有的字符串都加入L"..."作为Unicode表示,这样有个好处是如果你的软件要支持多种语言这是比较方便的.