详解DX9下3D游戏编程1.docx
- 文档编号:7806282
- 上传时间:2023-01-26
- 格式:DOCX
- 页数:15
- 大小:27.81KB
详解DX9下3D游戏编程1.docx
《详解DX9下3D游戏编程1.docx》由会员分享,可在线阅读,更多相关《详解DX9下3D游戏编程1.docx(15页珍藏版)》请在冰豆网上搜索。
详解DX9下3D游戏编程1
详解DX9下3D游戏编程1
来源:
[buaaytt]
浏览:
[899]
Introductionto3DGameProgrammingwithDirectX9.0
原著:
FrankD.Luna
第二部分
第一章D3D初始化
D3D的初始化以前一直被认为是一项乏味琐碎的工作。
幸运的是8.0版本简化了初始化模式并且DX9.0也使用和它相同的模式。
然而,在这个过程中仍需要我们熟知图形学的基础知识和D3D的基本类型,本章的前几节将讲述这方面的内容。
在余下的小节里将解释初始化的过程。
目的:
1.学习D3D怎样与图形硬件交互作用
2.弄懂COM在D3D中所扮演的角色
3.学习基础图形学知识,如2D图片是如何存储的、页面切换和深度缓冲
4.学习如何初始化D3D
5.熟悉本书例程中的一些常用的结构
1.1Direct3D概述
D3D是一种低层图形API,它主要使用3D硬件加速来进行3D世界的渲染。
我们可以把D3D看作是应用程序和图形设备之间的中介。
例如通知图形设备清空屏幕,应用程序将调用D3D的IDirect3DDevice9:
:
Clear方法。
图1.1显示了应用程序、D3D和图形设备之间的关系。
此图片被缩小显示,点击查看大图
图1.1:
应用程序、D3D和硬件间的关系。
图中所表示的D3D是已定义的供程序员使用的D3D接口和函数的集合。
这些接口和函数代表了当前版本的D3D所支持的全部特性集。
注意:
仅仅因为D3D支持某种特性,并不意味着你使用的显卡会支持它。
如图1.1所示,在D3D和图形设备之间有一层中介——叫做硬件抽象层(HAL,HardwareAbstractionLayer)。
D3D不能直接作用于图形设备,因为现在市面上的显卡种类实在是太多了并且每种显卡都有不同的性能和处理事件的方式。
例如,两种不同的显卡实现清屏的方式也可能是不同的。
因此,D3D要求设备制造商实现HAL。
HAL是一组指示设备执行某种操作的特殊设备代码的集合。
用这种方法,D3D避免了必须去了解某个设备的特殊细节,使它能够独立于硬件设备而存在。
设备制造商在HAL中实现他们的产品所支持的所有特性。
HAL将不会实现那些D3D支持但硬件产品不支持的特性。
调用一个HAL中没有实现的D3D的函数将会出错,除非它是顶点处理操作,因为这个功能可以由软件模拟来实现。
因此当使用某些仅由市面上少数显卡所支持的高级特性时,必须检测一下设备是否支持。
1.1.1TheREFDevice
你也许想把一些你的设备不支持的D3D函数写入程序中,为了达到这个目的,D3D提供了REF设备(referencerasterizer),它用软件模拟了所有的D3DAPI。
这允许你写并测试那些你的显卡不支持的D3D特性的代码。
例如在本书的第四部分,某些人的显卡可能会不支持顶点和像素着色器。
如果你的显卡不支持着色器,你仍然能够使用REF设备测试示例代码。
另外,REF设备实在是太慢了,除了测试外它没有任何利用价值。
1.1.2D3DDEVTYPE
在程序中,我们用D3DDEVTYPE_HAL来定义HAL设备,它是D3DDEVTYPE枚举类型的一个成员。
同样的,REF设备则由D3DDEVTYPE_REF来定义,它也属于D3DDEVTYPE枚举类型。
这个类型很重要,因为在创建设备的时候需要指定它。
1.2COM
组件对象模型(COM,ComponentObjectModel)是一种能使DirectX独立于编程语言和具有向下兼容性的技术。
我们通常把COM对象作为一个接口,你可以把它当作达到某种目的的C++类来使用它。
当使用C++写DirectX程序的时候,COM的大部分细节对我们来说是透明。
但是有一件事,我们必须知道,那就是我们通过某个特殊的COM接口的函数或指针获得了另一个COM接口指针,而不是通过C++的新关键字来创建它。
当我们使用完某个接口后,调用它的Release方法比直接Delete它更好。
COM对象具有它们自己的内存管理。
注意:
COM接口都具有前缀大写字母“I”,例如表示一个表面的COM接口叫做IDirect3DSurface9。
1.3SomePreliminaries(一些准备工作)
D3D的初始化过程要求我们对图形学基础知识和D3D类型有一定了解。
本节将介绍这些知识和类型以确保下一节能把更多的时间放在D3D初始化的讨论上。
1.3.1Surfaces
表面是一个像素点阵,在D3D中主要用来存储2D图形数据。
图1.2指明了表面的一些成分。
由图可以看出表面数据就像一个矩阵,像素数据实际上存储在线性数组里面。
此图片被缩小显示,点击查看大图
图1.2:
表面
表面的Width和Height是按像素计算的。
Pitch以字节为单位。
而且Pitch有可能比Width大且依赖于低层硬件,所以不能单纯的认为Pitch=Width*sizeof(pixelFormat)。
在程序中,可以使用IDirect3DSurface9接口来描述表面。
这个接口提供若干方法来直接读写表面数据并且还有一个方法用来返回表面信息。
IDirect3DSurface9中最重要的方法是:
1.LockRect——使用这个方法,我们将获得一个指向表面内存的指针,然后,通过一系列指针运
算,我们可以对表面上任一个像素点进行读、写操作。
2.UnlockRect——当你调用了LockRect和完成了对表面内存的访问后,你必须调用这个方法给表
面解锁。
3.GetDesc——这个方法将通过填充D3DSURFACE_DESC结构来返回表面的描述信息。
下面的代码块表示将表面锁定并将每一像素染成红色:
//Assume_surfaceisapointertoanIDirect3DSurface9interface.
//Assumesa32-bitpixelformatforeachpixel.
//Getthesurfacedescription.
D3DSURFACE_DESCsurfaceDesc;
_surface->GetDesc(&surfaceDesc);
//Getapointertothesurfacepixeldata.
D3DLOCKED_RECTlockedRect;
_surface->LockRect(
&lockedRect,//pointertoreceivelockeddata
0,//lockentiresurface
0);//nolockflagsspecified
//Iteratethrougheachpixelinthesurfaceandsetittored.
DWORD*imageData=(DWORD*)lockedRect.pBits;
for(inti=0;i { for(intj=0;j { //indexintotexture,noteweusethepitchanddivideby //foursincethepitchisgiveninbytesandthereare //4bytesperDWORD. intindex=i*lockedRect.Pitch/4+j; imageData[index]=0xffff0000;//red } } _surface->UnlockRect(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 程序中D3DLOCKED_RECT结构的定义如下: typedefstruct_D3DLOCKED_RECT{ INTPitch;//thesurfacepitch void*pBits;//pointertothestartofthesurfacememory }D3DLOCKED_RECT; 在程序中,我使用DWORD来定义一个32位的像素,我们暂时不用去关心为什么0xffff0000表示红色,关于颜色的说明将在第四章谈到。 1.3.2Multisampling 由于使用像素矩阵来表示图像,在显示时会出现锯齿状,Multisampling就是使其变得平滑的技术。 它的一种最普通的用法即为——全屏抗锯齿。 D3DMULTISAMPLE_TYPE枚举类型使我们可以指定全屏抗锯齿的质量等级: 1.D3DMULTISAMPLE_NONE——不使用全屏抗锯齿。 2.D3DMULTISAMPLE_1_SAMPLE…D3DMULTISAPLE_16_SAMPLE——设定1~16级的等级。 本书的示例程序中没有使用全屏抗锯齿的功能,因为它大大的降低了程序运行速度。 如果你实在很想使用它的话,要记住使用IDirect3D9: : CheckDeviceMultisampleType来检测你的显卡是否支持。 1.3.3PixelFormats(像素格式) 当我们创建一个表面或纹理时候,经常需要指定这些D3D资源的像素格式。 它是由D3DFORMAT枚举类型定义的。 这里例举一部分: 1.D3DFMT_R8G8B8——表示一个24位像素,从左开始,8位表红色,8位表绿色,8位表蓝色。 2.D3DFMT_X8R8G8B8——表示一个32位像素,首8位不用,其余同上。 3.D3DFMT_A8R8G8B8——32位像素,首8位为ALPHA通道,其余同上。 注意: 这三种格式是最常用并为大部分显卡所支持。 但浮点像素格式或其它一些类型的支持并不是很广泛,在使用它们前请先检测你的显卡,看是否支持。 1.3.4MemoryPools(内存池) 表面和其它一些D3D资源被放在多种内存池中。 内存池的种类由D3DPOOL枚举类型的一个成员来指定。 它可以为下列几种: 1.D3DPOOL_DEFAULT——表示D3D将根据资源的类型和用途把它们放在最合适的地方。 这有可能是显存、AGP内存或者系统内存中。 值得注意的是,这种内存池中的资源必须要在IDirect3DDevice9: : Reset被调用之前消毁掉,然后必须重新初始化。 2.D3DPOOL_MANAGED——资源将由D3D管理并且按设备的需要来指定放在显存还是放在AGP内存中,同时备份这些资源到系统内存中。 当应用程序访问和改变资源,也会对系统内存造成影响。 3.D3DPOOL_SYSTEMMEM——指定资源放在系统内存中。 4.D3DPOOL_SCRATCH——规定资源放在系统内存中,它与D3DPOOL_SYSTEMMEM不同之处在于使用这个参数使图形设备不能访问本内存池的资源,但资源可以被复制出去。 1.3.5TheSwapChainandPageFlipping(交换链和页面切换) D3D通常创建2~3个表面组成一个集合,即为交换链,通常由IDirect3DSwapChain接口来表示。 但是我们很少用到这个东东,通常让D3D自己去管理它。 所以我们只要大概的了解一下它就可以了。 此图片被缩小显示,点击查看大图 图1.4: 一个双表面的交换链。 如图1.4,FrontBuffer将用来在屏幕显示,我们所看到的就是这个表面。 但是监视器并不是实时显示这个表面的,通常情况下,它是每六十分之一秒刷新一次,即刷新率为60赫兹。 此图片被缩小显示,点击查看大图 图1.5 应用程序的帧数经常与监视器的刷新率不同步。 虽然FrontBuffer对应于显示屏幕,但我们并不直接在FrontBuffer上绘制动画,而是在BackBuffer进行绘制。 当监视器将FrontBuffer显示出来后,FrontBuffer就被放到交换链的末端,即变成图中的BackBuffer,而BackBuffer就会变成交换链中的FrontBuffer。 这个过程就叫做presenting。 这与DirectDraw中的Flip相似。 图1.5表示了交换的整个过程。 因此,我们绘图代码的结构就会像下面这样: 1.Rendertobackbuffer 2.Presentthebackbuffer 3.Goto (1) 1.3.6DepthBuffers(深度缓冲) 深度缓冲也是一个表面,但它不是用来存储图像数据而是用来记录像素的深度信息,它将确定哪一个像素最后被绘制出来。 所以,如果绘制的图片是640*480的分辨率,那就会有640*480个深度值。 此图片被缩小显示,点击查看大图 图1.6: 物体是重叠的。 图1.6展示了一个简单的场景,在这个场景里,一个物体把将另一个物体的一部分遮住了。 为了使D3D能确定物体的前后关系并正确的绘制出来,我们使用深度缓冲,又叫做z-buffering技术。 深度缓冲为每一个像素计算深度值并进行深度测试。 通过深度测试我们可以比较得出哪个像素离摄相机更近并将它画出来。 这样就可以只绘制最靠近摄相机的像素,被遮住的像素就不会被画出来。 深度缓冲的格式决定着深度测试的精确性。 一个24位的深度缓冲会比16位的深度缓冲更精确。 通常,应用程序能够很好的工作在24位深度缓冲下,但是D3D也支持32位的深度缓冲。 1.D3DFMT_D32——32位深度缓冲 2.D3DFMT_D24S8——24位深度缓冲并保留8位模版缓冲(stencilbuffer) 3.D3DFMT_D24X8——24位深度缓冲 4.D3DFMT_D24X4S4——24位深度缓冲并保留4位模版缓冲 5.D3DFMT_D16——16位深度缓冲 注意: 关于模版缓冲的问题将在第八章说明。 1.3.7VertexProcessing 顶点能够通过两种不同的方法被处理,一种是softwarevertexprocessing,一种是hardwarevertexprocessing,前者可以在任何显卡上使用,而后者则需要硬件支持。 使用硬件顶点处理比软件更快,而且不占用CPU资源,这意味差CPU可以有更多的空闲时间进行别的计算。 注意: 如果一块显卡支持硬件顶点处理的话,也就是说它也支持几何转换和光源。 1.3.8DeviceCapabilities D3D支持的每一项特性都对应于D3DCAPS9结构的一个数据成员。 如果你想在程序中检测你的设备的是否支持某一特性,只需要检测D3DCAPS9结构中相对应的某一成员就可以了。 下面将举例说明,假设我们想要检测显卡是否支持硬件顶点处理(换句话说,就是显卡是否支持几何转换和光源)。 通过查阅SDK中的D3DCAPS9结构,可以得知数据成员D3DCAPS9: : DevCaps中的D3DDEVCAPS_HWTRANSFORMANDLIGHT位表示硬件是否支持硬件顶点处理即几何变换和光源。 程序如下: boolsupportsHardwareVertexProcessing; //Ifthebitis“on”thenthatimpliesthehardwaredevice //supportsit. if(caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) { //Yes,thebitison,soitissupported. supportsHardwareVertexProcessing=true; } else { //No,thebitisoff,soitisnotsupported. hardwareSupportsVertexProcessing=false; } 注意: DevCaps即为“devicecapabilities” 下一节将学习怎样根据硬件的实际情况来初始化D3DCAPS9 建议阅读SDK中关于D3DCAPS9的说明 1.4InitializingDirect3D 下面几点说明怎样初始化D3D: 1.通过IDirect3D9获得一个指针。 这个接口用于获得物理设备的信息和创建一个IDirect3DDevice9接口,它是一个代表我们显示3D图形的物理设备的C++对象。 2.检查设备的技术特性(D3DCAPS9),搞清楚是否支持硬件顶点处理。 3.初始化一个D3DPRESENT_PARAMETERS结构实例,这个结构包含了许多数据成员允许我们指定将要创建的IDirect3DDevice9接口的特性。 4.创建一个基于D3DPRESENT_PARAMETERS的IDirect3DDevice9接口。 请注意,本书使用主显示设备绘制3D图形,如果你的机子只有一块显卡,那它就是主显示设备。 如果你有多个显卡,那么你当前使用的显卡将会成为主显示设备(如: 用来显示桌面的显卡)。 1.4.1AcquiringanIDirect3D9Interface 首先通过IDirect3D9接口初始化D3D,这很简单,代码如下: IDirect3D9*_d3d9; _d3d9=Direct3DCreate9(D3D_SDK_VERSION); Direct3DCreate9的唯一一个参数总是D3D_SDK_VERSION,这可以保证应用程序通过正确的头文件被生成。 如果失败,将返回一个空指针。 IDirect3D9通常有两个用途: 设备列举和创建IDirect3DDevice9对象。 设备列举即为查明设备的技术特性,显示模式、格式,和其它每一种显卡各自支持的特性。 但是这种检测实在太慢了,为了使D3D运行得尽可能快,我们通常不使用这个测试,除了下一节所谈到的一项测试。 为了安全跳过测试阶段,我们通可以选择总是被所有显卡都支持的“安全”配置。 1.4.2CheckingforHardwareVertexProcessing 在我们创建一个IDirect3DDevice9来表示主显示设备时,必须要设定其顶点处理的类型。 如果可以的话,当然要选用硬件顶点处理,但是如果显卡不支持的话,也只有用软件方法了。 首先我们要根据主显示设备的技术特性来初始化D3DCAPS9结构。 可以使用如下方法: HRESULTIDirect3D9: : GetDeviceCaps( UINTAdapter, D3DDEVTYPEDeviceType, D3DCAPS9*pCaps ); Adapter——指定要获得哪个显示适配器的特性 DeviceType——指定设备类型(硬件设备(D3DDEVTYPE_HAL),软件设备(D3DDEVTYPE_REF)) PCaps——返回一个已填充的D3DCAPS9结构 然后,我们可以开始检测了,代码如下: //FillD3DCAPS9structurewiththecapabilitiesofthe //primarydisplayadapter . D3DCAPS9caps; d3d9->GetDeviceCaps( D3DADAPTER_DEFAULT,//Denotesprimarydisplayadapter. deviceType,//Specifiesthedevicetype,usuallyD3DDEVTYPE_HAL. &caps);//ReturnfilledD3DCAPS9structurethatcontains //thecapabilitiesoftheprimarydisplayadapter. //Canweusehardwarevertexprocessing? intvp=0; if(caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) { //yes,savein‘vp’thefactthathardwarevertex //processingissupported. vp=D3DCREATE_HARDWARE_VERTEXPROCESSING; } else { //no,savein‘vp’thefactthatwemustusesoftware //vertexprocessing. vp=D3DCREATE_SOFTWARE_VERTEXPROCESSING; } 在程序中,我们使用变量vp来存储顶点处理类型。 这是因为在稍后创建IDirect3DDevice9时要求指定其顶点处理的类型。 注意: 标识符D3DCREATE_HARDWARE_VERTEXPROCESSING D3DCREATE_SOFTWARE_VERTEXPROCESSING是预定义的值,它们分别代表硬件顶点处理和 软件顶点处理。 如果一个应用程序在你的机子上不能运行,说明它用到的一些特性可能你的显卡并不支持,可以试试把设备类型换成REF。 1.4.3FillingOuttheD3DPRESENT_PARAMETERSStructure 现在我们要填充一个D3DPRESENT_PARAMETERS结构的实例了。 这个结构用于设定我们将要创建的IDirect3DDevice9对象的一些特性,它的定义如下: typedefstruct_D3DPRESENT_PARAMETERS_{ UINTBackBufferWidth; UINTBackBufferHeight; D3DFORMATBackBufferFormat; UINTBackBufferCount; D3DMULTISAMPLE_TYPEMultiSampleType; DWORDMultiSampleQuality; D3DSWAPEFFECTSwapEffect; HWNDhDeviceWindow; BOOLWindowed; BOOLEnableAutoDepthStencil; D3DFORMATAutoDepthStencilFormat; DWORDFlags; UINTFullScreen_RefreshRateInHz; UINTPresentationInterval; }D3DPRESENT_PARAMETERS; 下面介绍其比较重要的数据成员,至于更详细的信息,请查阅SDK: BackBufferWidth——后备表面的宽度(以像素为单位) BackBufferHeight——后备表面的高度(以像素为单位) BackBufferFormat——后备表面的像素格式(如: 32位像素格式为D3DFMT——A8R8G8B8) BackBufferCount——后备表面的数量,通常设为“1”,即只有一个后备表面 MultiSampleType——全屏抗锯齿的类型,详情请看SDK
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详解 DX9 游戏 编程
![提示](https://static.bdocx.com/images/bang_tan.gif)