使用Direct3D的简单的多设备交换步骤如下:
1、创建一个窗口(Windows窗口)
2、初始化
1)创建Device
2)基于Device创建Surface(离屏表面)
3)创建Texture(纹理)
4)
获取指定层的纹理表面
3、画面渲染与保存
1)保存当前表面
2 ) 开始渲染
3 )
为设备设置一个新的颜色缓冲区
4)为纹理填充颜色Clear
5)将画面从纹理转移到表面
6)
从设备的交换链中检索一个备份缓冲区
7)进行屏幕显示
8)保存渲染内存的数据
4、第三设备数据交换和保存
1.创建一个窗口(不属于D3D的API)
建立一个Win32的窗口程序,就可以用于Direct3D的显示。程序的入口函数是WinMain(),调用CreateWindow()即可创建一个窗口。这一步是必须的,不然Direct3D绘制的内容就没有地方显示了。
2.初始化
1) 创建Device
这一步完成的时候,可以得到一个IDirect3DDevice9接口的指针。创建一个Device又可以分成以下几个详细的步骤:
(a) 通过 Direct3DCreate9()或者Direct3DCreate9Ex()创建一个IDirect3D9或者LPDIRECT3D9EX接口。
获取IDirect3D9接口的关键实现代码:
IDirect3D9 *m_pDirect3D9 = Direct3DCreate9( D3D_SDK_VERSION );
获取LPDIRECT3D9EX接口的关键代码:
LPDIRECT3D9EX d3dex = NULL;
Direct3DCreate9Ex(D3D_SDK_VERSION, &d3dex);
IDirect3D9接口是一个代表我们显示3D图形的物理设备的C++对象。它可以用于获得物理设备的信息和创建一个IDirect3DDevice9接口。例如,可以通过它的GetAdapterDisplayMode()函数获取当前主显卡输出的分辨率,刷新频率等参数,实现代码如下。
D3DDISPLAYMODE d3dDisplayMode;
lRet = m_pDirect3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3dDisplayMode );
由代码可以看出,获取的信息存储在D3DDISPLAYMODE结构体中。D3DDISPLAYMODE结构体中包含了主显卡的分辨率等信息:
/* Display Modes */
typedef
struct
_D3DDISPLAYMODE
{
UINT
Width;
UINT
Height;
UINT
RefreshRate;
D3DFORMAT Format;
} D3DDISPLAYMODE;
也可以用它的GetDeviceCaps()函数搞清楚主显卡是否支持硬件顶点处理,实现的代码如下。
D3DCAPS9 d3dcaps;
lRet=m_pDirect3D9->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&d3dcaps);
int
hal_vp = 0;
if
( d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ){
// yes, save in ‘vp’ the fact that hardware vertex
// processing is supported.
hal_vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
由代码可以看出,获取的设备信息存储在D3DCAPS9结构体中。D3DCAPS9定义比较长包含了各种各样的信息,不再列出来。从该结构体的DevCaps字段可以判断得出该设备是否支持硬件顶点处理。
(b) 设置D3DPRESENT_PARAMETERS结构体,为创建Device做准备。
接下来填充一个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;
/* FullScreen_RefreshRateInHz must be zero for Windowed mode */
UINT
FullScreen_RefreshRateInHz;
UINT
PresentationInterval;
} D3DPRESENT_PARAMETERS;
D3DPRESENT_PARAMETERS这个结构体比较重要。详细列一下它每个参数的含义:
BackBufferWidth:后台缓冲表面的宽度(以像素为单位)。
BackBufferHeight:后台缓冲表面的高度(以像素为单位)。
BackBufferFormat:后台缓冲表面的像素格式(例如:32位像素格式为D3DFMT:A8R8G8B8)。
BackBufferCount:后台缓冲表面的数量,通常设为“1”,即只有一个后备表面。
MultiSampleType:全屏抗锯齿的类型,显示视频没用到,不详细分析。
MultiSampleQuality:全屏抗锯齿的质量等级,显示视频没用到,不详细分析。
SwapEffect:指定表面在交换链中是如何被交换的。支持以下取值:
*D3DSWAPEFFECT_DISCARD:后台缓冲表面区的东西被复制到屏幕上后,后台缓冲表面区的东西就没有什么用了,可以丢弃了。
*D3DSWAPEFFECT_FLIP:后台缓冲表面拷贝到前台表面,保持后台缓冲表面内容不变。当后台缓冲表面大于1个时使用。
*D3DSWAPEFFECT_COPY:同上。当后台缓冲表面等于1个时使用。
一般使用D3DSWAPEFFECT_DISCARD。
hDeviceWindow:与设备相关的窗口句柄,你想在哪个窗口绘制就写那个窗口的句柄
Windowed:BOOL型,设为true则为窗口模式,false则为全屏模式
EnableAutoDepthStencil:设为true,D3D将自动创建深度/模版缓冲。
AutoDepthStencilFormat:深度/模版缓冲的格式
Flags:一些附加特性
FullScreen_RefreshRateInHz:刷新率,设定D3DPRESENT_RATE_DEFAULT使用默认刷新率
PresentationInterval:设置刷新的间隔,可以用以下方式:
*D3DPRENSENT_INTERVAL_DEFAULT,则说明在显示一个渲染画面的时候必要等候显示器刷新完一次屏幕。例如显示器刷新率设为80Hz的话,则一秒最多可以显示80个渲染画面。
*D3DPRENSENT_INTERVAL_IMMEDIATE:表示可以以实时的方式来显示渲染画面。
下面列出使用Direct3D的时候D3DPRESENT_PARAMETERS的一个最简单的设置。
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = SCREENW;
d3dpp.BackBufferHeight = SCREENH;
d3dpp.hDeviceWindow = window;
(c) 通过IDirect3D9的CreateDevice ()创建一个Device。
最后就可以调用IDirect3D9的CreateDevice()方法创建Device了。
CreateDevice()的函数原型如下:
HRESULT
CreateDevice(
UINT
Adapter,
D3DDEVTYPE DeviceType,
HWND
hFocusWindow,
DWORD
BehaviorFlags,
D3DPRESENT_PARAMETERS *pPresentationParameters,
IDirect3DDevice9** ppReturnedDeviceInterface
);
其中每个参数的含义如下所列:
Adapter:指定对象要表示的物理显示设备。D3DADAPTER_DEFAULT始终是主要的显示器适配器。
DeviceType:设备类型,包括D3DDEVTYPE_HAL(Hardware Accelerator,硬件加速)、D3DDEVTYPE_SW(SoftWare,软件)。
hFocusWindow:同我们在前面d3dpp.hDeviceWindow的相同
BehaviorFlags:设定为D3DCREATE_SOFTWARE_VERTEXPROCESSING(软件顶点处理)或者D3DCREATE_HARDWARE_VERTEXPROCESSING(硬件顶点处理),使用前应该用D3DCAPS9来检测用户计算机是否支持硬件顶点处理功能。
pPresentationParameters:指定一个已经初始化好的D3DPRESENT_PARAMETERS实例
ppReturnedDeviceInterface:返回创建的Device
下面列出使用Direct3D的时候CreateDevice()的一个典型的代码。
LPDIRECT3D9EX d3dex = NULL;
D3DPRESENT_PARAMETERS d3dpp;
...
d3dex->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
2) 基于Device创建一个Surface
通过IDirect3DDevice9接口的CreateOffscreenPlainSurface ()方法即可创建一个Surface(离屏表面。所谓的“离屏”指的是永远不在屏幕上显示)。CreateOffscreenPlainSurface ()的函数原型如下所示:
HRESULT
CreateOffscreenPlainSurface(
UINT
width,
UINT
height,
D3DFORMAT format,
D3DPOOL pool,
IDirect3DSurface9 ** result,
HANDLE
* unused
);
其中每个参数的含义如下所列:
Width:离屏表面的宽。
Height:离屏表面的高。
Format:离屏表面的像素格式(例如:32位像素格式为D3DFMT_A8R8G8B8)
Pool:D3DPOOL定义了资源对应的内存类型,例如如下几种类型。
D3D3POOL_DEFAULT: 默认值,表示存在于显卡的显存中。
D3D3POOL_MANAGED:由Direct3D自由调度内存的位置(显存或者缓存中)。
D3DPOOL_SYSTEMMEM: 表示位于内存中。
Result:返回创建的Surface。
Unused:还未研究。
下面给出一个使用Direct3D的时候CreateTexture()的典型代码。
LPDIRECT3DDEVICE9 d3ddev;
LPDIRECT3DSURFACE9 surface;
...
d3ddev->CreateOffscreenPlainSurface(100, 100, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL);
if (!SUCCEEDED(result)) return false;
3)创建Texture(纹理)
通过IDirect3DDevice9接口的CreateTexture()方法即可创建一个Texture(纹理)。CreateTexture()的函数原型如下所示:
HRESULT CreateTexture( [in] UINT Width, [in] UINT Height, [in] UINT Levels, [in] DWORD Usage, [in] D3DFORMAT Format, [in] D3DPOOL Pool, [out, retval] IDirect3DTexture9 **ppTexture, [in] HANDLE *pSharedHandle);
其中每个参数的含义如下所列:
Width:纹理的宽度,以像素为单位。。
Height:纹理的高度,以像素为单位。
Levels:纹理的数量。
Usage:使用可以是0,这表示没有使用价值。但是,如果需要使用的话,可以使用一个或多个D3DUSAGE常量的组合。一般与IDirect3D9::CreateDevice的行为标志相匹配。
Format: D3DFORMAT枚举类型的成员,描述纹理的格式。
Pool:D3DPOOL枚举类型的成员,描述了应该放置纹理的类型。
**ppTexture:指向IDirect3DTexture9接口的指针,表示所创建的纹理资源。
*pSharedHandle:用作不同d3d设备资源交换。一般将该参数设置为NULL。该参数可用于Windows Vista的Direct3D 9,以共享资源。
下面给出一个使用D3D的时候CreateTexture()的典型代码。
LPDIRECT3DTEXTURE9 pTexture = NULL;
d3ddev->CreateTexture(100, 100, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
下当不同的D3D设备进行资源交换时。
HANDLE SharedHandle = NULL;
LPDIRECT3DTEXTURE9 pTexture = NULL;
d3ddev->CreateTexture(100, 100, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, &SharedHandle);
4)获取指定层的纹理表面
HRESULT GetSurfaceLevel( [in] UINT Level, [out, retval] IDirect3DSurface9 **ppSurfaceLevel);
level :
识别纹理资源的层次。这个方法返回一个表面,以达到这个参数指定的级别。顶层的表面用0表示。
ppSurfaceLevel :
一个指向IDirect3DSurface9接口的指针的地址,表示返回的表面。
注意:
调用此方法将增加IDirect3DSurface9接口的内部引用计数。如果没有在结束时调用Release 释放资源在结束时将发生内存泄漏。
一般用法(获取顶层表面):
LPDIRECT3DSURFACE9 pSurface = NULL;
LPDIRECT3DTEXTURE9 pTexture = NULL;
pTexture->GetSurfaceLevel(0, &pSurface);