初始化Direct3D(步骤)
下面几点说明怎样初始化Direct3D。根据下边的步骤你能初始化Direct3D:
1. 获得一个IDirect3D9接口指针。这个接口用于获得物理设备的信息和创建一个IDirect3DDevice9接口,它是一个代表我们显示3D图形的物理设备的C++对象。
2. 检查设备的技术特性(D3DCAPS9),搞清楚主显卡是否支持硬件顶点处理。我们需要知道假如它能支持,我们就能创建IDirect3DDevice9接口。
3. 初始化一个D3DPRESENT_PARAMETERS结构实例,这个结构包含了许多数据成员允许我们指定将要创建的IDirect3DDevice9接口的特性。
4. 创建一个基于已经初始化好的D3DPRESENT_PARAMETERS结构的IDirect3DDevice9对象。它是一个代表我们显示3D图形的物理设备的C++对象。
请注意,本书使用主显示设备绘制3D图形,如果你的机子只有一块显卡,那它就是主显示设备。如果你有多个显卡,那么你当前使用的显卡将会成为主显示设备(如:用来显示Windows桌面的显卡)。
//
一) 获得IDirect3D9接口
先预习一下下面COM的内容
//组件对象模型(COM, Component Object Model)是一种能使DirectX独立于编程语言和具有向下兼容性的技术。我们通常把COM对象作为一个接口,你可以把它当作达到某种目的的C++类来使用它。当使用C++写DirectX程序的时候,COM的大部分细节对我们来说是透明。但是有一件事,我们必须知道,那就是我们通过某个特殊的COM接口的函数或指针获得了另一个COM接口指针,而不是通过C++的新关键字来创建它。当我们使用完某个接口后,调用它的Release方法比直接Delete它更好。COM对象具有它们自己的内存管理。
对COM来说还有很多细节可以了解,但是掌握这些细节对于我们有效的使用DirectX不是必须的。
注意:COM接口都具有前缀大写字母“I”,例如表示一个表面的COM接口叫做IDirect3DSurface9。
//
Direct3D的初始化是从获得一个IDirect3D9接口指针开始的。使用一个专门的Direct3D函数来完成这个工作是非常容易的,代码如下:
IDirect3D9* _d3d9; _d3d9 = Direct3DCreate9(D3D_SDK_VERSION); |
Direct3DCreate9的唯一一个参数总是D3D_SDK_VERSION,这可以保证应用程序通过正确的头文件被生成。如果函数调用失败,那么它将返回一个空指针。
IDirect3D9对象通常有两个用途:
1)设备列举:设备列举即为查明系统中显示设备的技术特性,显示模式、格式,以及其它每一种显卡各自支持的特性。
2)创建IDirect3DDevice9对象:创建代表物理设备的IDirect3DDevice9对象,我们需要利用这个物理设备的显示模式结构和格式来创建它。为了找到一个工作配置,我们必须使用IDirect3D9的列举方法。
二)检查设备的技术特性(D3DCAPS9)
//
顶点是3D图形学的基础,它能够通过两种不同的方法被处理,一种是软件方式(software vertex processing),一种是硬件方式(hardware vertex processing),前者总是被支持且永远可用,后者必须要显卡硬件支持顶点处理才可用。
使用硬件顶点处理总是首选,因为它比软件方式更快,而且不占用CPU资源,这意味CPU至少可以有更多的空闲时间进行别的计算。
注意:如果一块显卡支持硬件顶点处理的话,也就是说它也支持硬件几何转换和光源计算。
/
(1) 检测硬件顶点处理
IDirect3D9::GetDeviceCaps Method
Retrieves device-specific information about a device. //返回关于设备的信息
Syntax
HRESULT GetDeviceCaps(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DCAPS9 *pCaps
);
Parameters
Adapter
[in] Ordinal number that denotes the display adapter. D3DADAPTER_DEFAULT is always the primary display adapter. //一般使用D3DADAPTER_DEFAULT 指定要获得哪个显示适配器 //的特性
DeviceType
[in] Member of the D3DDEVTYPE enumerated type. Denotes the device type. //设备类型 //指///定设备类型(硬件设备(D3DDEVTYPE_HAL),软件设备(D3DDEVTYPE_REF))
pCaps [out] Pointer to a D3DCAPS9 structure to be filled with information describing the capabilities of the device. //返回一个已初始化的D3DCAPS9结构
Return Value
If the method succeeds, the return value is D3D_OK.
//如果成功返回D3D_OK
If the method fails, the return value can be one of the following values.
D3DERR_INVALIDCALL | The method call is invalid. For example, a method's parameter may have an invalid value. |
D3DERR_INVALIDDEVICE | The requested device type is not valid. |
D3DERR_OUTOFVIDEOMEMORY | Direct3D does not have enough display memory to perform the operation. |
Remarks
The application should not assume the persistence of vertex processing capabilities across Microsoft Direct3D device objects. The particular capabilities that a physical device exposes may depend on parameters supplied to IDirect3D9::CreateDevice. For example, the capabilities may yield different vertex processing capabilities before and after creating a Direct3D Device Object with hardware vertex processing enabled. For more information see the description of D3DCAPS9.
// Fill D3DCAPS9 structure with the capabilities of the // primary display adapter. //填充 D3DCAPS9 结构用检测到的显示适配器的特性
D3DCAPS9 caps; d3d9->GetDeviceCaps( D3DADAPTER_DEFAULT, // Denotes primary display adapter.指定主显卡 deviceType, // Specifies the device type, usually D3DDEVTYPE_HAL. //指定设备内容 一般使用D3DDEVTYPE_HAL. &caps); // Return filled D3DCAPS9 structure that contains // the capabilities of the primary display adapter. //返回一个已初始化的D3DCAPS9结构
// Can we use hardware vertex processing? int vp = 0; if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) { //检测硬件是否支持变换和灯光的 // yes, save in ‘vp’ the fact that hardware vertex // processing is supported. vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; } else { // no, save in ‘vp’ the fact that we must use software // vertex processing. vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //没有意见支持那么就选软件支持 } |
观察代码,我们使用变量vp来存储顶点处理类型。这是因为在稍后创建IDirect3DDevice9对象时要求指定其顶点处理的类型。
注意:标识符D3DCREATE_HARDWARE_VERTEXPROCESSING和D3DCREATE_SOFTWARE_VERTEXPROCESSING是预定义的值,它们分别代表硬件顶点处理和软件顶点处理。
技巧:若我们开发有一些新的,高级的特性的程序,在使用前我们总是先检查硬件是否支持这些特性。
注意:如果一个应用程序在你的机子上不能运行,说明它用到的一些特性可能你的显卡并不支持,可以试试把设备类型换成REF。
三)初始化一个D3DPRESENT_PARAMETERS结构实例
初始化过程的下一步是填充一个D3DPRESENT_PARAMETERS结构的实例。这个结构用于设定我们将要创建的IDirect3DDevice9对象的一些特性,它的定义如下:
typedef struct _D3DPRESENT_PARAMETERS_ { UINT BackBufferWidth; UINT BackBufferHeight; D3DFORMAT BackBufferFormat; UINT BackBufferCount; D3DMULTISAMPLE_TYPE MultiSampleType; DWORD MultiSampleQuality; D3DSWAPEFFECT SwapEffect; HWND hDeviceWindow; BOOL Windowed; BOOL EnableAutoDepthStencil; D3DFORMAT AutoDepthStencilFormat; DWORD Flags; UINT FullScreen_RefreshRateInHz; UINT PresentationInterval; } D3DPRESENT_PARAMETERS; |
下面介绍其比较重要的数据成员,至于更详细的信息,请查阅SDK:
BackBufferWidth——后备缓冲表面的宽度(以像素为单位)
BackBufferHeight——后备缓冲表面的高度(以像素为单位)
BackBufferFormat——后备缓冲表面的像素格式(如:32位像素格式为D3DFMT——A8R8G8B8)
BackBufferCount——后备缓冲表面的数量,通常设为“1”,即只有一个后备表面
MultiSampleType——全屏抗锯齿的类型,详情请看SDK
MultiSampleQuality——全屏抗锯齿的质量等级,详情看SDK
SwapEffect——指定表面在交换链中是如何被交换的,取D3DSWAPEFFECT枚举类型中的一个成员。其中D3DSWAPEFFECT_DISCARD是最有效的
hDeviceWindow——与设备相关的窗口句柄,你想在哪个窗口绘制就写那个窗口的句柄
Windowed——BOOL型,设为true则为窗口模式,false则为全屏模式
EnableAutoDepthStencil——设为true,D3D将自动创建深度/模版缓冲
AutoDepthStencilFormat——深度/模版缓冲的格式
Flags——一些附加特性,设为0或D3DPRESENTFLAG类型的一个成员。下列两个最常用的标志
全部的标志请查阅SDK:
D3DPRESENTFLAG_LOCKABLE_BACKBUFFER——设定后备表面能够被锁定,这会降低应用程序的性能
D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL——深度/模版缓冲在调用IDirect3DDevice9::present方法后将被删除,这有利于提升程序性能
FullScreen_RefreshRateInHz——刷新率,设定D3DPRESENT_RATE_DEFAULT使用默认刷新率
PresentationInterval——属于D3DPRESENT成员,又有两个常用标志,其余请查SDK:
D3DPRESENT_INTERVAL_IMMEDIATE——立即交换
D3DPRESENT_INTERVAL_DEFAULT——D3D选择交换速度,通常等于刷新率
填充示例如下:
D3DPRESENT_PARAMETERS d3dpp; d3dpp.BackBufferWidth = 800; d3dpp.BackBufferHeight = 600; d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; //pixel format d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hwnd; d3dpp.Windowed = false; // fullscreen d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; // depth format d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; |
四)创建IDirect3DDevice9对象
在填充完了D3DPRESENT_PARAMETERS结构后,我们就可以用下面的方法创建一个IDirect3DDevice9对象了:
HRESULT IDirect3D9::CreateDevice( UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface ); |
l Adapter——指定对象要表示的物理显示设备
l DeviceType——设备类型,前面说过
l hFocusWindow——同我们在前面d3dpp.hDeviceWindow的相同
l BehaviorFlags——设定为D3DCREATE_SOFTWARE_VERTEXPROCESSING或者D3DCREATE_HARDWARE_VERTEXPROCESSING
l pPresentationParameters——指定一个已经初始化好的D3DPRESENT_PARAMETERS实例
l ppReturnedDeviceInterface——返回创建的设备
例子:
IDirect3DDevice9* device = 0;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT, // primary adapter
D3DDEVTYPE_HAL, // device type
hwnd, // window associated with device
D3DCREATE_HARDWARE_VERTEXPROCESSING, // vertex processing type
&d3dpp, // present parameters
&device); // returned created device
if( FAILED(hr) )
{
::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
return 0;
}