Direct3D的初始化分四步骤:
1. 获取接口IDrect3D9的指针;此指针在2,4步中将会用到,在2步中用来获取系统中物理硬件设备信息,4步中用来创建IDirect3DDevice9对象
代码:
IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2. 检查设备性能;判断主显卡是否支持顶点运算,在创建一个IDirect3DDevice9类型对象是,必须指定使用该对象进行顶点运算的类型,由于并非所有的显卡都支持硬件顶点运算,所以需要检查;
代码:
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;
}
D3DCREATE_HARDWARE_VERTEXPROCESSING硬件顶点运算
D3DCREATE_SOFTWARE_VERTEXPROCESSING软件顶点运算
3. 初始化D3DPRESENT_PARAMETERS结构的一个实例,该结构用于指定IDirect3DDevice9类型对象的一些特征
代码:
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;
4. 创建IDirect3DDevice9对象
代码:
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
deviceType,
hwnd,
vp,
&d3dpp,
device);
一个实例:(vs2010)
d3dUtility.h
#pragma once
#pragma comment (lib,"d3d9.lib")
#pragma comment (lib,"d3dx9.lib")
#pragma comment (lib,"winmm.lib")
#include <d3dx9.h>
#include <string>
namespace d3d
{
bool InitD3D(
HINSTANCE hInstance,
int width, int height,
bool windowed,
D3DDEVTYPE deviceType,
IDirect3DDevice9** device);
int EnterMsgLoop(
bool (*ptr_display)(float timeDelta));
LRESULT CALLBACK WndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
template<class T> void Release(T t)
{
if(t)
{
t->Release();
t = 0;
}
}
template<class T> void Delete(T t)
{
if(t)
{
delete t;
t = 0;
}
}
}
d3dUtility.cpp
#include "d3dUtility.h"
bool d3d::InitD3D(
HINSTANCE hInstance,
int width, int height,
bool windowed,
D3DDEVTYPE deviceType,
IDirect3DDevice9** device)
{
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);
HRESULT hr = 0;
//第1步:获取接口IDirect3D9指针
IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if( !d3d9 )
{
::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
return false;
}
//第2步:检查设备性能
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;
}
//第3步:初始化D3DPRESET_PARAMETER结构一个实例
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;
//第4步:创建IDirect3DDevice9对象
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
deviceType,
hwnd,
vp,
&d3dpp,
device);
if(FAILED(hr))
{
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();
}
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;
}
d3dInit.cpp
#include "d3dUtility.h"
#include<windows.h>
IDirect3DDevice9* Device = 0;
bool Setup()
{
// Nothing to setup in this sample.
return true;
}
void Cleanup()
{
// Nothing to cleanup in this sample.
}
bool Display(float timeDelta)
{
if( Device )
{
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
Device->Present(0, 0, 0, 0);
}
return true;
}
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);
}
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;
}
此实例在Dispaly函数中调用了IDrect3DDevice9::Clear函数,将后台缓存和深度或模版缓存分别设置为黑色和1.0,然后调用IDrect3DDevice9::Present函数提交后台缓存。
运行结果: