DirectX教程

DirectX教程
DirectX教程

DirectX 8 教程

著 Andy Pike

https://www.360docs.net/doc/6d514959.html,

译 Aman JIANG

https://www.360docs.net/doc/6d514959.html,

第一章: 准备就绪

What you will need(你需要什么)

?DirectX 8.0 SDK (可以从http://m https://www.360docs.net/doc/6d514959.html,/directx下载)

?VC6(SP5)/https://www.360docs.net/doc/6d514959.html,

?Windows 程序设计经验

?通晓 C++和OOP

Introduction(序)

(原著的话)

欢迎阅读本DX教程。本教程至少能帮你入门、使你了解怎样用DX8 来开发Windows游戏。我写这个教程的原由有二:首先,当出现DX时,我还是一个初学者。所以,我想边学习边写一个教程来锻炼自己。其次,对初学者来说,DX SDK 并不是很有帮助。而且,网上也没有什么像样的Dx8教程。另外,就像上面我提到的,我也是个初学者,所以,如果你发现教程中有什么地方不对,请给我写信:webmaster@https://www.360docs.net/doc/6d514959.html,。

译者言

我也是一名初学者,所以,有言在先:如果你读英文能如履平地,建议你还是去读原著。此教程很适合入门,等你入门以后,你会发现,其实一切并没有想象的那样复杂。这是个不错的Dx8教程,我会尽最大努力把它翻译好。注:我并没有完全按照原著来译,不适之处,请多包涵。嗯,你应该弄到教程附带的源代码,没有那个可不行!可以到https://www.360docs.net/doc/6d514959.html,去下载。欢迎指出我的错误,或与我联系,我的Email:Chaoyu_JIANG@hot https://www.360docs.net/doc/6d514959.html, or Am an_JIANG@https://www.360docs.net/doc/6d514959.html, , QQ:15852673。

COM

What is COM? COM 是什么呢?COM 就是 Component Object Model, 组件对象模型。COM 接口和C++的抽象类相似(但不一样),就像抽象类没有与之相关的实际代码一样,COM描述了一套符号和语法而非实现过程。你也可以把 COM 对象就想象成一套为某个主题而设计的一整套库函数。DX 就提供了一套完整的设计3D游戏的库。最棒的就是,使用DX时,你不必去直接接触硬件,而由DX帮你代理了。这使得一些事情变得简单了。

使用 COM 时应该注意,必须在程序结束前释放所有的 COM 对象(或接口)。而且,释放它们的顺序应该和创建

它们的顺序相反。就像这样:

1. Create interface A.

2. Create interface B.

3. Release interface B.

4. Release interface A.

调用它们的 Release 模块来释放它们。

Page Flipping (页翻动)

页翻动又是什么呢?嗯,你知道电影的原理吗?电影通过以每秒钟24幅的速度连续的闪动图像,每幅图像之间的差别又很小,由于人眼的滞留作用,我们看到的画面就是连续的了。这不难理解。其实,DirectX 也是这样工作的。我

西绘制到“后缓冲区”上。快速而连续的重复次过程,用户就会看到像电影一样连续的图像了。不过一般情况下,我们每秒钟能绘制的页数要比电影多很多。

如果我们不是用页翻动技术,那用户看到的屏幕中的物体,将会一个个的被绘制出来,虽然速度可能很快,但效果会很差,那并不是我们想要的。

所以,我们的游戏需要一个循环,称之为“Game Loop”。每次循环,我们都要清除“后缓冲区”,把该绘制的物体按照一定的逻辑都绘制到那上面,然后把它翻动到“前缓冲区”上,然后进入下一次循环。这个循环得直到游戏退出了才能结束。有时我们可能需要好几个这样的“后缓冲区”(多缓冲)来组成一个“交换链”(Swap Chain),以求更好的效果。

Devices (设备)

What is a device? 设备是什么?简单的说,就是你的3D卡。你得创建一个接口来代表设备,然后使用那个接口来绘制东西。

Game Loop (游戏循环)

什么是游戏循环呢?游戏循环是一段代码,在游戏退出之前循环执行的代码。这段代码在每次循环中都要:在屏幕上绘制物体(或场景人物随便什么)、处理游戏的逻辑过程(如:物体的移动、人工智能等等)、处理Windows的消息等等。基本上就是这样了。

Creating Your First Project (创建你的第一个项目)

译者:嗯,这部分我就不用译了吧,这可是基础的东西。不过还是说说初学者容易忽略的一点:一定要把你的DX SDK的Include目录和Lib目录的路径添加到VC的目录设置列表中去,而且不要把Include和Lib的地方放错了,而且还要放在第一位。还要把d3d8.lib添加到项目设置的Lib列表中,否则编译不了。

Okay, that’s enough theory lets get started. Follow the step-by-step guide below to create your first DirectX Graphics project.

1.In Visual C++ create a new Win32 Application.

a.File > New

b.From the Projects tab select Win32 Application

c.Enter a name for your project such as “DX Project 1”

d.Select a folder for the location of your source code files

e.Click Next

f.Select the em pty project option.

g.Click Finish

2.Make sure that your project settings are correct.

a.Project > Settings...

b.On the Link tab, m ake sure that "d3d8.lib" is in the list of Object/Library Modules. If it

isn’t sim ply type it in.

3.Make sure that your search paths are correct.

a.Tools > Options > Directories Tab

b.In the "Show directories for" drop-down, select "include files".

c.If it does not exist already, add the following path: \include.

d.Make sure that this path is at the top of the list by clicking on the up arrow button (if

needed).

e.In the "Show directories for" drop-down, select "library files".

f.If it does not exist already, add the following path: \lib.

g.Make sure that this path is at the top of the list by clicking on the up arrow button (if

needed).

4.Add the source code.

a.File > New

b.From the Files tab, select C++ Source File

c.Enter a filenam e such as “Main.cpp”

d.Copy the code segm ent below, and then paste it into your new fil

e.

5.Build and Run the program.

a.Press F7 to build your project

下面就是本章的例子了,好好研究吧,不难。

你会得到一个绿色背景的窗户(读者:是窗口,白痴),虽然看起来不怎么样,但至少是一个好的开始,不是吗?好地开头,就是成功地半拉!(读者:……)

(译者:嗯,那个老外用WinXP?我看还是Win2K好……)

(读者:切~~别在那废话。)

WinMain

此乃Win32程序的入口点,代码会从这里开始执行。这是我们注册、创建、显示窗口的地方。然后,我们要初始化Direct3D并进入游戏循环(Game Loop)。

WinProc

这是应用程序的消息处理过程。Windows发给我们的程序的消息,都要有它处理。注意我们上面的例子,我们处理了两种消息:WM_DESTROY(结束程序)和 WM_KEYUP(有按键被按下)。其他的消息我们都交给默认消息处理过程DefWindowProc处理了。

g_pD3D

这是指向IDirect3D8接口的指针,我们得通过它来创建Direct3D设备接口。

g_pD3DDevice

这是 IDirect3DDevice8(D3D 设备) 的接口的指针,它实际上代表了你的硬件3D卡。

InitialiseD3D

我们的这个函数是用来初始化Direct3D的。首先,创建IDirect3D8对象,通过这个对象我们得到了当前屏幕的显示模式。然后,根据刚刚我们获取的信息(显示模式),创建了兼容的设备。

译者:因为一些显示卡的显示模式并不相同,所以,我们的程序要在每块显卡上都能执行,就要了解这块显卡的显示模式等等一些信息。然后,根据这些信息,创建我们的D3D设备。

GameLoop

这就是上面提到的“游戏循环”的具体实现了。当初始化结束后,它就开始了。

他会检测有没有Windows的消息,没有的话,就调用Render来绘制屏幕。

Render

首先,我们清除了后缓冲区准备作画。然后,调用了BeginScene函数来告知DX我们要作画了。这时,我们就可以作画了(教程2)。结束了绘制,我们调用EndScene来告知DX我们画完了。最后,我们调用了Present来完成关键的一步:翻动后缓冲区到前缓冲区(屏幕)。这时,用户就能看到我们画的东西了。

CleanUp

我们在此做清洁工作:释放所有的被创建的对象。因为程序要推出了。

Summary (摘要)

译者:嗯,好了,这就是我们教程的第一章了。并不难,不是吗?看起来虽然字不多,翻译起来,蛮累呢!

研究明白了的话,看下一章吧!下一章我们就会真正的画一些东西了!呵呵,真是令人期待呢……

也让老外说几句吧:

Ok, that’s it for the first tutorial. I know that the finished program wasn’t the m ost spectacular thing in the world, but just wait for the next tutorial when we will be drawing some shapes!

第二章:绘制三角形

Introduction(序)

所有的 3D 图形都是由三角形构成的。为什么是三角形而不是别的图形呢?因为三角形有许多优越之处,例如:绘制效率。(译者:而且我们知道,任意不在同一条直线上的三个点都能构成三角形,这对于在空间中形成某种复杂图

优于直接绘制一个矩形。所以,本教程下面将告诉你如何绘制复杂物体的最小单元:三角形。(译者:神奇的三角形啊..)

Vertices (顶点)

顶点(vertex)是什么?顶点就是3D空间中的一个点。例如,三角形有三个顶点,而矩形有四个。在3D空间中,你可以用三个顶点来指定一个三角形。想做到这些,你需要了解迪卡尔坐标系统。

2D Cartesian coordinate system (2D 迪卡尔坐标系统)

下面的两幅图演示了2D 迪卡尔坐标系统是怎样工作的。

2D迪卡尔坐标系统是很简单的,用两条轴x、y的值来表示点的位置,进而表现出图形的位置。这是初中时我们就学习过的。

3D Cartesian coordinate system (3D 迪卡尔坐标系统)

下面的两幅图演示了左手3D 迪卡尔坐标系统是怎样工作的。

2D坐标系统只有x轴与y轴,因为它是平面的。而在3D空间里,两个轴显然不够用了,所以,有了第三个轴:z 轴。现在,我们用这三个轴就能在3D空间中表示出物体的任意位置了。这其实是很简单的事情,我就不多说了。

3D Primitives

Primit ive 为“原始”之意,3D primit ive 就是设备所支持的原始的类型。它包括:点列、线列、线代、三角形列、三角形带和三角扇形。使用3D primitive 完成上述的图形是很方便的。以后我们会用3D primitive 来绘制图形。下面的一些例子演示了上述的各种方式:

Point Lists

(点列)

Fig 2.5 Line Lists

(线列)

Fig 2.6 Line Strips

(线带)

Triangle Lists (三角形列)

Triangle Strips

(三角形带)

Triangle Fans

Flexible Vertex Format (FVF) (灵活顶点格式)

Flexible的意思是“灵活的”。这里不译为“灵活的顶点格式”而译为“灵活顶点格式”是有原因的:前者是一个短语,像是广告词一样;后者才更像是一种名词或术语。所以,我取了后者。灵活顶点格式(FVF)是用来描述顶点属性的一种格式,而这种格式是可以由我们自定义的,所以称它为“灵活顶点格式”。至此,我们至少知道了顶点有三种属性:x值、y值和z值。其实顶点还可以有其他属性,例如颜色与亮度。利用灵活顶点格式(FVF)我们能方便的指定顶点的属性。

如果我们在Direct3D指定了一个多边形,这个多边形将可以被它的各个顶点的属性所填充,带有过渡性的属性填充。我知道这个不太好理解,没关系,下面我们有例子,它也正是这样做的:在我们下面的例子中,将会有一个三个顶点所组成的三角形,三角形的每个顶点的颜色都是不同的,他们分别是红、绿、蓝,电脑中的三原色。三角形将会被这三种颜色混合的、渐变的填充起来。

Vertex Buffers (顶点缓冲)

顶点缓冲就是一块用于保存顶点的内存缓冲区。顶点缓冲可以保存任何的顶点类型。当你的一些顶点已经被保存在顶点缓冲区中,你就可以操作它们了,例如渲染、变换和剪裁。

Colours (颜色)

在DirectX中,如果我们要指定一种颜色,我们可以用D3DCOLOR_XRGB宏。宏中有三个参数,每个参数都是0到255间的整数值,分别用于描述颜色的红、绿、蓝分量,然后D3DCOLOR_XRGB宏会将它们调和,就像水彩调色一样。

例如:

D3DCOLOR_XRGB(0, 0, 0) 是黑色(无色)。

D3DCOLOR_XRGB(255, 255, 255) 是纯白色(满色调)。

D3DCOLOR_XRGB(0, 255, 0) 是亮绿色(没有红与蓝,全是绿色的分量)。

D3DCOLOR_XRGB(100, 20, 100) 是暗紫色 (100 红, 20 绿, 100 蓝)。

运行程序,你会得到一个背景为黑色的窗口。窗口的中央是一个三角形,被三原色过渡填充的三角形,很漂亮,不是吗?真高兴,现在我们已经可以绘制一些真正的图形了。看图来说,上面的一些东西就不难理解了。好了,下面有一幅程序运行时的截图:

嘿嘿,添加了几行代码,得到了如此漂亮的图形,不是很复杂,对吧?

那末,我们都做了什么改动呢?

WinMain

g_pVertexBuffer

这是顶点缓冲的指针。注意它是全局的,所以可以被所有的函数使用。这就是我们存储三角形的顶点的地方了,顶点缓冲,对,就是那个。

CUSTOMVERTEX

这是我们自定义的顶点格式,为什么能自定义呢?对!因为Direct3D支持的灵活顶点格式(FVF)。其中我们都指定了x,y,z,rhw 和颜色属性。

D3DFVF_CUSTOMVERTEX

上面的C USTOMVERTEX乃是我们自定义的顶点格式,但自定义也不能随便定义,我们需要按照一定的规则,而且也需要通知DX我们的格式知怎样定义的。所以,我们定义了这个标识D3DFVF_C USTOMVERTEX,它运用了DX原有的两个标识D3DFVF_XYZRHW和D3DFVF_DIFFUSE(已转换顶点和扩散颜色)定义了我们自己的格式,而且,跟上面我们定义的CUSTOMVERTEX格式是相吻合的。明白了吗?也就是说:我们要按照DX支持的各种顶点属性和它们的标识来组合出我们自己需要的顶点格式和标识,而标识是用来通知DX的。

InitialiseVertexBuffer

这是一个新的函数,你已经猜到了:它是用来初始化定点缓冲的。在函数中,首先定义了一个C USTOMVERTEX 型的数组cvVertices,并按照前面我们所定义的格式输入了三个不同的顶点,位置不同颜色也不同。注意:在本例中,顶点的z值应该在0到1之间,因为现在的程序只能支持一些2D的图形,这样做是为了让程序最简单且容易理解。不用急,以后我们就会创建真正的3D图形了。

然后我们利用设备借口调用了CreateVertexBuffer函数来初始化我们的顶点缓冲。注意第一个参数我们输入了顶点缓冲的大小,因为我们输入了三个顶点,所以是3个C USTOMVERTEX的大小。此函数将给我们一个指向顶点缓冲的指针(g_pVertexBuffer)。

这时我们的顶点缓冲已经创建好了,我们应该把我们指定好的顶点传送给它:锁定顶点缓冲-〉传送已经被保存的顶点-〉解除锁定。到这里,我们的顶点缓冲算是真正的准备完毕了。

Render

我们也细微地改动了这个函数。首先我们捆绑了顶点缓冲到设备数据流,然后设置了顶点着色方法,最后,调用了DrawPrimit ive来完成绘制工作。DrawPrimit ive的第一个参数是绘图方法(就是在文章上面的3D Primitive中我们提到的方法),我们用了三角形列(D3DPT_TRIANGLELIST)。下个参数是起始顶点,最后是需要画的图形的数目,这里我们设置为1,因为只有一个三角形要绘制。嗯,我们还用了D3DCOLOR_XRGB宏使背景成为了黑色(0, 0, 0)。

SafeRelease

我们还创建了这个SafeRelease宏。此宏能安全而简便地释放COM对象。

Summary(摘要)

啊…,第二个教程完成了,你一定有所收获吧?我相信是的。不过我挺累,我已经尽力翻译好了,怎么样?

在此,我们学习了很多理论性的东西,不过,应该很容易,对吧?啊对,你可以随意改动本文的例子,绘制更多的三角形、更漂亮的图案,译者本人(我)就是这样做的,很有意思。下个教程,我们就会创建真正的3D图形了!怎么样?激动吧?呵呵呵呵….

总是我在说,也的给原著点面子吧!

So, there you have it. The second tutorial is now complete. We've learnt a lot in this tutorial: Vertices, Coordinated System s, 3D Primit ives, FVF, Vertex Buffers and specifying colours. To take this tutorial a bit further, try adding another triangle. In the next tutorial we will create our first real 3D object.

第三章: 旋转的立方体

Introduction (序)

上一章,我们绘制了一个2D的三角形,很漂亮。这回呢,我们要创建我们的第一个3D对象:立方体。为了要显示它是真正的3D对象,呵呵,我们要旋转它,这样,你将会看到它的各个面。记住:所有的3D对象都是由三角形构成的(译者:神奇的三角形啊…读者:又来了),所以,我们的立方体是由12个三角形构成的(6个面,每个面需要2个三角形,二六一十二,乘法口诀,会不?)。

3D World Space (3D 世界空间)

上一章我们见到了左手3D迪卡尔坐标系统是怎样工作的,此坐标系统从现在开始将被我们应用。

DirectX的默认是左手坐标系统,以后我们就用左手坐标系统。至于左手坐标系统和右手坐标系统的差别,在此就不多说了,伸出手来就知道了。

Backface Culling (背面拣选)

什么是背面拣选?这是其实是一个很简单的概念。就是:所有的三角形面,面向我们的面将会被渲染出来(可见),否则将不被渲染(不可见,被拣选出来了)。多么简练的一句话,如果你没明白,我举个例子:假如空间中有一个正方形面(要想象成一块方形纸片),我们把正面涂成红色,背面涂成蓝色,你把它拿在手里,如果你没有弄弯它,那你始终只会看见面向你的那个面,而不会看见它背面(有透视眼者另当别论)。那么这个“背面拣选”在Direct3D中有什么用呢?假如我们创建了一个封闭的立方体(要想象成一个方纸盒),那末里面的六个面将不会被我们看见,所以,也不用被渲染。“背面拣选”将使渲染更有效率。

那么怎么知道那个面被渲染而哪个面被拣选(不渲染)呢?一切都在你定义的顶点的顺序上。下面的两幅图演示了如何定义“顺时针”的三角形。如果你定义的三角形是顺时针的,将会被渲染出来;但如果你把它翻过来,那它就变成逆时针的了,就不会被渲染出来。嗯,其实你可以指定哪个面将被拣选,顺时针或逆时针,但是DX默认是拣选逆时针的三角形。

How to make a cube (怎样创建立方体)

下面的两幅图演示了我们的立方体将被怎样创建出来。这里我们用了三个三角带:一个是顶,一个是四个连起来的面,一个是底。下面的图显示了每个三角形带及它们的顶点排列方法。顶点被排列成0到17,也会按照这个顺序被放到顶点缓冲中。还有一幅图显示了我们的立方体(Fig 3.4)。请注意图中哪些顶点重合了,还有就是除了立方体的底面之外的其它面都是顺时针的顶点排列。这是因为我们激活了上面提到的“背面拣选”。

Matrices (矩阵)

矩阵是什么呢?它其实是一个数学主题,所以,在此我只能简要地概括一下。矩阵就像是一个表格,有一定数目的行与列;每个格子中都一个数字或表达式。通过特定的矩阵,我们可以对3D对象中的顶点坐标进行运算,来实现类似移动、旋转、缩放这样的操作。详细内容请参考线性代数学。在DirectX中,矩阵都是4X4的表格。矩阵的类型有三种:World Matrix(世界矩阵)、View Matrix(视图矩阵)和Projection Matrix(投影矩阵)。

World Matrix(世界矩阵)

你可以利用世界矩阵在3D空间(世界空间)里通过修改对象的坐标来完成它们的旋转、缩放或平移操作。所有这些操作(变换)都是关于原点(0, 0, 0)的。单一的变幻(例如平移或缩放等)可以组合起来,形成更复杂的变幻;但要注意各种变幻的顺序很重要,矩阵1X矩阵2和矩阵2X矩阵1是不同的。还有,当你完成了一项世界变幻的矩阵操作时,矩阵跟着将转变所有的顶点。要旋转两个对象,一个关于x轴,一个关于y轴,你应该先完成x轴的变幻,然后渲染第一个对象;再完成y轴的变幻,然后渲染第二个对象。

View Matrix(视图矩阵)

视图矩阵就是摄像机(或眼睛)。摄像机在世界空间中有一个位置,还有一个观察点。例如,你可以把摄像机悬置于某个对象的上面(摄像机位置),把镜头对准那个对象的中心(观察点)。你也可以指定哪面是上面,在我们下面的例子中,我们指定了y轴的正方向是上面。

Projection Matrix(投影矩阵)

投影矩阵可以被想象成摄像机的镜头,它指定了视界(field of view)和前、后裁剪平面。目前我们会在例子中保持一致的设置。

好了,第三章的源代码就在这了,又做了一些新的变化。

相关主题
相关文档
最新文档