现在我们已经知道如何创建一个Win32窗口程序, 我们现在要学习如何访问DirectX图形, 首先我们需要包含DX9的头文件 d3d9.h 和链接 d3d9.lib . 初始化D3D主要需要以下几个步骤:

  1. 根据D3D版本创建D3D物体.
  2. 清空并设置显示参数.
  3. 使用定义的显示参数, 创建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宏释放资源.

下图为本例代码执行效果:

[返回目录][我有话说]