2024年3月31日发(作者:)

详解DX9下3D游戏编程1

来源: [ buaaytt ] 浏览: [899]

Introduction to 3D Game Programming with DirectX 9.0

原著: Frank D. Luna

第二部分

第一章 D3D初始化

D3D的初始化以前一直被认为是一项乏味琐碎的工作。幸运的是8.0版本简化了初始化模式并且DX9.0也

使用和它相同的模式。然而,在这个过程中仍需要我们熟知图形学的基础知识和D3D的基本类型,本章的

前几节将讲述这方面的内容。在余下的小节里将解释初始化的过程。

目的:

1. 学习D3D怎样与图形硬件交互作用

2. 弄懂COM在D3D中所扮演的角色

3. 学习基础图形学知识,如2D图片是如何存储的、页面切换和深度缓冲

4. 学习如何初始化D3D

5. 熟悉本书例程中的一些常用的结构

1.1 Direct3D概述

D3D是一种低层图形API,它主要使用3D硬件加速来进行3D世界的渲染。我们可以把D3D看作是应用程序

和图形设备之间的中介。例如通知图形设备清空屏幕,应用程序将调用D3D的IDirect3DDevice9::Clear

方法。图1.1显示了应用程序、D3D和图形设备之间的关系。

此图片被缩小显示,点击查看大图

图1.1:应用程序、D3D和硬件间的关系。

图中所表示的D3D是已定义的供程序员使用的D3D接口和函数的集合。这些接口和函数代表了当前版本的

D3D所支持的全部特性集。注意:仅仅因为D3D支持某种特性,并不意味着你使用的显卡会支持它。

如图1.1所示,在D3D和图形设备之间有一层中介——叫做硬件抽象层(HAL,Hardware Abstraction Layer)。

D3D不能直接作用于图形设备,因为现在市面上的显卡种类实在是太多了并且每种显卡都有不同的性能和

处理事件的方式。例如,两种不同的显卡实现清屏的方式也可能是不同的。因此,D3D要求设备制造商实

现HAL。HAL是一组指示设备执行某种操作的特殊设备代码的集合。用这种方法,D3D避免了必须去了解某

个设备的特殊细节,使它能够独立于硬件设备而存在。

设备制造商在HAL中实现他们的产品所支持的所有特性。HAL将不会实现那些D3D支持但硬件产品不支持

的特性。调用一个HAL中没有实现的D3D的函数将会出错,除非它是顶点处理操作,因为这个功能可以由

软件模拟来实现。因此当使用某些仅由市面上少数显卡所支持的高级特性时,必须检测一下设备是否支持。

1.1.1 The REF Device

你也许想把一些你的设备不支持的D3D函数写入程序中,为了达到这个目的,D3D提供了REF设备(reference

rasterizer),它用软件模拟了所有的D3DAPI。这允许你写并测试那些你的显卡不支持的D3D特性的代码。

例如在本书的第四部分,某些人的显卡可能会不支持顶点和像素着色器。如果你的显卡不支持着色器,你

仍然能够使用REF设备测试示例代码。另外,REF设备实在是太慢了,除了测试外它没有任何利用价值。

1.1.2 D3DDEVTYPE

在程序中,我们用D3DDEVTYPE_HAL来定义HAL设备,它是D3DDEVTYPE枚举类型的一个成员。同样的,REF

设备则由D3DDEVTYPE_REF来定义,它也属于D3DDEVTYPE枚举类型。这个类型很重要,因为在创建设备的

时候需要指定它。

1.2 COM

组件对象模型(COM, Component Object Model)是一种能使DirectX独立于编程语言和具有向下兼容性的

技术。我们通常把COM对象作为一个接口,你可以把它当作达到某种目的的C++类来使用它。当使用C++

写DirectX程序的时候,COM的大部分细节对我们来说是透明。但是有一件事,我们必须知道,那就是我

们通过某个特殊的COM接口的函数或指针获得了另一个COM接口指针,而不是通过C++的新关键字来创建

它。当我们使用完某个接口后,调用它的Release方法比直接Delete它更好。COM对象具有它们自己的内

存管理。

注意:COM接口都具有前缀大写字母“I”,例如表示一个表面的COM接口叫做IDirect3DSurface9。

1.3 Some Preliminaries(一些准备工作)

D3D的初始化过程要求我们对图形学基础知识和D3D类型有一定了解。本节将介绍这些知识和类型以确保

下一节能把更多的时间放在D3D初始化的讨论上。

1.3.1 Surfaces

表面是一个像素点阵,在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 _surface is a pointer to an IDirect3DSurface9 interface.

// Assumes a 32-bit pixel format for each pixel.

// Get the surface description.

D3DSURFACE_DESC surfaceDesc;

_surface->GetDesc(&surfaceDesc);

// Get a pointer to the surface pixel data.

D3DLOCKED_RECT lockedRect;

_surface->LockRect(

&lockedRect, // pointer to receive locked data

0, // lock entire surface

0); // no lock flags specified