第三章 Direct3D学习之DirectX的初始化

三哥讲堂继续更新。今天带领大家将一个普通的win32程序变成一个Directx程序。

还记得第一章介绍过的最简单的win32程序,我们今天在第一章(http://www.cnblogs.com/leexuzhi/archive/2011/10/10/2205391.html)代码的基础上来创建一个Direct3D程序。主要了解win32和directx的联系和区别。

首先,创建一个空的win32工程,按照第一章的讲述编写一个win32窗口程序。这个程序由winmain函数开始,并且使用winsdk api来创建一个空的窗口。其实一个win sdk也可以用来画图像,为什么我们还要用Directx来编写3D游戏呢。这是因为winsdk是通过操作系统来驱动的,操作系统的处理速度虽然不能说慢,但是相对于3D游戏这样实时性要求非常高的程序来说,winsdk的处理速度根本就不能满足。举个例子来说,把一台电脑比作我们的国家,操作系统就是我们的党中央。3D游戏程序好比是国家的某个地方在对外战争,如果在打仗的时候事事请示党中央,这个节奏大家应该能想象的到。这个时候就需要一个临时特权机构来管理这个战区。这个特权机构就是我们的Directx,它可以跳过操作系统直接操作底层硬件。官方称这个机制为COM,初学者不要纠结com这个词,你可以把它理解为JAVA中的接口,为什么要这么做呢,因为Directx要通过相同的函数来驱动每个厂家的硬件。所以这不可能由微软一家来完成,微软只是规定了每个函数要实现什么样的功能,具体的实现要硬件厂商自己解决,然后兼容到windows系统中。。。。OK!再说就跑题了,开始我们今天的课程,内容不多,主要是理解D3D的机制,以便之后的课程能轻松学习。

首先我们需要一个D3D设备IDirect3DDevice9,它就相当于临时特权机构中的总司令官,几乎所有的渲染操作都通过它来完成,所以我们可以创建一个全局的IDirect3DDevice9指针,以便我们随时可以使用到D3D设备。

IDirect3DDevice9* Device;

初始化一个Directx需要以下几步:

//
// Init D3D:
//

HRESULT hr = 0; //标识结果的数据类型 用于判断函数是否成功,或是有何种错误
Device = 0;

// Step 1: Create the IDirect3D9 object.
// 第一步 创建一个IDirect3D9 对象

IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

if( !d3d9 )
{
::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
return false;
}

// Step 2: Check for hardware vp.
// 第二步 检测硬件定点

D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);

int vp = 0;
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

// Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
//第三步 填充 D3DPRESENT_PARAMETERS 结构体 ,该结构体包含IDirect3DDevice9的一些特性

D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width;//D3D的画图宽度,我们将这个数设为窗口宽度就可以
d3dpp.BackBufferHeight = height;//D3D的画图高度,我们将这个数设为窗口高度就可以

d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = m_hWnd;
d3dpp.Windowed = true;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


// Step 4: Create the device.
//第四步 创建IDirect3DDevice9设备

hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT, // primary adapter
D3DDEVTYPE_HAL, // device type
m_hWnd, // 程序的窗口句柄,用来把设备和窗口联系起来
vp, // vertex processing
&d3dpp, // 刚刚创建的设备特征
&Device); // 函数成功将返回一个设备到此参数

if( FAILED(hr) )
{
// try again using a 16-bit depth buffer
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
m_hWnd,
vp,
&d3dpp,
&Device);

if( FAILED(hr) )
{
d3d9->Release(); // done with d3d9 object
::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
return false;
}

上述的代码夸张点说,属于一百年不用改的东西,原封不动的拷到程序中,当然是在创建窗口之后调用。然后我们有了自己的D3D设备可以开始之后的渲染过程了。渲染的原理其实画屏幕的一帧,所以我们的渲染函数要在程序主循环中调用,因此我们选择将它添加到消息循环中。改写第一章的消息循环函数如下。

WPARAM EnterMsgLoop()
{
MSG msg;
::ZeroMemory(&msg, sizeof(MSG));

static long lastTime = (long)timeGetTime();

while(msg.message != WM_QUIT)
{
if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) //该函数为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else
{ //如果没有系统消息,则处理程序逻辑
long currTime = (long)timeGetTime();//当前时间的毫秒数
long timeDelta = (currTime - lastTime);//与上一次程序走到这里时的时间毫秒数之差

if(timeDelta<33){//如果两次差小于33毫秒(这样可以将游戏固定在最大30帧),则处理一些游戏的逻辑部分,比如AI运算等

//可以在此添加逻辑代码

}else{//开始本帧的渲染
Display((float)timeDelta);//渲染函数
lastTime = currTime;//将本次时间赋值给上一次时间变量
}


}
}
return msg.wParam;
}

渲染函数代码如下:

bool Display(float eventime)
{
if( Device ) // Only use Device methods if we have a valid device.
{
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ccccff, 1.0f, 0);//用一个颜色(0x00ccccff)来覆盖整个画面,作用就是清除屏幕上一帧的画面,以便填加下一帧的画面
Device->BeginScene();//开始渲染

//这里添加真正的渲染代码,这是D3D最需要学习的部分,我们在以后的课程中慢慢讲解,需要现在理解的是,这时的渲染其实是在硬件缓存中做的,还没有真正的显示在屏幕上
Device->EndScene();//结束渲染
// Swap the back and front buffers.
Device->Present(0, 0, m_hWnd, 0);//将device缓存中的画面真正的画到屏幕上
}
return true;
}

到此为止我们的DirectX就初始化完成。运行程序效果:

posted @ 2011-10-16 16:12  重甲土拨鼠  阅读(939)  评论(0编辑  收藏  举报