(1)获取接口IDirect3D9的指针,该接口用于获取系统中物理硬件设备的信息并创建接口IDirect3DDevice9,该接口是一个C++对象,代表了我们用来显示3D图形的物理硬件设备。
使用Direct3DCreate9可获得该指针,它的参数必须是D3D_SDK_VERSION,只有如此才能保证程序使用正确头文件,如果函数调用失败,将返回一个NULL指针
(2)检查设备性能(D3DCAPS9),判断主显卡是否支持硬件顶点运算,为了创建接口IDirect3DDevice9,我们必须明确显卡是否支持该功能
HRESULT IDirect3D9::GetDeviceCaps(
UINT Adapter, //指定物理显卡的序号
D3DDEVTYPE DeviceType, //指定设备类型 硬件设备D3DDEVTYPE_HAL 软件设备D3DDEVTYPE_REF
D3DCAPS9 * pCaps //设备性能结构
);
(3)初始化D3DPRESENT_PARAMETERS结构示例,我们可以通过这些变量来指定即将创建接口IDirect3DDevice9的特性
(4)利用已初始化的D3DPRESENT_PARAMETERS结构创建一个IDirect3DDevice9对象
d3dUtility.h
#pragma once
#include <d3d9.h>
namespace d3d
{
//初始化Direct3D
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;
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 = L"Direct3D9App";
//窗口注册
if (!RegisterClass(&wc))
{
MessageBox(0, L"RegisterClass() - FAILED", 0, 0);
return false;
}
//创建窗口
HWND hwnd = 0;
hwnd = CreateWindow(L"Direct3D9App", L"Direct3D9App", WS_OVERLAPPEDWINDOW, 0, 0, width, height, 0, 0, hInstance, 0);
if (!hwnd)
{
MessageBox(0, L"CreateWindow() - FAILED", 0, 0);
return false;
}
//绘制更新窗口
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
//--------以下为初始化IDirect3D------------
//获取IDirect3D9指针
IDirect3D9* d3d9;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d9)
{
MessageBox(0, L"Direct3DCreate9() - FAILED", 0, 0);
return false;
}
//校验硬件性能(顶点运算)
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;
//填充D3DPRESENT_PARAMETERS结构
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width; //后台缓存中表面的宽度,单位为像素
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; //后台缓存的像素格式
d3dpp.BackBufferCount = 1; //所需使用的后台缓存个数,通常指定为1
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; //后台缓存所使用的多重采样类型
d3dpp.MultiSampleQuality = 0; //多重采样的质量水平
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //交换链中缓存的页面置换方式,D3DSWAPEFFECT_DISCARD时最高
d3dpp.hDeviceWindow = hwnd; //所要进行绘制的应用程序窗口
d3dpp.Windowed = windowed; //true为窗口模式,false为全屏模式
d3dpp.EnableAutoDepthStencil = true; //设为true则Direct3D自动创建并维护深度缓存或模板缓存
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; //深度缓存或模板缓存的像素格式 D3DFMT_D24S8 24位表示深度,8位保留模板缓存使用
d3dpp.Flags = 0; //附加特性 D3DPRESENTFLAG_LOCKABLE_BACKBUFFER指定可锁定后台缓存,使用一个可锁定的后台缓存会降低性能 D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //刷新频率
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //提交频率 D3DPRESENT_INTERVAL_IMMEDIATE立即提交 D3DPRESENT_INTERVAL_DEFAULT由Direct3D来选择提交频率
//创建IDirectDevice9接口
d3d9->CreateDevice(D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device);
d3d9->Release();
return true;
}
#if 0
GetMessage的主要功能是从消息队列中“取出”消息,消息被取出以后,就从消息队列中将其删除;而PeekMessage的主要功能是“窥视”消息,
如果有消息,就返回true,否则返回false。也可以使用PeekMessage从消息队列中取出消息,这要用到它的一个参数(UINT wRemoveMsg),
如果设置为PM_REMOVE,消息则被取出并从消息队列中删除;如果设置为PM_NOREMOVE,消息就不会从消息队列中取出
#endif
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;
}
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) //Esc键
DestroyWindow(hwnd);
break;
default:
break;
}
//调用缺省的窗口过程来为应用程序没有处理的任何窗口信息提供缺省的处理
//该函数确保每一个消息得到处理
return DefWindowProc(hwnd, msg, wParam, lParam);
}
D3DPractice.cpp
#include <windows.h>
#include "d3dUtility.h"
#include <d3dx9math.h>
IDirect3DDevice9* Device = NULL;
bool DisPlay(float timeDelta)
{
if (Device)
{
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
/*
STDMETHOD(Clear)(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) PURE;
Count: pRects数组中矩形的数目
pRects:要执行清除操作的屏幕矩形数组,该参数允许我们只对表面的部分区域进行清除操作
Flags:指定所要清除的表面
D3DCLEAR_TARGET 绘制目标表面,通常指后台缓存
D3DCLEAR_ZBUFFER 深度缓存
D3DCLEAR_STENCIL 模板缓存
Color:指定将绘制目标体设置为何种颜色
Z:深度缓存所需要设定的值
Stencil:模板缓存所需要设定的值
*/
Device->Present(0, 0, 0, 0); //提交后台缓存
}
return true;
}
bool SetUp()
{
return true;
}
void CleanUp()
{
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
if (!d3d::InitD3D(hInstance, 800, 600, true, D3DDEVTYPE_HAL, &Device))
{
::MessageBox(0, L"InitD3D() - FAILED", 0, 0);
return 0;
}
if (!SetUp())
{
::MessageBox(0, L"SetUp() - FAILED", 0, 0);
return 0;
}
d3d::EnterMsgLoop(DisPlay);
CleanUp();
Device->Release();
return 0;
}
版权声明:本文为SwordArcher原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。