技术文档(Document)
 

作者:clayman 

 
 

深入Managed DirectX9(四)

 
 
目录:
  第一部分
  第二部分
  第三部分
  第四部分
  第五部分
  第六部分
  第七部分
  第八部分
  第九部分
  第十部分
  第十一部分
  第十二部分
  第十三部分
  第十四部分
  第十五部分
  第十六部分
  第十七部分
  第十八部分
  第十九部分
  第二十部分
  第二十一部分
  第二十二部分
  第二十三部分




选择正确的Device
  The number of possible permutations when cretion a device is quite staggering. 如今,市场里有大量不同类型的显示卡,记住每种显卡所支持的特性几乎时不可能的。你应该询问device,让它告诉你它所支持的特性。我们接下来将讨论:
  枚举系统里所有的适配器(adapter)
  枚举每一个device所支持的格式
  确定所列举的设备功能


枚举系统里的适配器
  如今的大多数系统都支持多显示器。虽然这还不是主流配置,但多显示器确实很有用,并且变的越来越流行。在过去,这是高端图形卡专有的功能。但现在ATI,nVidia以及Matrox都支持让多台显示器共享一块显卡的多头显示技术。

  Direct3D的device必须指定给每一个适配器。在这里,你可以把“适配器”理解为一块链接了特定显示器的显卡。比如ATI Radeon 9700的显卡只是一块物理适配器,但它有两个显示器接口(DVI和VGA),因此,在Direct3D里,它有两个适配器。也许你不知道选哪一个,甚至不确定有多少device在运行游戏的系统里,那么怎样来检测它们并且选择正确的一个呢?

  在Direct3D里,一个叫做Manager的静态类可以简单的完成以上任务:枚举适配器和device的信息;获得系统里device所支持特性的信息。

  Manager类最重要的属性就是适配器的列表。在许多地方都会用到这个属性。它有一个“count”成员储存了系统里适配器的数量。因此,可以直接用索引访问适配器(e.g. Manager.Adapters[0]), 也可以枚举出系统里所有适配器。

  用一个简单的程序测试一下这个功能,它将以树状结构显示出系统里的适配器,以及他们所支持的显示模式:
  1.创建新的C# Windows Formd工程;
  2.添加DirectX组件;
  3.创建一个TreeView控件,并且占满整个窗口:把Dock属性设置为fill
  好了,现在该加入扫描每一个适配器,显示所支持的每一种显示模式的函数了:
  Public void LoadGRaphics()
  {
      foreach(AdapterInformation ai in Manager.Adapters)
      {
          treeNode root = new TreeNOde(ai.Information.Description);
          treeNode driverInfo = new TreeNode(string.Format(“Driver information:{0} – {1}”, ai.Information.DriverName, ai.Information.DriverVersion) );
          root.Node.Add(driverInfo);
          treeNode displayMode – new TreeNodeJ(string.Format(“Vurrent Display Mode:{0}×{1}×{2}”, ai.CurrentDisplayMode.Width, ai.CurrentDisplayMOde.Height, ai.CurrentDisplayuMode.Format) );
          foreach(DisplayMode dm in ai.SupportedDisplayModes)
          {
              treeNode supportedNode = new TreeNode(string.Format(“Supported:{0}×{1}×{2}”, dm.Width, dm.Height, dm.Format) );
              displayMode.Nodes.Add(supportedNode);
          }
          root.Nodes.Add(displayMode);
          treeView1.Node.Add(root);
      }
  }

虽然代码看起来有一点点多,但它所做的事情实际上是非常简单的。你可以先分来来看看我们都作了些什么。首先,我们枚举系统里的适配器。C#的Foreach迭代器使这个过程异常的简单。对每一个适配器来说,这个循环都只执行一次,并且用给定的适配器填充AdapterInformation结构。观察一下AdapterInformation结构,有以下几个成员

Public struct AdapterInformation
{
    int adapter;
    DisplayMode CurrentDisplayMode;
    AdapterDetails Information;
    AdapterDetails GetWhqlInformation();
    DisplayModeEnumerator SupportedDisplayModes;
}

  这里adapter成员指创建device时的适配器序数。序数是一个基于0的索引,并且序数的个数等于系统里适配器的个数。两个返回AdapterDetails结构的成员都使用同一个方法返回同样的结果。对Information成员来说,Windows Hardware Quality Labs(WHQL)并不返回细节,而GetWhqlInformation却可以。获得这些信息要花费一些代价及事件,所以我们把它分成两部分。

  AdapterDetails结构保存了适配器的大量信息,包括对适配器自身的描述以及驱动信息。虽然这不是一定会用到的,但应用程序却能依次作出对硬件类型的判断。

  剩下的两个成员返回DisplayMode结构。这些结构包含了大量的显示模式,包括显示的高度和宽度,刷新率以及使用的格式。CurrentDisplayMode返回当前的显示模式,SupportedDisplayModes返回适配器所支持的模式的列表。

  So,我们用从Information属性获得的对device的描述作为tree view的根节点。然后加入了一个表示驱动程序名字以及版本号的子节点。同样也加入了一个显示当前显示模式的子节点,并且在这个子节点下列出了所有支持的显示模式。

  运行程序,可以看到包含了所有支持模式的列表。填充present parameter结构时,这些模式都能当作正确的后备缓冲格式。每一个枚举出来的模式后面都有一个以固定模式显示的字符串(e.g X8R8G8B8),字母和数字交替出现。字母表示了数据的类型,数字表示这种类型的数据所占的位数。下边是常见的字母:

  A――alpha B――blue X---unused L----luminance R----red P----palette G---green
  (虽然有很多种格式,但只有几种能正确的用于后备缓冲以及显示模式。可用于后备缓冲的模式包括:A2R10G10B10, A1R5G5B5, A8R8G8B8, X1R5G5B5, X8R8G8B8, R5G5B5; Display formats can be the same as the back buffer formats, with the exception of those that contain an alpha component . The only format that can be used for a display weith alpha is A2R10G10B10,and even then that’s only in full-screen mode.)

  每种类型所占的位数加起来,就是这种格式的总大小。比如X8R8G8B8,就是32位的格式,红、绿、蓝各8位,还有8位没有使用。

  至今为止,我们获得了要创建的适配器序数,要支持的后备缓冲格式,那么关于device构造函数的其他参数呢?很幸运,Manager类有我们所需的一切。


判断哪一个设备是可用的
  manager类有许多方法可以用来检测你的适配器是否支持一个特定的功能。比如,你需要检测适配器是否支持一种特殊的格式,但又不想枚举所有可能的适配器以及格式,那你就可以用manager类来解决这个问题。使用如下的方法:

    pubic static System.Boolean CheckDeviceType(int adapter, DeviceType checkType, Format DisplayFormat, Format backBufferFormat, bool windowed, int result)

  这个方法可以快速的检测出device是否支持你将要使用的格式。第一个参数是你要检测的适配器序数;第二个是要检测的device类型,但这个值大多数情况下都被设置为DeviceType.Fardware。接着指定将使用的后备缓冲类型和显示格式,以及是否需要全屏显示。最后一个参数是可选的,如果使用的话他将返回关于这个方法的一个整数(即COM中的HRESULT)。如果这是一个有效的设备,则方法返回true,否则为false。当你预先知道要使用的格式使,这个方法是很有用的。
(应该注意到,在窗口模式,后备缓冲的格式不一定要匹配于显示格式,只要你的硬件支持适当的颜色转换就可以了。不论你的硬件是否支持这种功能,CheckDeviceType方法都会返回适当的结果,应该使用manager类的CheckDeviceFormatConversion方法来判断是否支持这种转换。也可以在窗口模式下使用Format.Unknown。全屏模式下不需要这种转换。)


检测Device的功能(capabilities)
  我们把每一个device能完全用硬件实现的功能都叫做“capability”,或简称做“Cap”。Direct3D有一个Caps结构可以列出device所支持的每一种可能的capabilities。创建了device之后,就可以使用device的Caps属性来检测他所支持的特性,但如果在创建设备之你就想知道device所支持的特性该怎么办呢?自然,Manager类也有一个方法能完成这个任务。

  现在,先前的程序里加一点点代码来获得系统里每一种适配器的capabilities。我们将不再使用tree view来显示这些capabilities,应为这可能包含了数百种capabilities。最好的方法是使用一个text box。回到windows form的设计模式,把tree view的Dock属性改为“Left”,把宽度改为现在的一半;入text box控件,把Dock属性设置为“Fill”,Multiline设置为true,Scrollbars设置为“both”。

  现在你可能想为程序添加一个钩子(hook),这样在选择了一个适配器之后,textbox里的数据也会更新。使用tree view的AfterSelect事件,添加如下代码:

private void treeView_1AfterSelect(object sender, System.Windows.Forms.TreeViewEcentArgs e)
{
    if (e.Node.Parent == null)
    {
        textBox1.Text = e.Node.Text + “Capabilities: \r\n\r\n” + Manager.GetDeviceCaps(e.Node.Indes, DeviceType.Hardware).ToString().Replace(“\n”, “\r\n”);
    }
}
如你所见,相当简单。运行一下看看结果吧。


  下载本章源码

(第四部分完,下一章我们将讨论一些简单的渲染技术了,包括vertex buffer,纹理)
 
 

        


本站中所有文章以及图形均为作者本人、公司所有,本站所有资讯仅供参考,若有任何损失本站概不负责,请自行斟酌。
Copyright © 2001-2005 游戏开发资源网(GameRes.com) All Rights reserved.
This site is optimized for at least 1024x768 resolution (hi-color) viewing with a browser that supports style sheets.