本文属于《逐梦旅程》学习笔记系列的DirectX篇,与此系列的Windows/GDI并列。
本系列不打算深入研究DirectX而只是简单介绍DirectX中应用最广泛的部分:Direct3D
作为本篇的开篇,我们用一个最简化的示例来说明。
这个示例的完整代码可以在这里找到
https://github.com/fengyhack/DirectGame/tree/SimpleDemo
首先,Windows Application的主函数WinMain具有如下结构
App app;
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
LPCSTR lpsz = "DemoWindow";
HWND hwnd = CreateSimpleWindow(hInstance, lpsz, WndProc);
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
PlaySound("NOIR3.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); //循环播放背景音乐
app.Create(hwnd);
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
app.Render();
}
}
UnregisterClass(lpsz, hInstance);
return 0;
}
基本上就是这几步,具体可以参考Windows应用程序的基本框架浅析(01)
需要注意的是消息循环
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
app.Render();
}
}
队列里的消息已经处理完毕,那么就可以进入渲染(Render)步骤。
当然,如果当前消息就是一条Update或者Paint消息的话,同样执行相应的渲染操作。
我们知道,Windows GDI/GDI+ 已经足够处理一般的绘图需求,但是对于复杂的情形,这种模式就显得有些效率底下了。
在常规的3D游戏中,绘图需求要求极高(当然还需要处理其他事务,例如用户交互,数据处理等等),需要寻求一种比
GDI/GDI+更高效的模式,尽最大限度的发挥硬件性能。
DirectX正式为此而生,它是M$的独门武器。另外还有强劲的对手OpenGL,与DirectX不同,它是开放的,但是此处不做讨论。
我们关注DirectX在3D图形(主要是指游戏开发)中的应用。
回到上述讨论。
在消息队列空闲时(可能是暂时没有外部事件,也可能是刚处理完所有消息)执行Render操作,这样更大限度的利用资源,
这样能够呈现更好的视觉效果。
同样的,在响应PAINT事件时也执行Render操作,就是说,只要可能就执行绘制操作,尽量保证“更高的帧率”(但也并非越高越好)。
关于创建Window和消息响应函数WINDOWPROC可以参见Windows应用程序的基本框架浅析(01)
我们来看看这个DirectX实例应用的具体内容
为了方便起见,我将其封装成一个类,声明如下
#include <d3d9.h>
#include <d3dx9.h>
#include <Windows.h>
class App
{
public:
App();
~App();
public:
void Create(HWND hwnd);
void Render(void);
void CleanUp(void);
private:
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DDEVICE9 device;
int width, height;
};
可以看到其中的3个public方法
void Create(HWND hwnd);
void Render(void);
void CleanUp(void);
分别表示创建、渲染、清理。
在类的析构函数中主动调用CleanUp函数以清理资源。
目前没有任何内容,因此Render函数内部是空的。
而CleanUp函数也比较简单,使用过的资源进行回收。
主要关注Create函数
void App::Create(HWND hwnd)
{
RECT rect;
::GetWindowRect(hwnd, &rect);
width= rect.right - rect.left;
height = rect.bottom - rect.top;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = hwnd;
LPDIRECT3D9 dx = Direct3DCreate9(D3D_SDK_VERSION);
dx->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device);
dx->Release();
}
函数需要知道目标窗体的句柄HWND hwnd以及目标区域width,height(可以通过GetWindowRect(HWND,LPRECT)来获取 )
函数使用了
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DDEVICE9 device;
两个关键变量。
d3pp是相应的参数,device是Direct3D设备对象。
LPDIRECT3D9 dx = Direct3DCreate9(D3D_SDK_VERSION);
是DirectX3D9接口,一切由此开始。
由此创建3D(虚拟)设备dx->CreateDevice(...)
至此,一个完整的DirectX示例程序构造完毕。运行结果如下
本文原创,博文地址
http://blog.csdn.net/fengyhack/article/details/41649257