Microsoft DirectX 8 开发人员常见问题
Microsoft DirectX 8 开发人员常见问题
:
Microsoft DirectX 8 开发人员常见问题
摘要:本文对与 Microsoft DirectX 8.0 版有关的常见开发问题进行解答,其中包括有关 Direct3D、DirectSound 和 DirectPlay 的章节。
目录
一般性 DirectX 开发事宜
Direct3D
一般问题
几何(顶点)处理
性能调谐
Direct3DX 实用程序库
DirectSound
DirectPlay
一般性 DirectX 开发事宜
我在试图编译示例时,为何得到那么多错误消息?
您可能没有将 include 路径设置正确。许多编译器(包括 Microsoft® Visual C++®)包含 SDK 的一个较早版本,因此如果您的 include 路径首先搜索标准的编译器 include 目录,则您会得到不正确版本的头文件。为解决这一问题,请确保 include 路径和库路径被设为搜索 DirectX include 和库路径。另请参见 SDK 中的 dxreadme.txt 文件。如果您安装 DirectX SDK 而您又在使用 Visual C++,则可以选择让安装程序为您设置各个 include 路径。
我得到关于全局唯一标识符 (GUID) 符号重复或缺失的连接器错误,怎么办?
您使用的各种 GUID 应该得到一次性定义,且只能定义一次。如果您在插入 DirectX 头文件之前用 #define 定义 INITGUID 符号,则会插入 GUID 的定义。因此,你应确保只对一个编译单元进行此类操作。这一方法的一个替代方案就是用 dxguid.lib 库进行连接,其中包含所有 DirectX GUID 的定义。 如果您使用这一方法(建议),则您永远不要通过 #define 定义 INITGUID 符号。
我能否将指针指向一个到较低版本号的 DirectX 接口?
不能。DirectX 接口属于 COM 接口。 这意味着不要求将较高版本号的接口从相应的低版本号导出。因此,获得到 DirectX 对象的一个不同接口的唯一安全方法就是使用接口的 QueryInterface 方法。该方法是标准的 IUnknown 接口的一部分,所有 COM 接口必须从其导出。
我能在同一应用程序中将 DirectX 8 组件和 DirectX 7 或更早的组件混用吗?
您可以随意混用不同版本的“不同组件”;例如,您可以在将 DirectPlay 8 和 DirectDraw 7 用在同一应用程序中。但是,您通常不可以将“同一组件”的不同版本混用在同一应用程序中;例如,您不能混用 DirectDraw 7 和 Direct3D 8 (鉴于这些实际上是同一组件,因为 DirectDraw 已被含入 DirectX 8 的 Direct3D)。
Release 或 AddRef 方法的返回值有何含义?
返回值将是对象的当前参照计数。但是,COM 规范声明,您不应依赖该返回值;该值通常仅供用于调试目的。您观察到的值可能并非所期待的,因为各种其它系统对象可能保持着对你所创建的 DirectX 对象的参照。 因此,您不应编写反复调用 Release 的代码,一直到参照计数为零,因为此时可以将对象释放,即使另一组件可能仍旧在对其进行参照。
我释放 DirectX 接口的次序很重要吗?
应当没有问题,因为 COM 接口是参照计数的。 但是,在某些 DirectX 版本中,接口的释放次序有一些已知的缺陷。 安全起见,在可能的情况下,建议您以与创建时相反的次序释放接口。
智能指针是什么,我要用它们吗?
智能指针是一个 C++ 模板类,旨在封装指针功能。尤其有一些标准智能指针类,用于封装 COM 接口指针。这些指针自动进行 QueryInterface,而不是进行造型,并替您处理 AddRef 和 Release。您是否使用这些指针,大体上是个人偏好。如果您的代码包含大量的接口指针复制操作,即使用多重 AddRefs 和 Releases,则智能指针可能会使您的代码更加简洁和不易出错。否则,不用也罢。Visual C++ 包含一个标准的 Microsoft COM 智能指针,是在 "comdef.h" 头文件中定义的(请在帮助中查找 com_ptr_t)。
我在调试 DirectX 应用程序时遇到问题,能提示一下吗?
调试 DirectX 应用程序时最常见的问题就是试图在 DirectDraw 表面被锁定时进行调试。这一情形会在 Microsoft Windows® 9x 系统上导致 "Win16 Lock" ,因此而无法绘制调试窗口。在锁定表面时指定 D3DLOCK_NOSYSLOCK 旗标,通常会消除该现象。Windows 2000 没有这一问题。在开发一个应用程序时,最好运行调试版本的 DirectX 运行时(在安装 SDK 时进行选择);该版本进行某些参数证实,并将一些有用的消息输出到调试程序的输出窗口。
如何正确地检查返回代码?
使用 SUCCEEDED 和 FAILED 宏。 DirectX 方法可以返回多个成功和失败代码,因此一个简单的 "==D3D_OK" 或类似的测试结果不总是够用的。
DirectDraw 有何变化?
DirectDraw 的大多数功能现已被含入新的 Direct3D8 接口。编制单纯 2D 应用程序的开发人员可能会希望继续使用旧的 DirectX 7 接口。对于编制带有某些 2D 元素的 3D 应用程序的开发人员,鼓励其使用 Direct3D 替代程序(例如点对象和公告牌纹理),因为这会改善性能和灵活性。
我如何禁用 ALT+TAB 以及其它的任务切换功能?
请切勿这样做。
有什么值得推荐的对 COM 进行解释的书吗?
有什么关于一般性 Windows 编程的书吗?
- Programming Windows (《Windows 编程》),Charles Petzold 著(Microsoft Press 出版)
- Advanced Windows (《Windows 进阶》),Jeffrey Richter 著(Microsoft Press 出版)
Direct3D
一般问题
我在何处可以找到有关 3D 图形技巧的信息?
Direct3D 能够仿真硬件未提供的功能吗?
Direct3D 包含有软件光栅器吗?
没有。Direct3D 现在支持插件式软件光栅器。但是,目前并不默认提供任何软件光栅器。
Direct3D 几何代码使用 3DNow! 和/或 Pentium III SIMD 指令吗?
我如何防止透明的像素被写到 z 缓冲区?
您可以借助高于或低于某一给定门限的 alpha 值来将像素滤除。您通过描绘状态 ALPHATESTENABLE、ALPHAREF 和 ALPHAFUNC 来控制这一操作。
模板缓冲区是什么?
我如何使用模板缓冲区来描绘阴影量?
Texel (特塞尔)对齐规则是什么?我怎样才能得到一一映射?
D3DCREATE_PUREDEVICE 旗标有何用途?
我如何使用颜色键控?
DirectX 8 并不支持颜色键控。您应当换用 alpha 混色/测试,大体上这是一个更加灵活的技巧,没有与颜色键控相关的一些问题。
我如何枚举多监视器系统中的所有显示设备?
几何(顶点)处理
D3DVERTEX 等等顶点类型有何变动?
不再显式支持“预罐装”的顶点类型。多重顶点流系统允许对顶点数据进行更加灵活的装配。如果您想使用其中一个“传统”的顶点格式,则您可以建立一套相应的 FVF 代码。
我对顶点流不大清楚,其工作原理如何?
Direct3D 对从一个或多个顶点流馈入流水线的每个顶点进行组装。只有一个顶点流时,就对应于 DirectX 8 以前的老模型,即顶点来自单独一个源。借助 DirectX 8,不同的顶点组件可以来自不同的源;例如,一个顶点缓冲区可能含有位置和法线,而另一个则含有颜色值和纹理坐标。
顶点着色器是什么?
顶点着色器是一个用于处理单一顶点的过程。这是借助一种类似于汇编的简单语言来进行定义的,由 D3DX 实用程序汇编为一个 Direct3D 接受的令牌流。顶点着色器接受单独一个顶点和一组常量值的输入,并输出一个顶点位置(在剪贴空间),还可能输出一组用于光栅化的颜色和纹理坐标。请注意,在您有一个定制的顶点着色器时,顶点组件就不再有任何由 Direct3D 施加给它们的语义,而顶点就只是由您所创建的顶点着色器进行解释的任意数据。
顶点着色器进行透视划分或剪裁吗?
不。顶点着色器在已变换的顶点位置的剪贴空间输出一个纯系坐标。透视分割和剪裁是由后着色器自动进行的。
我能借助顶点着色器生成几何图形吗?
顶点着色器无法创建或消灭顶点;其一次只对单一顶点进行操作,即作为输入接收一个未经处理的顶点,而输出单独一个经过处理的顶点。因此可以将其用于操作已有的几何图形(应用变形或进行外观变换操作),但实际上无法生成新的几何图形。
我能将一个定制的顶点着色器应用到固定功能几何流水线(或者进行相反的操作〕吗?
不能。您必须选择其一。如果您正在使用一个定制的顶点着色器,则您负责进行整个顶点变换操作。
如果我的硬件并不支持定制的顶点着色器,我可以使用吗?
可以。Direct3D 软件顶点处理引擎完全支持定制的顶点着色器,且性能指标出奇的高。
我如何确定硬件是否支持我的定制的顶点着色器?
能够硬件支持顶点着色器的设备被要求填充 D3DCAPS8::VertexShaderVersion 字段,以指示其所支持的顶点着色器的版本级别。所有声称支持某一级别的顶点着色器的设备,必须支持所有合法的顶点着色器,这些顶点着色器符合针对该级别或较低级别的规范。
有多少个常量寄存器可以用于顶点着色器?
要求支持 DX8 顶点着色器的设备至少支持 96 个常量寄存器。设备的支持能力可能会超过这一最低数目,且可以通过 D3DCAPS8::MaxVertexShaderConst 字段进行报告。
我可以在带有不同纹理坐标的顶点之间共享位置数据吗?
该情形的一个通常示例就是一个立方体,其中您想为每个面使用一个不同的纹理。很不幸,答案是不行;目前还还不能独立索引每个顶点组件。即使是多顶点流,也是所有的顶点一起索引。
在我提交一列带索引的原语时,Direct3D 是处理缓冲区中所有的顶点,还是只处理我索引过的顶点?
在使用软件几何流水线时,Direct3D 首先转换您所提交的范围中的所有的顶点,而不是“根据要求”按照索引对其进行转换。这对于密集数据(即其中使用了大多数的顶点)效率更高,尤其是在可以使用 SIMD 指令时。如果您的数据比较松散(即很多顶点未被使用),则您可能需要考虑重新排列您的数据,以避免多余的转换。在使用硬件几何加速时,顶点经常是根据需要进行转换的。
索引缓冲区是什么?
索引缓冲区与顶点缓冲区极其类似,但其包含的是用于 DrawIndexedPrimitive 调用的索引。强烈建议您尽可能使用索引缓冲区,而不要使用原始的由应用程序分配的内存,其道理与顶点缓冲区相同。
我注意到 32 位的索引现在是一种支持类型;我可以将其用在所有的设备上吗?
不可以。你必须检查 D3DCAPS8::MaxVertexIndex 字段,以确定设备所支持的最大索引值。该值必须大于 216-1 (0xffff) 才能支持 D3DFMT_INDEX32 类型的索引缓冲区。另外请注意,某些设备可能支持 32 位的索引,但其所支持的最大索引值却小于 232-1 (0xffffffff);这样,应用程序必须遵从设备所报告的限制。
将多重顶点流用于固定功能流水线有何限制?
固定功能流水线要求每条顶点流水线是一个严格的 FVF 子集,即根据一个完整的 FVF 声明预定的。 另外请注意,您必须遵从 D3DCAPS8::MaxStreams 字段所报告的流水线数目的限制(现在的许多设备和/或驱动程序仅支持单一流水线)。
性能调谐
我如何能够改善我的 Direct3D 应用程序的性能?
- 批处理大小:Direct3D 已为大批量原语进行过优化。一次调用所能发送的多边形越多,其效果也就越好。凭经验而论,建议平均每次调用 100 个以上的多边形。低于该水平,您可能不会得到最好的性能,而高于该水平,您收到的效果会递减,且可能会与并行事项发生冲突(参见下面的论述)。
- 状态更改:更改描绘状态这种操作可能会很昂贵,尤其是在更改纹理时。因此,每帧所作的状态更改应尽可能地少,这一点很重要。另外,请尽量降低对顶点或索引缓冲区的更改。
注意:在 DirectX 8 中更改缓冲区已不在象在以前版本中那样昂贵了,但依旧建议尽量避免更改顶点缓冲区。
- 并行:如果能够安排描绘与其它处理同时进行,则您可以充分利用系统性能。这一目标可能会与降低描绘状态更改的目标相抵触。您需要在进行批处理以降低状态更改和较早将数据推出到驱动程序以达到并行目的之间找到一个平衡点。以循环方式使用多个顶点缓冲区,会有助于并行功能。
- 纹理上载:将纹理上载到设备会消耗带宽并导致与顶点数据争用带宽。 因此,不要占用过多的内存这一点很重要,因为这会强制缓存方案为每一帧上载过多的纹理。
- 顶点缓冲区和索引缓冲区: 您应当一直使用顶点缓冲区和索引缓冲区,而不是由应用程序分配的普通内存块。顶点缓冲区和索引缓冲区的锁定语义至少可以避免多于的复制操作。对于某些驱动程序,顶点缓冲区和索引缓冲区可能是更理想的存储器中的某些区域(可能是在视频或 AGP 存储器中),供硬件进行访问。
- 状态宏锁定:这些是在 DX 7.0 中推出的,为将一系列的状态更改(包括照明、材质和矩阵更改)记录成一个宏提供了一个机制,该宏然后就可以通过单一的调用来重放了。这有两个优势:
- 您进行一次调用而不是多次调用,从而降低调用开销。
- 有感悟能力的驱动程序可以对状态更改进行预分析和预编译,从而使到图形硬件的提交速度快得多。
状态更改可能依旧很昂贵,但使用状态宏至少会有助于降低部分成本。
- 仅使用单独一个 Direct3D 设备:如果您需要描绘到多个目标,则请使用 SetRenderTarget。如果您是要创建一个带有多个 3D 窗口的窗口化程序,则请使用 CreateAdditionalSwapChain API。运行时已为单一设备进行过优化,使用多个设备时会有相当多的速度折扣。
我应当使用哪些基本类型(条形、扇形、列表等)?
在真实数据中遇到的许多网格,都具有多个多边形共享顶点的特性。为将性能最大化,最好将所转换的顶点中的重复率降低,并横跨总线将其发给描绘设备。使用简单的三角列表根本实现不了任何顶点共享,因而这是最不理想的方法。这一点已很清楚。然后所要作的选择就是使用条形和扇形(暗示多边形之间的具体连接关系),还是使用索引列表。在数据自然归入各种条形和扇形的情况下,这些就是最为合适的选择,因为发给驱动程序的数据被降至最低。但是,将网格分解条形和扇形经常会造成大量分离块,暗示有大量的 DrawPrimitive 调用。因此,最富效率的方法通常是使用带三角列表的单独一个 DrawIndexedPrimitive 调用。使用索引列表的另一个优势就是,这在连续三角形仅共享单独一个顶点时也有益处。总而言之,如果您的数据自然归入各种较大的条形和扇形,就使用条形和扇形,否则就使用索引列表。
如果我要生成动态数据,怎样才算是较好地使用顶点缓冲区了呢?
- 借助 D3DUSAGE_DYNAMIC 和 D3DUSAGE_WRITEONLY 使用旗标以及 D3DPOOL_DEFAULT 缓冲池旗标来创建一个顶点缓冲区。(如果您正使用软件顶点处理功能的话,还要指定 D3DUSAGE_SOFTWAREPROCESSING。)
- I = 0。
- 设置状态(纹理、描绘状态等)。
- 检查缓冲区内是否有空间,即 i.e.I + M <= N? (其中 M 是新顶点的数目)。
- 如果为真,则借助 D3DLOCK_NOOVERWRITE 对 VB 进行 Lock (锁定)。这告知 Direct3D 和驱动程序,您将要添加顶点,而并不修改您先前批处理过的顶点。 因此,如果当时正在进行一项 DMA 操作,则并不中断该操作。否则,转至 11。
- 在 I 处填充 M 个顶点。
- Unlock (解锁)。
- 调用 Draw[Indexed]Primitive。对于未经索引的,请将 I 用作 StartVertex 参数。对于已编索的基本类型,请确保索引指向顶点缓冲区的正确部分(要做到这一点,使用 SetIndices 调用的 BaseVertexIndex 参数可能最为容易)。
- I += M。
- 转到 3。
- 好,空间已用尽,就让我们开始一个新的顶点缓冲区。 我们不想使用同一个顶点缓冲区,因为有可能有一个 DMA 操作正在进行之中。我们将这一情形告知 Direct3D,方法是借助 D3DLOCK_DISCARD 旗标,将“同一个”顶点缓冲区锁定。 这意思是,“你可以给我一个新的指针了,因为我已用完旧的指针,不再在意旧的内容。”
- I = 0。
- 转至 4 (或 6)。
Direct3DX 实用程序库
D3DX 图象文件加载器函数支持哪些文件格式?
D3DX 图象文件加载器函数支持 BMP、TGA、PNG、JPG、DIB、PPM 和 DDS 文件。
D3DX 中的文字描绘函数好象失效,我的操作有什么问题吗?
使用 ID3DXFont::DrawText 功能时的一个常见错误就是为颜色参数指定一个零 alpha 组件,从而导致完全透明(即不可见)的文本。对于完全不透明的文本,请确保色彩参数的 alpha 成分完全饱和 (255)。
对于字体描绘,我应当使用 ID3DXFont 还是 SDK 框架 CD3DFont 类?
ID3DXFont 类能够处理字间距,因为它使用 GDI 来绘制字符串。这可能会有点慢,因为每次均需要调用 GDI。
CD3DFont 设计用于加速和使用纹理化基本类型来绘制字符。它只能处理简单字体,并不支持 ID3DXFont 可用的全套格式选项,但适用于简单而快速的显示,诸如帧速率计数等等。
对于产品代码,您可能需要实施您自己的字形描绘功能,即借助纹理化基本类型和/或基于 GDI 的方案(带避免重新绘制的缓存功能)。
DirectSound
我的应用程序启动时,为何为发出一阵净噪声?我注意到其它应用程序也有这个问题。
DirectPlay
我如何确保我的游戏将能够与各种 Network Address Translator (网络地址转换器,NAT) 和 Internet Connection Sharing (Internet 连接共享,ICS)设置正常工作?
NAT 和 ICS 是较为复杂的主题,在 MSDN 上的另一篇文章中有更详尽的论述。但是,下列提示可以作为很好的一般性指导:
- 通过 IDirectPlay8Client 和 IDirectPlay8Server 接口,使用一种客户端-服务器而不是点对点网络拓扑。
- 将服务器放在清澈的 Internet 上,而不是在一个 NAT 后面。
- 直接枚举游戏端口,而不是使用 DPNSVR。
- 不要在您的消息中内嵌 IP 地址或端口号。
有关点对点游戏、将服务器驻于 NAT 后面的事宜,以及针对各种不同的 Windows 操作系统上的 ICS 的具体建议,请参考更详尽的文档。
DPNSVR 是作什么用的?
IDirectPlay8LobbyClient::Initialize 为何返回 DPNERR_NOTALLOWED?
DirectPlay 不允许每个进程有一个以上的前端客户端或应用程序,因而试图创建多个客户端会导致返回这一错误。
Microsoft DirectX 8 开发人员常见问题相关推荐
- DirectX 8开发人员常见问题
目 录 General Direct3D DirectSound DirectPlay 本文对与Microsoft DirectX 8.0版有关的常见开发问题进行解答,其中包括有关Direct3D.D ...
- 开发人员必备的13项技能
原文地址:13 Technical Skills You Should Have As A Developer 如果你是计算机科学专业的学生或正在修读软件工程师或软件开发人员的课程,那么你需要掌握一些 ...
- SQL Server开发人员应聘常见问题妙解
SQL Server开发人员应聘常见问题妙解 目前在职场中很难找到非常合格的数据库开发人员.我的一个同事曾经说过:"SQL开发是一门语言,它很容易学,但是很难掌握." 在面试应聘的 ...
- Microsoft Windows Workflow Foundation 入门:开发人员演练
有关向 Windows 平台添加工作流支持的初步知识 Microsoft Windows Workflow Foundation (WWF) 是一个可扩展框架,用于在 Windows 平台上开发工作流 ...
- 针对开发人员的Microsoft SQL Server元数据
Microsoft SQL Server 2016最近在关系数据库管理系统(RDBMS)中处于领先地位. 高性能,安全性,分析和云兼容性的结合使其成为领先的RDBMS . SQL Server 201 ...
- Microsoft Quantum Katas帮助开发人员探索使用Q#实现量子计算
Microsoft根据"软件招式"(Code Katas)这一理念,开源了一个称为"Quantum Katas"的项目.该项目意在帮助开发人员迈出使用Q#语言实 ...
- Windows Mobile 6 中为开发人员提供的新功能(1)
Windows Mobile 6 中为开发人员提供的新功能(1) 2007年06月10日 星期日 10:29 Jim Wilson,JW Hedgehog, Inc. 摘要 Windows Mobil ...
- 面向.NET开发人员的Dapr——前言
Foreword 前言 With the wave of cloud adoption well underway, there is a major shift happening towards ...
- Adreno GPU上的DirectX应用开发简介 (4)
Adreno GPU上的DirectX应用开发简介 (4) 3 工具和资源 3.1 Microsoft Direct3D11.1 Tools 3.2 Qualcomm Adreno SDK 3.3 Q ...
- 知方可补不足~开发人员可以自己定义VS文件模版
团队开发,最重要的是什么? 统一的规范,对于一个团队,在开发项目之前,必须要先告诉大家项目的规范是什么,而开发人员在实际当中再去执行这个规范,对于规范事实上是个很宏观的概念,它可能有很多版本,呵呵,如 ...
最新文章
- STM32如何计算RTC时钟异步预分频和同步预分频
- 华为mate8怎么申请云闪付_华为消费者管培生面试问题分享
- 在Django中使用PostgreSQL数据库
- 鸿蒙开发-基础组件介绍及chart组件使用
- 漫画:什么是二叉堆?(修正版)
- 大数据技术原理与应用-概述
- 阿里云朱照远:边缘计算,无处不在
- 终于我还是没忍住,用Python爬了一波女神
- c++------------之---【虚函数和抽象基类的应用】
- Extjs 从grid中导出Excel表格。后台为C#(绝对好用)(按照自己的需求修改版本)...
- [No0000174]Spring常用注解(收藏大全)
- 盘点各种程序员常用的框架,看看你是否落伍了?
- MySQL数据库知识大全
- 非常详细的STM32 CAN通信的贴子,从总线细节到编程实现
- [CareerCup] 9.8 Represent N Cents 美分的组成
- 红帽linux安装intel(R) wifi link 5100 AGN总结
- oracle 给表授权grant
- Linux下ESC键无法退出
- ExtentReports生成自动化测试报告
- 《PeopleWare》读书笔记