现在我们已经知道如何创建一个Win32窗口程序, 我们现在要学习如何访问DirectX图形, 首先我们需要包含DX9的头文件 d3d9.h 和链接 d3d9.lib . 初始化D3D主要需要以下几个步骤:
- 根据D3D版本创建D3D物体.
- 清空并设置显示参数.
- 使用定义的显示参数, 创建D3D设备.
以下为初始化D3D窗口程序的主要代码, 代码中并没有检测系统支持的格式.
//******************************************************************** // Filename: Main.cpp // Author: Chinafish // Modifier: Chinafish // Created: 2008-3-3 17:55 // Updated: 2008-3-3 17:55 // QQ: 149200849 // MSN: china_fish@msn.com // Purpose: Initialize D3D window //==================================================================== // Copyright(C) 2004-2008 by Chinafish. All Rights Reserved. //******************************************************************** #define STRICT #define WIN32_LEAN_AND_MEAN #include "windows.h" // Link D3D #include "d3d9.h" #pragma comment(lib, "d3d9.lib") #define Release_Safe(p){if(p!=NULL) p->Release();} #define WINDOW_TITLE "www.csinx.org - Initializing D3D Window (DX9+VC7)" #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 //----------------------------------------------------------------------------- // GLOBALS //----------------------------------------------------------------------------- HWND g_hWnd = NULL; LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //----------------------------------------------------------------------------- // PROTOTYPES //----------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow); LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void InitD3D(void); void ShutDown(void); void Render(void); //----------------------------------------------------------------------------- // Name: WinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { WNDCLASSEX winClass; MSG uMsg; memset(&uMsg,0,sizeof(uMsg)); winClass.lpszClassName = "CLASS_INITD3D_WINDOW"; winClass.cbSize = sizeof(WNDCLASSEX); winClass.style = CS_HREDRAW | CS_VREDRAW; winClass.lpfnWndProc = WindowProc; winClass.hInstance = hInstance; winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)NULL); winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)NULL); winClass.hCursor = LoadCursor(NULL, IDC_ARROW); winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winClass.lpszMenuName = NULL; winClass.cbClsExtra = 0; winClass.cbWndExtra = 0; if( !RegisterClassEx(&winClass) ) return E_FAIL; g_hWnd = CreateWindowEx( NULL, "CLASS_INITD3D_WINDOW", WINDOW_TITLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL ); if( g_hWnd == NULL ) return E_FAIL; // Adjust window RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; AdjustWindowRect( &rect, GetWindowLong( g_hWnd, GWL_STYLE ), FALSE ); SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE ); ShowWindow( g_hWnd, nCmdShow ); UpdateWindow( g_hWnd ); // Init D3D InitD3D(); while( uMsg.message != WM_QUIT ) { if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &uMsg ); DispatchMessage( &uMsg ); } else { // Render a frame Render(); } } ShutDown(); UnregisterClass( "CLASS_INITD3D_WINDOW", winClass.hInstance ); return uMsg.wParam; } //----------------------------------------------------------------------------- // Name: WindowProc() // Desc: The window's message handler //----------------------------------------------------------------------------- LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_KEYDOWN: { switch( wParam ) { case VK_ESCAPE: PostQuitMessage(0); break; } } break; case WM_CLOSE: { PostQuitMessage(0); } case WM_DESTROY: { PostQuitMessage(0); } break; default: { return DefWindowProc( hWnd, msg, wParam, lParam ); } break; } return 0; } //----------------------------------------------------------------------------- // Name: InitD3D() // Desc: Initialize Direct 3D //----------------------------------------------------------------------------- void InitD3D( void ) { // Create D3D g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ); if( !g_pD3D ) { return; } // Fill parameters D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Windowed = TRUE; // Create D3D device if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return; } } //----------------------------------------------------------------------------- // Name: ShutDown() // Desc: Release all //----------------------------------------------------------------------------- void ShutDown( void ) { Release_Safe(g_pd3dDevice); Release_Safe(g_pD3D); } //----------------------------------------------------------------------------- // Name: Render() // Desc: Render something you want //----------------------------------------------------------------------------- void Render( void ) { // Clear screen with D3DCOLOR_XRGB(255, 0, 255) g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 255), 1.0f, 0 ); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->EndScene(); g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); }
在以上代码中我们在创建窗口程序后初始化D3D环境. 首先我们通过 Direct3DCreate9 创建一个 D3D物体 , D3D物体用来配置基于系统显卡的支持能力的D3D程序, 在本例中我们仅用于创建 D3D设备 .
然后我们需要填充 D3DPRESENT_PARAMETERS 结构来设置显示参数, 在创建窗口模式我们只需要设置是否为窗口模式,障碍这里我们设置窗口模式为TRUE, 其他主要设置还有像素格式, 后置缓冲显示方式, 后置缓冲数量, 显示模式等.
设置显示参数以后我们通过 IDirect3D9::CreateDevice 来创建一个 D3D设备 . 现在我们已经完成DirectX图形的初始化并可以使用D3D渲染啦.
我们在渲染时需要通过 IDirect3DDevice9::Clear 指定一个颜色填充后置缓冲区(我们需要用来画东西的表面), D3DCOLOR_XRGB 宏用于指定一种颜色. 需要注意的是我们在渲染任何物体之前都要调用 IDirect3DDevice9::BeginScene 函数并且在结束渲染后调用 IDirect3DDevice9::EndScene . 这主要是告诉DirectX我们需要画一些图形并且已经清过后置缓冲区啦. 最后我们通过调用 IDirect3DDevice9::Present 切换后置缓冲区到前置缓冲区, 将我们画的图形显示到屏幕上.
D3D物体 和 D3D设备 都是 COM物体 , 我们需要在程序结束后通过 Release 将资源释放给Window, 在以上代码中我们使用自定义的Release_Safe宏释放资源.
下图为本例代码执行效果: