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; } } } |
图1:添加引用对话框 |
Microsoft.DirectX.Direct3D.Device device = null; |
private Device device = null; |
/// 设备初始化的时候调用。这段代码检查设备最小的性能, /// 如果没有通过检查,就返回false public bool IsDeviceAclearcase/" target="_blank" >cceptable(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) { // 这个应用程序没有使用任何get方法,它被设计成在一个纯设备上工作。 // 因此如果受到支持并且使用HWVP,就建立一个纯设备。 if ( (caps.DeviceCaps.SupportsPureDevice) && ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) ) settings.BehaviorFlags |= CreateFlags.PureDevice; } |
请注意 后台缓冲区是实际要显示的数据(象素)在发送给显卡处理并输出到屏幕之前所存储的地方。后台缓冲区的格式决定了可以显示多少种色彩。大多数格式遵循特定的命名习惯--每个字符跟着一个数字,例如A8R8G8B8。字符所指定的构成部分拥有与其后面的数字相同数量的位(bit)。在A8R8G8B8中,该格式可以包含32位色彩信息,alpha、red、green和blue各用8位。最常见的构成是: A Alpha R Red G Green B Blue X Unused |
请注意 窗体模式是我们运行的大多数应用程序的显示方式。其中大多数应用程序带有边框和控制菜单,右上角带有最小化、最大化和关闭按钮。在全屏模式下,应用程序覆盖了整个屏幕,并且在大多数情况下没有边框。如果全屏模式使用了另外的屏幕大小(你当前使用的桌面),你可以改变桌面的分辨率。 |
图2:允许不安全的代码 |
private Framework sampleFramework = null; // 示例的框架组件 /// 建立该类的一个新的实例 public GameEngine(Framework f) { // 存储框架组件 sampleFramework = f; } |
// 查找系统中的每个适配器 for each(AdapterInformation ai in Manager.Adapters) { EnumAdapterInformation adapterInfo = new EnumAdapterInformation(); // 存储一些信息 adapterInfo.AdapterOrdinal = (uint)ai.Adapter; // 序号 adapterInfo.AdapterInformation = ai.Information; // 信息 // 获取这个适配器上的所有显示模式 // 建立一个所有显示适配器格式的临时列表 adapterFormatList.Clear(); // 现在检测支持哪种格式 for(int i = 0; i < allowedFormats.Length; i++) { // 检查这种格式的每一种可支持的显示模式 for each(DisplayMode dm in ai.SupportedDisplayModes[allowedFormats[i]]) { if ( (dm.Width < minimumWidth) || (dm.Height < minimumHeight) || (dm.Width > maximumWidth) || (dm.Height > maximumHeight) || (dm.RefreshRate < minimumRefresh) || (dm.RefreshRate > maximumRefresh) ) { continue; // 这种格式是无效的 } // 添加到列表中 adapterInfo.displayModeList.Add(dm); // 如果先前并不存在就把它添加到格式列表中 if (!adapterFormatList.Contains(dm.Format)) { adapterFormatList.Add(dm.Format); } } } // 获取适配器显示模式 DisplayMode currentAdapterMode = ai.CurrentDisplayMode; // 检查这种格式是否在列表中 if (!adapterFormatList.Contains(currentAdapterMode.Format)) { adapterFormatList.Add(currentAdapterMode.Format); } // 对显示模式列表进行排序 adapterInfo.displayModeList.Sort(sorter); // 获取这个适配器上每个设备的信息 EnumerateDevices(adapterInfo, adapterFormatList); // 如果适配器上至少有一个设备,并且它是兼容的,就把它添加到列表中 if (adapterInfo.deviceInfoList.Count > 0) { adapterInformationList.Add(adapterInfo); } } |
请注意 这是一种通过把设备创建为适配器组的方式在"不同的"设备之间共享资源的方法。这种方法受到了少许限制。你可以查阅DirectX文档了解更多的信息。 |
请注意 示例框架选择的最小尺寸为640x480并不意味着在全屏模式下它就会选择最小的尺寸。在全屏模式下,示例框架选择最好的可用尺寸,它一般是当前桌面的大小(通常不是640x480的)。 |
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; // 它们一定相同,所以返回0 return 0; } } |
private static void EnumerateDevices(EnumAdapterInformation adapterInfo, ArrayList adapterFormatList) { // 在查找设备类型的时候忽略任何异常 DirectXException.IgnoreExceptions(); // 列举每个Direct3D设备类型 for(uint i = 0; i < deviceTypeArray.Length; i++) { // 建立一个新设备信息对象 EnumDeviceInformation deviceInfo = new EnumDeviceInformation(); // 存储该类型 deviceInfo.DeviceType = deviceTypeArray[i]; // 试图获取其性能 deviceInfo.Caps = Manager.GetDeviceCaps((int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType); // 获取该设备上每个设备组合的信息 EnumerateDeviceCombos( adapterInfo, deviceInfo, adapterFormatList); // 我们有设备组合吗? if (deviceInfo.deviceSettingsList.Count > 0) { // 有,把它添加到列表中 adapterInfo.deviceInfoList.Add(deviceInfo); } } // 打开异常处理开关 DirectXException.EnableExceptions(); } |
private static void EnumerateDeviceCombos(EnumAdapterInformation adapterInfo, EnumDeviceInformation deviceInfo, ArrayList adapterFormatList) { // 查找这种设备支持哪种适配器格式 for each(Format adapterFormat in adapterFormatList) { for(int i = 0; i < backbufferFormatsArray.Length; i++) { bool windowed = false; do { if ((!windowed) && (adapterInfo.displayModeList.Count == 0)) continue; if (!Manager.CheckDeviceType((int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType, adapterFormat, backbufferFormatsArray[i], windowed)) continue; // 不支持的 // 我们需要加速象素阴影混合吗? if (isPostPixelShaderBlendingRequired) { if (!Manager.CheckDeviceFormat( (int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType, adapterFormat, Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backbufferFormatsArray[i])) continue; // 不支持的 } // 如果提供了某个应用程序回调函数,就要确保这个设备受到该应用程序的支持 if (deviceCreationInterface != null) { if (!deviceCreationInterface.IsDeviceAcceptable(deviceInfo.Caps, adapterFormat, backbufferFormatsArray[i],windowed)) continue; // 应用程序不喜欢这个设备 } EnumDeviceSettingsCombo deviceCombo = new EnumDeviceSettingsCombo(); // 存储信息 deviceCombo.AdapterOrdinal = adapterInfo.AdapterOrdinal; deviceCombo.DeviceType = deviceInfo.DeviceType; deviceCombo.AdapterFormat = adapterFormat; deviceCombo.BackBufferFormat = backbufferFormatsArray[i]; deviceCombo.IsWindowed = windowed; BuildDepthStencilFormatList(deviceCombo); BuildMultiSampleTypeList(deviceCombo); if (deviceCombo.multiSampleTypeList.Count == 0) { continue; } BuildConflictList(deviceCombo); BuildPresentIntervalList(deviceInfo, deviceCombo); deviceCombo.adapterInformation = adapterInfo; deviceCombo.deviceInformation = deviceInfo; // 把组合添加到设备列表中 deviceInfo.deviceSettingsList.Add(deviceCombo); windowed = !windowed; } while (windowed); } } } |