在DirectX程序中我们可以创建多个D3D设备在多个不同的窗口中渲染物体。这样他们可以共享纹理和模型数据等多个窗口渲染的话我们建议使用交换链,那样可以使用更少资源更优化的管理我们的资源

我们先看以下创建多个窗口和设备的代码:

//********************************************************************
//      Filename: Main.cpp
//        Author: Chinafish
//      Modifier: Chinafish
//       Created: 2010-06-25 13:41
//       Updated: 2010-06-25 13:41
//            QQ: 149200849
//           MSN: china_fish@msn.com
//       Purpose: Render to multiple windows using multiple devices.
//====================================================================
//  Copyright(C) 2004-2010 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_0    "www.csinx.org - Multiple Devices #0 (DX9+VC7)"
#define WINDOW_TITLE_1    "www.csinx.org - Multiple Devices #1 (DX9+VC7)"

#define WINDOW_WIDTH	800
#define WINDOW_HEIGHT	600

//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
HWND					g_hWnd_0			= NULL; // Handle to the first window
HWND					g_hWnd_1			= NULL; // Handle to the second window
LPDIRECT3D9				g_pD3D				= NULL;
LPDIRECT3DDEVICE9		g_pd3dDevice_0		= NULL; // Direct3d device for the first window
LPDIRECT3DDEVICE9		g_pd3dDevice_1		= NULL; // Direct3d device for the second window
D3DPRESENT_PARAMETERS	g_d3dpp;
//-----------------------------------------------------------------------------
// 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_0();
void InitD3D_1();
void ShutDown_0(void);
void ShutDown_1(void);
void Render_0(void);
void Render_1(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_MULTIPLEVIEWPORTS";
	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;

	//
    // Create window #0...
    //

	g_hWnd_0 = CreateWindowEx(NULL, "CLASS_MULTIPLEVIEWPORTS",
		WINDOW_TITLE_0,
		WS_EX_TOPMOST, 0, 0,
		WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL,
		hInstance, NULL);

	if(g_hWnd_0 == NULL)
		return E_FAIL;

	// Adjust window
	RECT rect_0 = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
	AdjustWindowRect(&rect_0, GetWindowLong(g_hWnd_0, GWL_STYLE), FALSE);
	SetWindowPos(g_hWnd_0, 0, 0, 0, rect_0.right - rect_0.left, rect_0.bottom - rect_0.top,
		SWP_NOZORDER | SWP_NOMOVE);

	ShowWindow(g_hWnd_0, nCmdShow);
	UpdateWindow(g_hWnd_0);

	//
	// Create window #1...
	//

	g_hWnd_1 = CreateWindowEx(NULL, "CLASS_MULTIPLEVIEWPORTS",
		WINDOW_TITLE_1,
		WS_EX_TOPMOST, 300, 200,
		WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL,
		hInstance, NULL);

	if(g_hWnd_1 == NULL)
		return E_FAIL;

	// Adjust window
	RECT rect_1 = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
	AdjustWindowRect(&rect_1, GetWindowLong(g_hWnd_1, GWL_STYLE), FALSE);
	SetWindowPos(g_hWnd_1, 0, 0, 0, rect_1.right - rect_1.left, rect_1.bottom - rect_1.top,
		SWP_NOZORDER | SWP_NOMOVE);

	ShowWindow(g_hWnd_1, nCmdShow);
	UpdateWindow(g_hWnd_1);

	// Init D3D
	InitD3D_0();
	InitD3D_1();

	while(uMsg.message != WM_QUIT)
	{
		if(PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&uMsg);
			DispatchMessage(&uMsg);
		}
		else
		{
			// Render a frame
			Render_0();
			Render_1();
		}
	}

	ShutDown_0();
	ShutDown_1();

	UnregisterClass("CLASS_MULTIPLEVIEWPORTS", 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_0()
// Desc: This function will only be called once during the application's
//       initialization phase. Therefore, it can't contain any resources that
//       need to be restored every time the Direct3D device is lost or the
//       window is resized.
//-----------------------------------------------------------------------------
void InitD3D_0()
{
	// Create D3D
	g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if(!g_pD3D)
	{
		MessageBox(NULL, "Direct3DCreate9() - Failed!", "Error", NULL);
		return;
	}

	D3DDISPLAYMODE d3ddm;
	g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

	ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
	g_d3dpp.Windowed               = TRUE;
	g_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
	g_d3dpp.BackBufferFormat       = d3ddm.Format;
	g_d3dpp.EnableAutoDepthStencil = TRUE;
	g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	g_d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;

	g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
		g_hWnd_0, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&g_d3dpp, &g_pd3dDevice_0);

	if(!g_pd3dDevice_0)
	{
		return;
	}
}

//-----------------------------------------------------------------------------
// Name: InitD3D_1()
// Desc: This function will only be called once during the application's
//       initialization phase. Therefore, it can't contain any resources that
//       need to be restored every time the Direct3D device is lost or the
//       window is resized.
//-----------------------------------------------------------------------------
void InitD3D_1()
{
	// Create D3D
	g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if(!g_pD3D)
	{
		MessageBox(NULL, "Direct3DCreate9() - Failed!", "Error", NULL);
		return;
	}

	D3DDISPLAYMODE d3ddm;
	g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

	ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
	g_d3dpp.Windowed               = TRUE;
	g_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
	g_d3dpp.BackBufferFormat       = d3ddm.Format;
	g_d3dpp.EnableAutoDepthStencil = TRUE;
	g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	g_d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;

	g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
		g_hWnd_1, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&g_d3dpp, &g_pd3dDevice_1);

	if(!g_pd3dDevice_1)
	{
		return;
	}
}

//-----------------------------------------------------------------------------
// Name: ShutDown_0()
// Desc: Release all
//-----------------------------------------------------------------------------
void ShutDown_0(void)
{
	Release_Safe(g_pd3dDevice_0);
	Release_Safe(g_pD3D);
}

//-----------------------------------------------------------------------------
// Name: ShutDown_1()
// Desc: Release all
//-----------------------------------------------------------------------------
void ShutDown_1(void)
{
	Release_Safe(g_pd3dDevice_1);
}

//-----------------------------------------------------------------------------
// Name: Render_0()
// Desc: Render something you want
//-----------------------------------------------------------------------------
void Render_0(void)
{
	// Clear screen with D3DCOLOR_XRGB(255, 0, 255)
	g_pd3dDevice_0->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 255), 1.0f, 0);

	g_pd3dDevice_0->BeginScene();

	// Render geometry here...

	g_pd3dDevice_0->EndScene();

	g_pd3dDevice_0->Present(NULL, NULL, NULL, NULL);
}

//-----------------------------------------------------------------------------
// Name: Render_1()
// Desc: Render something you want
//-----------------------------------------------------------------------------
void Render_1(void)
{
	// Clear screen with D3DCOLOR_XRGB(0, 255, 0)
	g_pd3dDevice_1->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);

	g_pd3dDevice_1->BeginScene();

	// Render geometry here...

	g_pd3dDevice_1->EndScene();

	g_pd3dDevice_1->Present(NULL, NULL, NULL, NULL);
}
				

框架代码我们在前面已经有说明,这里需要说明的是我们创建了两个窗口,并在每个窗口创建了D3D设备,这些操作只是说明这样做是可以的,在实际使用中估计没有人会这么做。

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

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