📄 3d游戏编程入门经典.txt
字号:
adapterinfo.adapterinformation = ai.information; // information
// get list of all display modes on this adapter.
// also build a temporary list of all display adapter formats.
adapterformatlist.clear();
// now check to see which formats are supported
for(int i = 0; i < allowedformats.length; i++)
{
// check each of the supported display modes for this format
for each(displaymode dm in ai.supporteddisplaymodes [allowedformats[i]])
{
if ( (dm.width < minimumwidth) ||
(dm.height < minimumheight) ||
maximumwidth) ||
maximumheight) ||
(dm.refreshrate < minimumrefresh) ||
maximumrefresh) )
{
continue; // this format isn’t valid
}
// add this to the list
adapterinfo.displaymodelist.add(dm);
// add this to the format list if it doesn’t already exist
if (!adapterformatlist.contains(dm.format))
{
adapterformatlist.add(dm.format);
}
}
}
// get the adapter display mode
displaymode currentadaptermode = ai.currentdisplaymode;
// check to see if this format is in the list
if (!adapterformatlist.contains(currentadaptermode.format))
{
adapterformatlist.add(currentadaptermode.format);
}
// sort the display mode list
adapterinfo.displaymodelist.sort(sorter);
// get information for each device with this adapter
enumeratedevices(adapterinfo, adapterformatlist);
// if there was at least one device on the adapter and it’s compatible,
// add it to the list
0)
{
adapterinformationlist.add(adapterinfo);
}
}
manager类中的adapters属性是一个集合,包含了关于系统中每一个“适配器(adapter)”的信息。术语“适配器”稍微有些用词不当,但基本的定义是显示器能够连接的任何设备。例如,假设您有一个ati radeon 9800 xt图形卡。这里只有一个图形卡,但是可以将两个不同的显示器连接到它上面(分别通过视频图形适配器[vga]端口和后面的数字可视接口[dvi]端口连接)。连接两个显示器后,这个卡将具有两个适配器,即两个不同的设备。
提示:
通过将设备创建为一个适配器组,可以让单个卡在所有“不同”设备间共享资源。该方法具有几个限制。关于该主题的更多信息,请参考directx文档。
该循环至少有一个迭代,具体依赖于您的系统。在存储了当前活动适配器的基本信息之后,代码需要找该适配器在全屏模式中支持的所有显示模式。您将注意到,可以直接利用当前正在枚举的适配器信息来枚举所支持的显示模式,这就是该段代码实际做的工作。
当枚举一种显示模式时,首先检查它是否位于某个特定范围之中。大多数设备支持广泛的模式,但当前不会使用到其中很多种模式。多年以前,您可能看到过一些运行在320×200全屏窗口中的游戏,但在今天已经没有这样的游戏(除非您碰巧在玩一个手持机,例如gameboy advance)。样本框架所选择的默认最小尺寸是640×480的窗口,没有设置最大尺寸。
警告:
样本框架选择了640×480作为最小尺寸,但是这不意味着在全屏模式中样本框架将选择这一最小尺寸。对于全屏模式,框架选择最常用的尺寸,往往是桌面的当前尺寸(它很可能不是640×480)。
在满足框架需求的支持模式添加到程序清单后,添加当前显示模式,因为该模式总是被支持的。最后,icomparer接口的一个实现对这些模式排序。如程序清单3.5所示。
程序清单3.5 排序显示模式
public class displaymodesorter : icomparer
{
///
/// compare two display modes
///
public int compare(object x, object y)
{
displaymode d1 = (displaymode)x;
displaymode d2 = (displaymode)y;
d2.width)
return +1;
if (d1.width < d2.width)
return -1;
d2.height)
return +1;
if (d1.height < d2.height)
return -1;
d2.format)
return +1;
if (d1.format < d2.format)
return -1;
d2.refreshrate)
return +1;
if (d1.refreshrate < d2.refreshrate)
return -1;
// they must be the same, return 0
return 0;
}
}
icomparer接口允许对数组或者集合执行一个简单快速的排序算法。该接口提供的惟一方法是compare方法,该方法返回一个整型值:如果左边的项大于右边的项,则返回+1;如果左边的项小于右边的项,则返回–1;如果两个项相等,则返回0。在该实现中,显示模式的宽度具有最高优先级,然后是高度、格式和刷新率。当比较诸如1280×1024和1280×768这样的两种模式时,这种顺序保证了比较的正确性。
模式排序后,调用enumeratedevices方法。您可以在程序清单3.6中看到该 方法。
程序清单3.6 枚举设备类型
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?
0)
{
// yes, add it
adapterinfo.deviceinfolist.add(deviceinfo);
}
}
// turn exception handling back on
directxexception.enableexceptions();
}
在查看这段代码时,应当注意两点。您能够猜到它们是什么吗?如果您猜到是对directxexception类的调用,则您将赢得重奖。第一个调用关闭了managed directx程序集中异常的抛出。您可能希望知道这么做的目的,答案是性能的提高。捕获和抛出异常是非常昂贵的操作,该代码段具有大量抛出异常的项。您系望枚举代码能够快速地执行,因此所有发生的异常都被忽略。在该函数结束后,恢复标准的异常处理。这段代码看上去非常简短,因此您很可能会问:“为什么这段代码易于抛出异常?”
我非常高兴您能够问这个问题,幸而,我恰好有一个好的答案。最常见的情形是设备不支持directx 9。或许您没有升级视频驱动,或许当前的视频驱动没有必要的代码路径。这可能是当前卡本身太老无法使用directx 9。很多时候,可以通过包含一个不支持directx 9的pci显卡,来允许系统的multimon功能。
该方法中的代码尝试获得这个适配器的功能,并枚举它的各种组合,并且尝试获得每一种可利用的设备类型的信息。可能的设备类型如下:
● 硬件—— 最常见的设备类型。绘图由硬件(显卡)处理。
● 引用—— 不管是否存在具有处理能力的硬件都能够以direct3d运行库所支持的任意设置绘图的设备。所有的处理以软件形式完成,这意味着在游戏中这种设备类型非常慢。
● 软件—— 除非已经编写了一个软件rasterizer(如果是这样,您的能力已经超出了本书所教授的内容),您将不会使用该选项。
假设在枚举期间发现某种设备设置的组合,则将它存储在一个列表中。枚举类存储的少量列表将在后面样本框架创建设备时被使用。如程序清单3.7所示的enumeratedevicecombos方法。
程序清单3.7 枚举设备组合
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -