posts - 7, comments - 6, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

第一章第二节:枚举

Posted on 2008-03-02 16:02 AntialiasingMan 阅读(882) 评论(0)  编辑 收藏 引用 所属分类: VB + DirectX

原文地址:http://directx4vb.vbgamer.com/DirectX4VB/Tutorials/DirectX8/GR_Lesson02.asp

译文地址:http://www.cnitblog.com/-AntialiasingMan-/archive/2008/03/02/40359.html

 

原文作者:Jack Hoxley

译文作者:AntialiasingMan

原文写于:2000年12月02日

译文写于:2008年02月25日

作者联系:Jollyieffers@Greenonions.netscapeonline.co.uk

译者联系:AntialiasingMan@gmail.com

本文附件:Graph_02.Zip [11 Kb]

 

内容概要:

1. 引言

2. 显示设备,适配器和图形分辨率的枚举

3. 硬件性能枚举

4. 勘误表


 

1.引言

一旦你习惯于枚举,就会知道它其实是一个相当基本的想法——如果你打算使用DirectX做可分配的应用程序的话,那么你就会再次使用到它。枚举是检测(硬件实际)能力的过程——你问它一些问题(关于它能做什么的问题),它就会告诉你它能或不能做你想让它做的事。就下面的教程而言,这种硬编码方式是相当可靠的,例如:设置分辨率和渲染器——就算(应用程序)不能工作,也没有真正遗漏掉什么,但是如果你要写一个真正的应用程序的话,就会有很多的人去使用(例如被发行的游戏),那么你就要使你的应用程序(的健壮性)坚如磐石。

一些游戏使用枚举出显示分辨率列表的方式来保证你可以正确无误的运行游戏,但它总是不会通知你使用的是何种方法。例如:应用程序可以查询你的硬件是否可能使用凹凸贴图,如果枚举返回的结果是true,那么你就可在游戏中使用凹凸贴图技术;如果返回的结果是false,那么游戏程序可以决定不使用凹凸贴图,也可以做一些其它的事情代替(如使用软件模拟凹凸贴图技术)。

这一课将向你介绍两种主要类型的枚举——显示模式/渲染器和硬件性能的枚举。虽然有非常之多的硬件性能需要检查,但在这里仅讨论上述两种。更多类型的枚举将在后续课程中被使用,并且与此相关的任何细节都会在那时再加以讨论,不过若你此时恰巧有DirectX 8的软件开发包,可以自己查看它们所有可能枚举的描述/信息。

 

2.显示设备,适配器和图形分辨率的枚举

首先,要知道是我们可以使用什么模式来初始化应用程序。窗口模式并不是很好的主意,但在全屏模式下你必须准备并设置好该硬件所支持的正确显示模式——否则,当你尝试创建设备是就会得到错误。当枚举显示模式和格式时,你需要记住下面这个基本的概念:

Adapter(适配器) » Device(设备) » Resolutions(分辨率) » Capabilities(硬件实际性能)

最初,我们需要查询可用的适配器,接着,选择其中的一个再查询它支持的设备驱动程序(硬件加速和软件加速),然后我们需要组合适配器和设备查询支持的分辨率和硬件性能。嗯,首先的首先还是来告诉你如何枚举适配器吧:

'// D3D需要为一个有效的Direct3D8对象的实例 
'// AdapterInfo为一个被定义成D3DADAPTER_IDENTIFIER8类型的变量 
Private Sub EnumerateAdapters()
  Dim I As Integer, sTemp As String, J As Integer
  '// 这个值不是1就是2 
  nAdapters = D3D.GetAdapterCount
  For I = 0 To nAdapters - 1
    '// 获取相关细节 
    D3D.GetAdapterIdentifier I, 0, AdapterInfo
    '// 获取当前适配器的名称--它被储存在一个较长 
    '// 的字符列表中,我们需要将它分解成一个字符串 
    '// 不要问我为何这么做,这样问似乎真的很傻 
    '// 重设字符串变量准备使用它 
    sTemp = ""
    For J = 0 To 511
      sTemp = sTemp & Chr$(AdapterInfo.Description(J))
    Next
    sTemp = Replace(sTemp, Chr$(0), "")
    cmbAdapters.Additem sTemp
  Next I
End Sub

你可以改变一下输出方式——在这个例子中是将所有相关信息储存到“cmbAdapters”组合框中的。上面的代码主要计算可用的适配器数量(几乎总是1),然后通过适配器数量循环搜集他们的信息(在AdapterInfo变量)。如果想了解更多有关适配器的东西,你还可以得到下面这些(有用)的信息:

Description:简要描述了打算显示给用户适配器的详细信息。

Driver:硬件使用的是什么驱动——同上,显示给用户(这通常是一个DLL文件名称)。

DeviceID一个代表芯片集类型的数字,如果未知其值为0。

DeviceIdentifier一组(4个变量)确定硬件使用的标识符。这个是个极好的用来识别硬件组件的变量。

现在我们能够识别适配器,可以看看它支持什么设备驱动。软件渲染是个高级的话题,并且还不太可靠,所以这里就忽略它吧。取而代之的是,我们将要检测硬件是否支持HAL(硬件加速)功能,REF(一调试工具)应始终处于可用状态,请仅仅假定我们可以访问它。

Private Sub EnumerateDevices()
  On Local Error Resume Next '// 我们要处理错误 
  Dim Caps As D3DCAPS8
  D3D.GetDeviceCaps combAdapter.ListIndex, D3DDEVTYPE_HAL, Caps
  If Err.Number = D3DERR_NOTAVAILABLE Then
    '// 没有硬件加速功能 
    cmbDevice.AddItem "Reference Rasterizer(REF)" '// REF要始终处于可用状态 
  Else
    cmbDevice.AddItem "Hardware Acceleration(HAL)"
    cmbDevice.AddItem "Reference Rasterizer(REF)" '// REF要始终处于可用状态 
  End If
End Sub

上述代码是以稍微随便的方式来检测硬件是否支持硬件加速功能的——但它工作的好并很简易。如果我们尝试从硬件加速设备中读取一些东西并且不存在的话,就会得到“D3DERR_NOTAVAILABLE”错误代码,这个时候,我们就知道只有REF设备可以使用的。代码将这些结果输出到一个组合框中,如果有必要,你可以改变这个输出结果的方式……

最后一件事是我们希望能够检查支持什么样的显示模式。当我们选择了一个适配器和设备驱动后就可以检查了。

Private Sub EnumerateDispModes(Renderer As Long)
  '// 清除任何存在于组合框中的项目 
  cmbRes.Clear
  Dim I As Integer, ModeTemp As D3DDISPLAYMODE
  '// 循环并搜集数据 
  For I = 0 To nModes - 1
    Call D3D.EnumAdapterModes(cmbAdapter.ListIndex, I, ModeTemp)
    '// 首先将显示模式分成两个部分--16位色部分和32位色部分 
    If ModeTemp.Format = D3DFMT_R8G8B8 Or ModeTemp.Format = D3DFMT_X8R8G8B8 Or ModeTemp.Format = D3DFMT_A8R8G8B8 Then
      '// 检查这个设备驱动是否有效且可以被访问 
      If D3D.CheckDeviceType(cmbAdapters.ListIndex, Renderer, ModeTemp.Format, ModeTemp.Format, False) >= 0 Then
        '// 添加到显示列表框中 
        cmbRes.AddItem ModeTemp.Width & "x" & ModeTemp.Height & "32 bit" & " [FMT:" & ModeTemp.Format & "]"
      End If
    Else
      If D3D.CheckDeviceType(cmbAdapter.ListIndex, Renderer, ModeTemp.Format, ModeTemp.Format, False) >= 0 Then
        cmbRes.AddItem ModeTemp.Width & "x" & ModeTemp.Height & "16 bit" & " [FMT:" & ModeTemp.Format & "]"
      End If
    End If
  Next I
  cmbRes.ListIndex = cmbRes.ListCount - 1
End Sub

一旦我们检索到显示模式的数目后,就可以通过循环来确定它们是哪种位深(16位色或32位色),然后我们再去检查当前选择的设备驱动和适配器是否能与Direct3D一起工作。如果一切都没有问题,将把结果输出到一个组合框中,用户(他/她)就可以随时选择想使用的(分辨率)了。请注意结尾处的“FMT: ”部分,这说明了在此位深度下具体的格式,16位色/32位色其实是不够确切的,所以我额外包含了在此位深度下更精确的格式信息。

当你看到这篇教程的示例代码时,就会发现每次改变适配器时,它都会重新计算分辨率和设备;每次选择一个新渲染器时,都会重新计算显示模式列表。

 

3.硬件性能枚举

最后的部分是要确定硬件支持的功能。如果你想使用一个并不常见且依赖于硬件的功能时,这就非常有用了(例如:使用边缘裁切技术)。硬件能力的枚举很简单,但是却有100多个 (或许是1000多个) 需要你去检查。

第一阶段事实上是检索设备的信息,不过这令人难以置信的简单:

'// 下面的代码假定D3D是Direct3D8对象的有效实例 
Dim Caps As D3DCAPS8 '// 拥有我们所需的全部信息…… 
D3D.GetDeviceCaps cmbAdapters.ListIndex, Renderer, Caps 

此时我们就有了一个持有所有信息的结构体(“Caps”),可以通过查询的方式来获知硬件的性能。你可以看到该结构体有许多不同的成员变量,它们都被列在了VB的对象浏览器中,不过你应该不太可能会猜出它们所有的含义。而DirectX8帮助文件会详细列出这些成员变量的含义——否则的话就只能等某人来告诉你 (在后续课程中我会解释一部分)或自己猜它们的含义了。

下面是如何获取部分硬件性能信息的代码:

If Caps.MaxActiveLights = -1 Then
  List1.AddItem "Maximum Active Lights: Unlimited"
Else
  List1.AddItem "Maximum Active Lights: " & Caps.MaxActiveLights
End If

List1.AddItem "Maximum Point Vertex Size: " & Caps.MaxPointSize
List1.AddItem "Maximum Texture Size: " & Caps.MaxTextureWidth & "×" & Caps.MaxTextureHeight
List1.AddItem "Maximum Primatives in one call: " & Caps.MaxPrimitiveCount

If Caps.TextureCaps And D3DPTEXTURECAPS_SQUAREONLY Then
  List1.AddItem "Textures must always be square"
End If
If Caps.TextureCaps And D3DPTEXTURECAPS_CUBEMAP Then
  List1.AddItem "Device Supports Cube Mapping"
End If
If Caps.TextureCaps And D3DPTEXTURECAPS_VOLUMEMAP Then
  List1.AddItem "Device Supports Volume Mapping"
End If

这里可获取更多硬件性能的信息,但是上面这些已经足够——除了指定不同的成员变量外,其它都是相同的。

强烈建议你下载这一课的示例代码,这样就可以清楚看到它是如何工作的了。请在这页的顶端下载代码。

假如你能理解所有这些知识,就可以继续学习第三课:2D图形第一部分——基础。

 

4.勘误表

吉尔提供了下面这些技巧:

第一部分的这些代码:

'// 获取当前适配器的名称--它被储存在一个较长 
'// 的字符列表中,我们需要将它分解成一个字符串 
'// 不要问我它们为何这么做,这样问似乎真的很傻 
'// 重设字符串变量准备使用它 
sTemp = ""
For J = 0 To 511
  sTemp = sTemp & Chr$(AdapterInfo.Description(J))
Next J
sTemp = Replace(sTemp, Chr$(0), "")

可以被替换成这样:

'// 获取当前适配器的名称。它被储存在一个字节数组里。
'// 这可能是因为在C++中(DirectX是为C++而开发的),
'// 字符数组就是字符串的缘故
sTemp = Trim$(Replace(StrConv(AdapterInfo.Description, vbUnicode), vbNullChar, " ")) 

还有一个要提的是:通过在Direct3D.GetAdapterIdentifier中指定常量参数D3DENUM_NO_WHQL_LEVEL (=2),就可以避免每个适配器的驱动程序为确定是否为“微软公司视窗硬件质量实验室”认证(WHQL)而延时一到两秒钟的情况,这个认证过程的返回值仅是个日期,对识别该适配器没有实际用途。据我的经验,任何时候都可以不使用认证检测代码。认证检测的时间是几秒钟,并不是几毫秒,它会严重影响应用程序的启动时间。



上面的教程提到了个开发DirectX应用程序时有用的工具——DirectX SDK 8 For VB(VB版DirectX软件开发包),但遗憾的是现在网上基本上找不到这个版本的下载了,不过功夫不负有心人,在我疯狂的Google下,还是被我在一个小网站上找到了,这个网站其实也是关于用VB开发DirectX应用程序的。不同之处是它提供给开发者一个游戏引擎,你可以免费使用这个游戏引擎来开发属于自己的VB多人在线游戏!

请点击这里下载DirectX SDK 8.1 For VB。

【难译语句中英对照表】:

原文 译文
A set of 4 variables determining the hardware in use. This is the best variable to use should you want to identify a piece of hardware. 一组(4个变量)确定硬件使用的标识符。这是个极好的用来识别硬件组件的变量。
只有注册用户登录后才能发表评论。