Clayman的专栏

It's all about XNA & GPU Programming

孙凌峰ID:soilwork
188060次访问,排名376好友0人,关注者10
soilwork的文章
原创 85 篇
翻译 15 篇
转载 0 篇
评论 324 篇
clayman的公告
嘿嘿 ^o^....
最近评论
CYF:哈哈,楼上的楼上真搞笑。
在企业应用中,WEB是主流,也是趋势。
企业应用与图形完全是两个领域,不相干的东西,何必扯在一起?完全没可比性。。。。。。。
skbaker:应该整理一下,形成系列,方便查找。
文章对入门级用户帮助很大
kobeair:每当我要放弃的时候,我都会来你的博客,回到你写这篇帖子。学习的过程很枯燥并且现在学习的时间越来越少。但是看到这篇文章有种莫名的冲动,而且不断的问自己:“别人能做到!为什么我不行?”
lijunjun:做WEB的人最终是会后悔的.
老鬼菠萝:继续~~~
文章分类
收藏
    相册
    blogs
    David Weller
    nVidia Developer blog
    Rico Mariani
    Shawn Hargreaves
    XNA Team blog
    XNA资源
    XNA Creators Club
    ZBuffer
    Ziggyware XNA Resources
    中国XNA开发网
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

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

    新一篇: 【翻译】Managed DirectX(第十二章上 ) | 旧一篇: 【翻译】Managed DirectX(第十一章)

    作者:clayman

    clayman_joe@yahoo.com.cn

    转载请注明作者,商业使用请联系我^_^

    理解框架

     

             首先创建工程,添加对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

     

    {

     

        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,那么就忽略这种设备组合类型。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    发表于 @ 2005年10月20日 17:52:00|评论(loading...)|编辑

    新一篇: 【翻译】Managed DirectX(第十二章上 ) | 旧一篇: 【翻译】Managed DirectX(第十一章)

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © clayman