游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3024|回复: 0

使用Managed DirectX编写游戏---理解sample framework之枚举设备

[复制链接]

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2005-10-20 17:43:00 | 显示全部楼层 |阅读模式
理解框架
        首先创建工程,添加对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;

        // 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的一些内容。还请大家多多支持。   [em19]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-22 08:58

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表