网页功能: 加入收藏 设为首页 网站搜索  
使用Managed DirectX编写游戏(二) 理解sample framework之枚举设备
发表日期:2007-03-27作者:[转贴] 出处:  

理解框架

  首先创建工程,添加对DirectX程序集的引用。接下来,把sample framework添加到工程中。我们把这些文件放到一个单独的文件夹中,在解决方案管理器中点击右键---添加---新建文件夹,并把它命名为 framework。右键点击新创建的文件夹,选择添加现有项,导航到SDK的\Samples\Managed\Common目录下,把每一个文件添加到项目中。

  好了,现在回到我们刚才创建的Form1.cs文件中来,可以看到大部分自动生成的代码都是用来创建Windows Form应用程序的。因此删除所有代码,并添加如下代码:

using System;
using System.Configuration;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;

public class GameEngine : IDeviceCreation
{
    /// <summary>
    /// Entry point to the program. Initializes everything and goes into a
    /// message processing loop. Idle time is used to render the scene.
    /// </summary>
    static int Main()
    {
        using(Framework sampleFramework = new Framework())
        {
            return sampleFramework.ExitCode;
        }
    }
}

  这里有三个需要注意的地方 。首先,我们只留下了一个修改过的main方法。由于其他代码都是窗体设计器为Windows Form程序生成的,所以完全可以删除它们。其次,代码现在还不能通过编译,应为GameEngine类还有两个接口没有实现。第三,这段代码实际上什么也没做。

  首先我们来实现IDeviceCreation接口,你将通过他来控制枚举和创建device。在这里,枚举的含义包括检查目标机器上有几块显卡、几个显示器、可以支持多少种显示模式、控制刷新率等等。

public bool IsDeviceAcceptable(Caps caps, Format adapterFormat,Format backBufferFormat, bool windowed)
{
    if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType,adapterFormat, Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
        return false;
    if (caps.MaxActiveLights == 0)
        return false;
    return true;
}

public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
{
    if ( (caps.DeviceCaps.SupportsPureDevice) && ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
        settings.BehaviorFlags |= CreateFlags.PureDevice;
}

  第一个方法将在device初始化时调用,用来检查device最低能支持什么特性(capability)。当sample framework在系统上枚举设备时,他会对所找到的每一种可能组合调用这个方法。注意看这个方法是如何决定返回值的。他的第一个参数包含了大量关于制定设备的信息,可以帮你决定它是否是你希望创建的device类型。接下来的参数一个是关于后备缓冲的,另一个则是关于设备格式。最后一个参数则是检查是否支持窗口模式。虽然大多数游戏都是运行在全屏模式,但在窗口模式之下调试程序会方便一些。这个方法默认情况下将返回true,但他还做了两个特别的检查。首先,检查它是否支持alpha混合(创建游戏的用户界面将用到他)。其次,检查是否支持动态灯光----没有灯光物体看起来会很单调而且不真实,所以至少使用一个灯光。

  再来看第二个方法:在创建device之前调用它,来修改创建设备的参数。Setting参数包含了框架为device所制定的设置,你可以自由的修改这些设置。需要特别注意的是sample framework不会验证这些设置的有效性,因此,你需要自己来验证。

  在继续之前,还有一件事情要做。由于sample framework包含一些unsafe的代码块,因此,必须允许工程中包含不安全代码:


现在,可以使用框架来枚举设备了。首先,为GameEngine类添加一个构造函数,把从main方法中创建的sample framework实例作为参数:

private Framework sampleFramework = null;
public GameEngine(Framework f)
{
    // Store framework
    sampleFramework = f;
}

  在调用了sample framework之后,他所做的第一件事就是枚举系统设备。在工程中,打开之前添加的dxmutenum.cs文件。这个文件包含了枚举设备的所有代码。由于知道如何以及为什么枚举设备是很重要的,我们来仔细看一下这些代码。

  首先注意到Enumeration是不能被实例化的,塔顶每一个方法和成员也都是静态的。因为就目前来说,你的硬件图形设备在运行时不太可以改变,所以枚举的过程在程序一开始运行一次就可以了。

  大多数的枚举过程都是在创建device之前,通过sample framework调用Enumerate方法开始的。这个方法所接受的唯一参数,就是我们至今为止在GameEngine类中实现的接口。在枚举设备状态组合的时候,需要调用IsDeviceAcceptable方法来判断这个设备状态是否应该添加到正确的设备列表中。那么到底是如何来枚举设备的呢?实际上大多数功能都是通过Manager类来完成的。如果你熟悉普通的DirectX API,那么这个类实际上就是COM接口Idirect3D9的映射。(注:枚举设备的过程这里不再讲解,请看我以前翻译过的文章)

把所有符合框架要求的显示模式都保存到一个列表中,最后,通过实现Icomparer接口对他们进行排序。

public class DisplayModeSorter : IComparer
{
    public int Compare(object x, object y)
    {
        DisplayMode d1 = (DisplayMode)x;
        DisplayMode d2 = (DisplayMode)y;
        if (d1.Width > d2.Width)
            return +1;
        if (d1.Width < d2.Width)
            return -1;
        if (d1.Height > d2.Height)
            return +1;
        if (d1.Height < d2.Height)
            return -1;
        if (d1.Format > d2.Format)
            return +1;
        if (d1.Format < d2.Format)
            return -1;
        if (d1.RefreshRate > d2.RefreshRate)
            return +1;
        if (d1.RefreshRate < d2.RefreshRate)
            return -1;
        return 0;
    }
}

这里的算法很简单,大家自己看吧。保存了可用的显示模式之后,调用EnumerateDevices方法。

private static void EnumerateDevices(EnumAdapterInformation adapterInfo, ArrayList adapterFormatList)
{
    // Ignore any exceptions while looking for these device types
    DirectXException.IgnoreExceptions();
    // Enumerate each Direct3D device type
    for(uint i = 0; i < deviceTypeArray.Length; i++)
    {
        // Create a new device information object
        EnumDeviceInformation deviceInfo = new EnumDeviceInformation();

        // Store the type
        deviceInfo.DeviceType = deviceTypeArray[i];

        // Try to get the capabilities
        deviceInfo.Caps = Manager.GetDeviceCaps((int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType);

        // Get information about each device combination on this device
        EnumerateDeviceCombos( adapterInfo, deviceInfo, adapterFormatList);

        // Do we have any device combinations?
        if (deviceInfo.deviceSettingsList.Count > 0)
        {
            // Yes, add it
            adapterInfo.deviceInfoList.Add(deviceInfo);
        }
    }
    // Turn exception handling back on
    DirectXException.EnableExceptions();
}

  观察一下这段代码,你应该注意到并且记住两件事。猜猜是什么?如果答案是DirectXException类方法调用,那么恭喜,答对了。  DirectXException.IgnoreExceptions();方法关闭了Managed DirectX程序集中所有异常抛出。你可能会问这样做有什么好处,答案是性能的提升。捕捉和抛出异常是系统花费很大的操作,而这段代码有可能导致多个异常的抛出。你只希望快速的完成枚举,因此,暂时忽略所有异常,在这段代码结束的时候,再打开异常机制。虽然这里的代码很简单,但你可能会问问什么会导致异常。

  很高兴你问到了这个问题,那么我们就来仔细讨论一下吧。最常见的问题就是你的设备不支持DirectX 9。有可能你没有更新驱动程序,或者当前的驱动程序没有正确安装。也有可能是你的显卡太老了无法使用DirectX 9。通常PCI接口的显卡都不能很好的支持DirectX 9了。

  这段代码尝试获得关于显卡能力的信息,并为适配器枚举合适的组合。可用的设备类型有以下几种:Hardware, Reference, software。

  假设枚举时找到了合适的设备设置组合,就把他保存到一个列表中。Enumeration类为之后创建device保存了一些列表,观察 EnumerateDeviceCombos方法。注意,如果IsDeviceAcceptable方法返回false,那么就忽略这种设备组合类型。

~~~~~~~~~~~~~~~~~~~厚道的分隔线~~~~~~~~~~~~~~~~

  原来打算这个系列的文章是翻译Beginning 3D Game Programming,不过这几天仔细看了一下,有部分内容与kick start中的内容重复了,而且几个我也没有几个例子的源码和资源文件,所以打算综合Introduction to 3D Game Engine Design Using DirectX 9 and C#的内容通过我自己的组织来写一些教程。原来的翻译的kick start主要集中在讲解Managed DirectX API,而这个系列打算写如何把这些API组织起来,以及MDX中一些相应的性能技巧。首先推出的是对SDK中sample framework的一些内容。还请大家多多支持。
我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 使用Managed DirectX编写游戏(二) 理解sample framework之枚举设备
本类热点文章
  DDraw和D3D立即模式编程手册
  矩阵求逆的快速算法
  本地化支持:OGRE+CEGUI中文输入:OGRE方..
  Direct3D中实现图元的鼠标拾取
  3D场景中的圆形天空顶
  OpenGL显卡编程
  一种高效的基于大规模地形场景的OCCLUS..
  一个完善的读取3DS文件例子
  如何制作一个可控制的人体骨骼模型
  Direct3D 入门之我见
  Slope(斜坡) 法线生成算法,在地形渲染..
  新手翻译的FAQ--可视和转换(学opengl两..
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.01106