初始化Direct3D(2)
1.3.2 Multisampling
由于使用像素矩阵来表示图像,在显示时会出现锯齿状,Multisampling就是使其变得平滑的技术。它的一种最普通的用法即为——全屏抗锯齿(看图1.3)。
D3DMULTISAMPLE_TYPE枚举类型使我们可以指定全屏抗锯齿的质量等级:
D3DMULTISAMPLE_NONE——不使用全屏抗锯齿。
D3DMULTISAMPLE_1_SAMPLE…D3DMULTISAPLE_16_SAMPLE——设定1~16级的等级。
Defines the levels of full-scene multisampling that the device can apply.
typedef enum D3DMULTISAMPLE_TYPE
{
D3DMULTISAMPLE_NONE = 0,
D3DMULTISAMPLE_NONMASKABLE = 1,
D3DMULTISAMPLE_2_SAMPLES = 2,
D3DMULTISAMPLE_3_SAMPLES = 3,
D3DMULTISAMPLE_4_SAMPLES = 4,
D3DMULTISAMPLE_5_SAMPLES = 5,
D3DMULTISAMPLE_6_SAMPLES = 6,
D3DMULTISAMPLE_7_SAMPLES = 7,
D3DMULTISAMPLE_8_SAMPLES = 8,
D3DMULTISAMPLE_9__SAMPLES = 9,
D3DMULTISAMPLE_10_SAMPLES = 10,
D3DMULTISAMPLE_11_SAMPLES = 11,
D3DMULTISAMPLE_12_SAMPLES = 12,
D3DMULTISAMPLE_13_SAMPLES = 13,
D3DMULTISAMPLE_14_SAMPLES = 14,
D3DMULTISAMPLE_15_SAMPLES = 15,
D3DMULTISAMPLE_16_SAMPLES = 16,
D3DMULTISAMPLE_FORCE_DWORD = 0xffffffff,
} D3DMULTISAMPLE_TYPE, *LPD3DMULTISAMPLE_TYPE;
使用全屏抗锯齿的功能将大大的降低了程序运行速度。如果你实在很想使用它的话,要记住使用IDirect3D9::CheckDeviceMultisampleType来检测你的显卡是否支持。
1.3.3像素格式
当我们创建一个表面或纹理时,经常需要指定这些Direct3D资源的像素格式。它是由D3DFORMAT枚举类型的一个成员来定义的。这里例举一部分:
D3DFMT_R8G8B8——表示一个24位像素,从左开始,8位分配给红色,8位分配给绿色,8位分配给蓝色。
D3DFMT_X8R8G8B8——表示一个32位像素,从左开始,8位不用,8位分配给红色,8位分配给绿色,8位分配给蓝色。
D3DFMT_A8R8G8B8——表示一个32位像素,从左开始,8位为ALPHA通道,8位分配给红色,8位分配给绿色,8位分配给蓝色。
D3DFMT_A16B16G16R16F——表示一个64位浮点像素,从左开始,16位为ALPHA通道,16位分配给蓝色,16位分配给绿色,16位分配给红色。
D3DFMT_A32B32G32R32F——表示一个128位浮点像素,从左开始,32位为ALPHA通道,32位分配给蓝色,32位分配给绿色,32位分配给红色。
想了解全部的像素格式请查看SDK文档中的D3DFORMAT部分。
注意:这前三种格式(D3DFMT_R8G8B8、D3DFMT_X8R8G8B8、D3DFMT_A8R8G8B8)是最常用并为大部分显卡所支持。但浮点像素格式或其它一些类型的支持并不是很广泛,在使用它们前请先检测你的显卡,看是否支持。
1.3.4 内存池
表面和其它一些Direct3D资源被放在多种内存池中。内存池的种类由D3DPOOL枚举类型的一个成员来指定。可用到的内存池有下列几种:
D3DPOOL_DEFAULT——表示Direct3D将根据资源的类型和用途把它们放在最合适的地方。这有可能是显存、AGP内存或者系统内存中。值得注意的是,这种内存池中的资源必须要在IDirect3DDevice9::Reset被调用之前消毁掉,并且再次使用时必须重新初始化。
D3DPOOL_MANAGED——资源将由Direct3D管理并且按设备的需要来指定放在显存还是放在AGP内存中。当应用程序访问和改变资源时它先把这些资源拷贝到系统内存中,当需要时Direct3D会自动把它们拷贝到显存里。
D3DPOOL_SYSTEMMEM——指定资源放在系统内存中。
D3DPOOL_SCRATCH——指定资源放在系统内存中,它与D3DPOOL_SYSTEMMEM不同之处在于使用这些资源不必受图形设备的限制。因此,参数使图形设备不能访问该内存池的资源,但资源可以相互拷贝。
AGP内存
AGP(Accelerate Graphical Port),加速图形接口。随着显示芯片的发展,PCI总线日益无法满足其需求。英特尔于1996年7月正式推出了AGP接口,它是一种显示卡专用的局部总线。严格的说,AGP不能称为总线,它与PCI总线不同,因为它是点对点连接,即连接控制芯片和AGP显示卡,但在习惯上我们依然称其为AGP总线。AGP接口是基于PCI 2.1 版规范并进行扩充修改而成,工作频率为66MHz。
AGP总线直接与主板的北桥芯片相连,且通过该接口让显示芯片与系统主内存直接相连,避免了窄带宽的PCI总线形成的系统瓶颈,增加3D图形数据传输速度,同时在显存不足的情况下还可以调用系统主内存。所以它拥有很高的传输速率,这是PCI等总线无法与其相比拟的。
由于采用了数据读写的流水线操作减少了内存等待时间,数据传输速度有了很大提高;具有133MHz及更高的数据传输频率;地址信号与数据信号分离可提高随机内存访问的速度;采用并行操作允许在CPU访问系统RAM的同时AGP显示卡访问AGP内存;显示带宽也不与其它设备共享,从而进一步提高了系统性能。
AGP标准在使用32位总线时,有66MHz和133MHz两种工作频率,最高数据传输率为266Mbps和533Mbps,而PCI总线理论上的最大传输率仅为133Mbps。目前最高规格的AGP 8X模式下,数据传输速度达到了2.1GB/s。
AGP接口的发展经历了AGP1.0(AGP1X、AGP2X)、AGP2.0(AGP Pro、AGP4X)、AGP3.0(AGP8X)等阶段,其传输速度也从最早的AGP1X的266MB/S的带宽发展到了AGP8X的2.1GB/S。
AGP 1.0(AGP1X、AGP2X)
1996年7月AGP 1.0 图形标准问世,分为1X和2X两种模式,数据传输带宽分别达到了266MB/s和533MB/s。这种图形接口规范是在66MHz PCI2.1规范基础上经过扩充和加强而形成的,其工作频率为66MHz,工作电压为3.3v,在一段时间内基本满足了显示设备与系统交换数据的需要。这种规范中的AGP带宽很小,现在已经被淘汰了,只有在前几年的老主板上还见得到。
AGP2.0(AGP4X)
显示芯片的飞速发展,图形卡单位时间内所能处理的数据呈几何级数成倍增长,AGP 1.0 图形标准越来越难以满足技术的进步了,由此AGP 2.0便应运而生了。1998年5月份,AGP 2.0 规范正式发布,工作频率依然是66MHz,但工作电压降低到了1.5v,并且增加了4x模式,这样它的数据传输带宽达到了1066MB/sec,数据传输能力大大地增强了。
AGP Pro
AGP Pro接口与AGP 2.0同时推出,这是一种为了满足显示设备功耗日益加大的现实而研发的图形接口标准,应用该技术的图形接口主要的特点是比AGP 4x略长一些,其加长部分可容纳更多的电源引脚,使得这种接口可以驱动功耗更大(25-110w)或者处理能力更强大的AGP显卡。这种标准其实是专为高端图形工作站而设计的,完全兼容AGP 4x规范,使得AGP 4x的显卡也可以插在这种插槽中正常使用。AGP Pro在原有AGP插槽的两侧进行延伸,提供额外的电能。它是用来增强,而不是取代现有AGP插槽的功能。根据所能提供能量的不同,可以把AGP Pro细分为AGP Pro110和AGP Pro50。在某些高档台式机主板上也能见到AGP Pro插槽,例如华硕的许多主板。
AGP 3.0(AGP8X)
2000年8月,Intel推出AGP3.0规范,工作电压降到0.8V,并增加了8x模式,这样它的数据传输带宽达到了2133MB/sec,数据传输能力相对于AGP 4X成倍增长,能较好的满足当前显示设备的带宽需求。
AGP接口的模式传输方式
不同AGP接口的模式传输方式不同。1X模式的AGP,工作频率达到了PCI总线的两倍—66MHz,传输带宽理论上可达到266MB/s。AGP 2X工作频率同样为66MHz,但是它使用了正负沿(一个时钟周期的上升沿和下降沿)触发的工作方式,在这种触发方式中在一个时钟周期的上升沿和下降沿各传送一次数据,从而使得一个工作周期先后被触发两次,使传输带宽达到了加倍的目的,而这种触发信号的工作频率为133MHz,这样AGP 2X的传输带宽就达到了266MB/s×2(触发次数)=533MB/s的高度。AGP 4X仍使用了这种信号触发方式,只是利用两个触发信号在每个时钟周期的下降沿分别引起两次触发,从而达到了在一个时钟周期中触发4次的目的,这样在理论上它就可以达到266MB/s×2(单信号触发次数)×2(信号个数)=1066MB/s的带宽了。在AGP 8X规范中,这种触发模式仍然使用,只是触发信号的工作频率变成266MHz,两个信号触发点也变成了每个时钟周期的上升沿,单信号触发次数为4次,这样它在一个时钟周期所能传输的数据就从AGP4X的4倍变成了8倍,理论传输带宽将可达到266MB/s×4(单信号触发次数)×2(信号个数)=2133MB/s的高度了。
目前常用的AGP接口为AGP4X、AGP PRO、AGP通用及AGP8X接口。需要说明的是由于AGP3.0显卡的额定电压为0.8—1.5V,因此不能把AGP8X的显卡插接到AGP1.0规格的插槽中。这就是说AGP8X规格与旧有的AGP1X/2X模式不兼容。而对于AGP4X系统,AGP8X显卡仍旧在其上工作,但仅会以AGP4X模式工作,无法发挥AGP8X的优势。
1.3.5 交换链和页面切换
Direct3D通常创建2~3个表面组成一个集合,即为交换链,通常由IDirect3DSwapChain接口来表示。我们不必去了解它更详细的细节。我们也很少去管理它,通常Direct3D会自己去管理。所以我们只要大概的了解一下它就可以了。
交换链以及页面切换技巧被用在使两帧动画之间过度更平滑。图1.4展示的是一个有两个绘制表面的交换链。
如图1.4,在Front Buffer中的表面将用来在屏幕上显示。显示器不能即时显示Front Buffer中表示的图像;通常情况下,它是每六十分之一秒刷新显示一次,即刷新率为60赫兹。应用程序的帧率经常与监视器的刷新率不同步(比如应用程序的渲染帧速度可能比显示器的刷新速度快)。然而,我们不能在显示器显示完成当前帧之前就更新有下一帧动画的Front Buffer内容,但是我们又不想让程序停止渲染而去等待显示器显示。因此,我们渲染另一个屏幕表面Back Buffer。当监视器将Front Buffer显示出来后,Front Buffer就被放到交换链的末端,即变成图中的Back Buffer,而Back Buffer就会变成交换链中的Front Buffer。这个过程就叫做presenting。图1.5表示了交换的整个过程。
因此,我们绘图代码的结构就会像下面这样:
1. Render to back buffer
2. Present the back buffer
3. Goto (1)
1.3.6 深度缓冲
深度缓冲也是一个表面,但它不是用来存储图像数据的,而是用来记录像素的深度信息。它将确定哪一个像素最后被绘制出来。所以,如果要绘制640*480分辨率的图片,那么就会有640*480个深度值。
图1.6展示了一个简单的场景,在这个场景里,一个物体把将另一个物体的一部分遮住了。为了使Direct3D能确定物体的前后关系并正确的绘制出来,我们使用一种深度缓冲,又叫做z-buffering的技术。
深度缓冲为每一个像素计算深度值,并进行深度测试。通过深度测试,我们可以比较出哪个像素离照相机更近,并将它画出来。这样就可以只绘制最靠近照相机的像素,被遮住的像素就不会被画出来。
深度缓冲的格式决定着深度测试的精确性。一个24位的深度缓冲比16位的深度缓冲更精确。通常,应用程序在24位深度缓冲下就能工作的很好,但是Direct3D也同时支持32位的深度缓冲。
D3DFMT_D32——表示32位深度缓冲
D3DFMT_D24S8——表示24位深度缓冲并保留8位模版缓冲(stencil buffer)
D3DFMT_D24X8——表示24位深度缓冲
D3DFMT_D24X4S4——表示24位深度缓冲并保留4位模版缓冲
D3DFMT_D16——表示16位深度缓冲
1.3.7 顶点处理
顶点是3D图形学的基础,它能够通过两种不同的方法被处理,一种是软件方式(software vertex processing),一种是硬件方式(hardware vertex processing),前者总是被支持且永远可用,后者必须要显卡硬件支持顶点处理才可用。
使用硬件顶点处理总是首选,因为它比软件方式更快,而且不占用CPU资源,这意味CPU至少可以有更多的空闲时间进行别的计算。
注意:如果一块显卡支持硬件顶点处理的话,也就是说它也支持硬件几何转换和光源计算。
1.3.8 设备能力
Direct3D支持的每一项特性都对应于D3DCAPS9结构的一个数据成员。初始化一个D3DCAPS9实例应该以你的设备实际支持特性为基础。因此,在我们的应用程序里,我们能够通过检测D3DCAPS9结构中相对应的某一成员来检测设备是否支持这一特性。
下面将举例说明,假设我们想要检测显卡是否支持硬件顶点处理(换句话说,就是显卡是否支持硬件几何转换和光源计算)。通过查阅SDK中的D3DCAPS9结构,可以得知数据成员D3DCAPS9::DevCaps中的D3DDEVCAPS_HWTRANSFORMANDLIGHT位表示硬件是否支持硬件顶点处理即硬件几何变换和光源计算。程序如下:
bool supportsHardwareVertexProcessing;
// If the bit is "on" then that implies the hardware device supports it.
if( caps.DevCaps & D3DDEVCAPS HWTRANSFORMANDLIGHT )
{
// Yes, the bit is on, so it is supported.
supportsHardwareVertexProcessing = true;
}
else
{
// No, the bit is off, so it is not supported.
hardwareSupportsVertexProcessing = false;
}
注意:DevCaps即为“device capabilities。