分享
 
 
 

D3DFrame 入门

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

D3DFrame 入门

作者:Philip Taylor

发布日期:2000 年 5 月 15 日 将于 2000 年 6 月 19 日存档

下载本文的源代码(63.9K)

欢迎关注“Driving DirectX”的第二个问题,MSDN Online Voices 的 DirectX® 专栏。在下面几个专栏中,我想着重讨论 Direct3d(R) (D3D) for DirectX 7.0。对于 D3D 示例和 D3DFrame,好的切入点是“DirectX 软件开发工具包 (SDK)”应用程序框架。所有的 D3D 示例都使用 D3DFrame。

使用公用的框架 D3DFrame,为我们提供了公共平台,在此平台上我们可以展开各种功能的讨论。

一些图形芯片厂商使用 D3DFrame 的变体作为自己的示例;例如 ATI SDK 使用具有某些 ATI 专用附件的 D3DFrame 版本。使用公共框架提供了公共平台,在此平台上可以进行如何启用各种功能的讨论。使用公共框架也使我能够避开 D3D 的一般“基本知识”。这并不意味着 D3DFrame 可以作为产品代码;相反,它只是编写短小精悍示例的“方便”工具而已。

开卷语

在开始说明 D3DFrame 之前,让我们回顾一下 DirectX SDK 基础知识,并提供关于 SDK 开发的共同语言。请确保在您建立的环境中,查找头文件和库文件目录的命令是正确的。常见的问题是这些错误的命令,导致了许许多多编译和链接错误。安装 DirectX SDK 的默认路径是 \mssdk。在安装 SDK 时您可以控制该路径。运行时的头文件和库文件保存在 \mssdk\include 和 \mssdk\lib 中。

SDK HTML Help 是大体了解 DirectX 的主要资源,特别是对 D3D。我在解决了某些问题,以及有了某种想法之后,多次重读了该文档中的段落,于是有了温故知新的感觉,“喔,原来是这么回事。”示例代码是学习 DirectX 另一个最好的工具。“Direct3D 立即模式”示例代码保存在 \mssdk\samples\multimedia\d3dim 中。在 \d3dim 下面为 \bin、\include、\lib、\media 和 \src。以准备建立的形式存在的所有示例,可以在 \src 中找到,这取决于 \include 和 \lib,并且使用 \media 中的艺术内容。SDK 安装程序将预先建立的可执行文件植入 \bin 下。我强烈推荐用示例来进行试验,并检验使用它们列出的功能所需的代码。这是快速使用 D3D 的最快的方法。

调试 DirectX 应用程序可能是个难题。让我来介绍几种使工作更轻松的有用的小工具和技术。DXDiag SDK 实用工具提供有关 SDK 安装的信息。一定要对您的系统了如指掌。如果发现任何缺陷,则需要这些信息来报告缺陷。而且,一定要在 SDK 安装时选择调试运行时选项。如此就能保证在调试运行时进行开发,调试运行时包含错误检查和报告,这能真正帮助您解释代码在哪里出现了偏差。调试运行时允许设置启用运行时内部调试的报告级。“DirectX 控制面板”允许开发人员将报告级设置为 0 到 5。我在调试时一般设置为 3,而对于特别严重的缺陷要设置为 5。任何调试程序可以跟踪调试。Visual C++ GUI 调试程序提供了调试输出窗格,专门用来跟踪调试。Visual C++ GUI 调试程序,只有在使用下列系统时,才能调试全屏独占应用程序:

多监视器系统

远程调试

在这种思想指导下,通常明智的做法是产生代码并先在窗口模式下调试,然后再专注于全屏幕。

高级视图

让我们现在回到 DirectX 7.0 D3DFrame。D3DFrame 是 Direct3D SDK 示例的示例框架。如果您确实想了解示例是如何工作的 — 不是了解示例中列出的功能 — 必须对 D3DFrame 如何工作有基本了解。首先我会带您进入包含所有必须了解的内容的 D3DFrame 高级视图,并且使用 D3DFrame 编写自己的示例。对于象谚语中的猫一样好奇的人,我将就 D3DFrame 的主要部分给出更详细等级的概要介绍,以便解释如何提供应用程序接口。在随后的讨论中,我将在示例应用 D3DFrame 的同时介绍有关 D3DFrame 的更多内容。

图 1. D3DFrame 项目视图

D3DFrame 由 7 个模块组成:

D3DApp 展示了该示例使用的应用程序接口。

D3DFrame 提供了应用程序接口使用的框架,“在该框架下”进行 voodoo 会很顺利。

D3DEnum 包含对驱动程序、设备和模式的枚举支持。

D3DTextr 提供纹理支持。

D3DFile 提供 x-文件支持。

D3DMath 给出数学实用程序函数。

D3DUtil 包括剩下的其他各种有用的函数。

每个模块都是由一个 .cpp 源文件和 .h 头文件组成。源文件位于 d3dim\src。头文件位于 d3dim\include。框架库位于 d3dim\lib。鉴于本文的目的,我主要讨论 D3DApp 和 D3DFrame。

检查用户编写的函数

D3DApp 模块包含类 CD3DApplication。该类在 D3Dapp.h 文件中,为示例程序发布接口,如下所示:

牋牋 // 应用程序创建的可替代的 3D 场景函数

virtual HRESULT OneTimeSceneInit() { return S_OK; }

virtual HRESULT InitDeviceObjects() { return S_OK; }

virtual HRESULT DeleteDeviceObjects() { return S_OK; }

virtual HRESULT Render() { return S_OK; }

virtual HRESULT FrameMove( FLOAT ) { return S_OK; }

virtual HRESULT RestoreSurfaces() { return S_OK; }

virtual HRESULT FinalCleanup() { return S_OK; }

要使用示例框架创建新的 D3D 应用程序,只要创建新的项目和这些函数的新的实现;让我们为 D3Dframe 示例调用“公共接口”。这正是 D3D SDK 示例所做的。让我们看一看这些函数:

OneTimeSceneInit 允许示例完成一次性初始化任务,例如加载纹理和 x-文件,建立计算数值,生成程序的结构和类似的操作。通常,任何一次性的资源分配应该在这里完成。在每个应用程序执行周期中,OneTimeSceneInit 被调用一次。

InitDeviceObjects 给示例提供了初始化每个设备对象的机会。通常情况下,程序执行诸如将纹理位加载到设备表面、设置矩阵、设置光源以及填充顶点缓冲区等等操作。在初始化第一个设备以及每当设备有变化时,调用 InitDeviceObjects。

DeleteDeviceObjects 包含示例用于删除在 InitDeviceObjects 中创建的对象的代码。这两个函数是成对匹配的;一定要使您的设备专用的资源分配与删除匹配,否则每当设备改变时将泄漏内存。每当设备被取消时调用 DeleteDeviceObjects。

Render 是所有展现发生的地方。在这儿,清除框架缓冲区并调用 BeginScene/EndScene 对之间所有的展现代码。每帧调用 Render 一次。

FrameMove 提供了收集每帧动画任务的简便方法。更新矩阵,纹理调整,对象调整和其他随时间变化的动作都发生在 FrameMove。每帧调用 FrameMove 一次。

RestoreSurfaces 使示例测试丢失的表面并重新恢复它们,使应用程序可以继续执行。在表面因应用程序切换而丢失时,调用 RestoreSurfaces。

FinalCleanup 与 OneTimeSceneInit 配对,并提供一次取消一个应用程序的对象的方法。一定要使清除代码与初始化代码匹配,避免内存泄漏。

D3DFrame 内部

一旦掌握了应用函数的用途后,就该看一看什么东西会使它们准确运行。除了公共接口以外,类 CD3DApplication 有两个值得检查的部分。首先,类 CD3DApplication 包含下列成员函数:

HRESULT Initialize3DEnvironment();

HRESULT Change3DEnvironment();

HRESULT Render3DEnvironment();

VOID Cleanup3DEnvironment();

这些函数使用了公共接口和类 CD3DFramework7,来处理 D3D 应用程序的许多工作。

Initialize3DEnvironment 调用 CD3DFramework7->Initialize 来初始化示例框架,然后调用公共接口 InitDeviceObjects 来初始化设备专用对象。构造该代码用于处理在初始化过程中可能发生的错误。

Change3DEnvironment 为应用程序处理驱动程序、设备和/或模式的改变。它调用公共接口 DeleteDeviceObjects 释放旧设备的对象。然后建立新的设备状态,并调用 Initialize3DEnvironment 以创建新设备的环境。

Render3DEnvironment 完成五个重要的任务。首先,它检查合作状态以保证它可以继续展现。接着,它为随时间变化的动画调用公共接口 FrameMove。然后调用公共接口 Render 以完成绘制。如果启动了统计,则进行绘制。最后使用 CD3DFramework7->ShowFrame 显示帧。如果显示帧导致表面丢失情况,则框架和公共接口 RestoreSurfaces 都将被调用。

Cleanup3DEnvironment 调用 DeleteDeviceObjects 和 FinalCleanup 为应用程序结束做准备。

我们不要忘了 D3D 应用程序实际上是 Windows 应用程序。Win32 应用程序的内容核心隐藏在成员函数中:

virtual HRESULT Create( HINSTANCE, TCHAR* );

virtual INT Run();

virtual LRESULT MsgProc( HWND hWnd, UINT uMsg,

WPARAM wParam, LPARAM lParam );

在往下深入讲解之前,让我们看一看当使用 CD3DApplication 时 WinMain 变为什么。在本实例中,WinMain 是这样结束的:

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )

{

CMyD3DApplication d3dApp;

if( FAILED( d3dApp.Create( hInst, strCmdLine ) ) )

return 0;

return d3dApp.Run();

}

这是非常简单的 WinMain。并且隐藏 Create 和 Run 的动机是明确的,因为它们是 Winmain。MsgProc 是 Windows 消息处理程序。在内部,它们都使用 xxx3DEnvironment 函数和类 CD3DFramework7 来管理 D3D 应用程序以及 Windows 应用程序。

Create 使用模块 D3DEnum 提供的对枚举驱动程序、设备的支持,以及当前硬件的模式支持;它还选择一个默认值。然后调用公共接口 OneTimeSceneInit。一旦创建了用户对象,新的 CD3DFramework7 对象将实例化。需要注意一般的 Win32 细节,注册窗口类,然后创建窗口。最后,调用 Initialize3DEvironment 创建新设备的环境。

Run 完成两个重要的任务:Windows 消息循环处理和调用 Render3DEnvironment。Run 也为 WM_QUIT 消息和退出做准备。

MsgProc 是 Windows 消息的消息处理程序。它依赖并使用 xxx3DEvironment 函数和 CD3DFramework7 对象管理 Win32 和 D3D 应用程序。

现在,我已经大体介绍了 CD3DApplication 类的工作方式,以及它如何使用 CD3DFramework7 类,下面再深入研究 CD3DFramework7 和它的内部。

在类 CD3DFramework7 中主要的繁重任务是由下面两组成员函数完成的:

// 创建框架

HRESULT Initialize( HWND hWnd,GUID* pDriverGUID,

GUID* pDeviceGUID, DDSURFACEDESC2* pddsd,

DWORD dwFlags );

HRESULT DestroyObjects();

// 框架类的内部函数

HRESULT CreateZBuffer( GUID* );

HRESULT CreateFullscreenBuffers( DDSURFACEDESC2* );

HRESULT CreateWindowedBuffers();

HRESULT CreateDirectDraw( GUID*, DWORD );

HRESULT CreateDirect3D( GUID* );

HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*,

DWORD );

让我们先看第一组,Initialize 和 DestroyObjects。

Initialize 是创建框架内部对象的公共函数。它在内部建立一些状态,然后依赖 CreateEnvironment 去完成大部分艰难的工作。

DestroyObjects 仅仅释放 Initialize 中创建的所有 DirectX COM 对象。

CreateEnvironment 创建框架的内部对象。它决定设备的内存类型,然后调用 CreateDirectDraw。一旦它们不正常,CreateFullscreenBuffers 或 CreateWindowedBuffers 就会创建前台和后端缓冲区。最后,CreateDirect3D 创建 3-D 设备,并且 CreateZBuffer 创建并连接 Z-缓冲区。

鉴于理解 D3DFrame 的目的,我们不需要了解 CreateDirectDraw、CreateFullscreenBuffers、CreateWindowedBuffers、CreateDirect3D 或 CreateZBuffer 内部的详细实现。它们是直接相关的 — 这一句就够了。而对于那些想了解如何精确实现的人,源代码正等待他们去研究。

类 CD3Dframework7 中值得一提的最后几组函数提供了另外一些对展现的支持。它们是:

// 帮助展现的函数

HRESULT RestoreSurfaces();

HRESULT ShowFrame();

HRESULT FlipToGDISurface( BOOL bDrawFrame = FALSE );

VOID Move( INT x, INT y );

对于这些内容,我只是粗略带过,因为它们在先前检验的函数中使用,并且它们的用法可以轻松地从上下文导出。

要创建新的示例,现在只须实现一个类,诸如,下面所示的 CMyD3Dapplication:

class CMyD3DApplication : public CD3DApplication

{

protected:

HRESULT OneTimeSceneInit();

HRESULT InitDeviceObjects();

HRESULT DeleteDeviceObjects();

HRESULT Render();

HRESULT FrameMove( FLOAT fTimeKey );

HRESULT FinalCleanup();

static HRESULT ConfirmDevice( DDCAPS*, D3DDEVICEDESC7* );

public:

CMyD3DApplication();

}

完成之后,您就拥有一个有效的 D3DFrame 示例了。可以看见它在 D3D SDK 示例中反复出现。或者等下一个专栏。仅提供空实现功能将导致空的 D3D 应用程序。我已经完成它,将作为以后专栏的基础,这里我也提供了源代码。运行在窗口中的空 D3D 应用程序,如图 2 所示。

图 2. D3DFrameApp 示例

结束语

作为下面几部分的难题,请参阅关于下列内容的四篇 DirectX 7.0 Direct3D 文章:

虚拟光

两篇关于 Alpha 混合物的文章:

顶点中的 Alpha

纹理中的 Alpha

DotProduct3 展现

“虚拟光”一文将说明如何操纵 Direct3D 光,以避开大多数硬件施加的八光限制。Alpha 混合物文章将说明两种不同的透明技术:顶点中的透明和纹理中的透明。DotProduct3 文章将讨论非常好的 DOTPRODUCT3 操作符及其用途(提示,可将 DOTPRODUCT3 视为广义的从矢量到像素的查找函数)。每篇文章都包含一个基于 D3DFrame 的示例。

欢迎您提出反馈!欢迎您通过下面的地址,将您的评论、问题、主题思想或者您对本专栏涉及的主题的不同意见告诉我。不过,请不要期待单独回复或发给我请求支持的问题。请记住,Microsoft 有一个活动邮件的列表,DirectXDev,供志趣相投的开发者作为论坛来共享信息。Web 界面位于 http://DISCUSS.MICROSOFT.COM/archives/DIRECTXDEV.html(英文)。提问之前,请阅读 FAQ,它位于 http://msdn.microsoft.com/library/techart/dxfaq2.htm(英文)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有