如何学好3D游戏引擎编程(二)

来源:互联网 发布:逆战换弹连炮数据 编辑:程序博客网 时间:2024/05/21 21:48

2。游戏编程所需要的基础知识

我这里介绍下要做一个好的,称职的,游戏程序员所需要。学习就和盖楼一样,要想上层建筑牢固,你就要有坚实的基础,我这里介绍的基础是你从事游戏编程最基础,基础的不能再基础的东西。
2。1 数学
数学是游戏中支柱,没有了它,任何都不要谈,在你编写你游戏的时候,你就会知道,世界抽象成一堆数学是多么的神奇,突然你会觉得以前枯燥无味的数学现在是一顿大餐,但这个是霸王餐。国外人写关于引擎方面书的人,都可以说是数学高手,他们理论和实践都很厉害,让我崇拜的不得了。大学里是你学好数学的最好机会,一定要弄明白它的现实意义,任何理论都不是凭空出来的,它一定有现实基础,这个现实基础,就可以帮助你很好理解这个理论。
2。1。1高等数学——微积分理论
在游戏引擎中,很多游戏特效都是通过微积分方程来解得的,高度仿真是现在游戏的追求,真实感越强就需要越多的计算量。极限,一元微积分,多元微积分,级数,微分方程等等在游戏图形图象和物理上都有明显体现。有时一个硕士或者一个博士为了拟真一个效果要花费几个月或者几年的时间,做为一个游戏程序员,微积分到达什么层次我很难给出定义,但起码如果别人给出了原理我们能看明白,并把它实现,我觉得就很可贵了。
2。1。2线性代数和空间解析几何
在大学课本中,空间解析几何是放在高等数学书里面讲的,但游戏中,它和线性代数放到一起我认为更加合适。线性代数所有知识都要掌握,在游戏中它们比微积分体现的更淋漓尽致,理解上我个人认为相对微积分更容易。
空间解析几何主要讲向量,平面,线,体,这些东西并通过线形代数矩阵进行空间变换,最后达到游戏想要的目标。
2。1。3四元数
这个在大学里面不学数学的,估计很少有人接触,它也是来用来变换空间,理解起来不是那么容易,但最常用的就是用四元数来表示旋转。
我这里只是一概而过,上面任何知识在游戏中都有应用,但大学里的数学不是为了游戏而开设的,所以和游戏中用的数学在知识分列和讲解上还是有很大差异,尤其是线性代数和空间解析几何,不用担心,我在后面介绍给大家一些好的游戏书籍,对大家学习游戏编程和有帮助的。
2。2语言
编写游戏c和c++是你首选,相对来讲C++是你更应该掌握的。
2。2。1 其他语言为什么不是当今流行的编写游戏程序语言?
VB,JAVA,C#,等等其他语言,并不是说它们不能做游戏,它们能做,由于语言本身设计机理的限制,只能做一些对游戏速度要求低的游戏,对于运行速度要求高的游戏,它们被判成死刑。当然这个也取决于硬件的发展,以前8bit FC游戏都用C语言和汇编来写,现在由于硬件速度提高,用VB,JAVA,C#来写这些游戏运行也是可以的,例如现在兴起的WebGame(网页游戏)。但如果你真想做游戏的话,你一定想要了解现在最流行游戏编写,C和C++是你最好的选择,也是你走上真正的游戏编程道路的重要武器。
2。2。2 C和C++应该选择那一个?
C和C++,这里面我还要说一说,我个人更看好C++。大家都知道C是面向过程的,而C++是面向对象的,虽然C++的面向对象特性还不是很完善,但出于对大型软件设计上的考虑,因为游戏引擎是大的工程,框架设计远远要比编程重要,一般框架设计用面向对象方式更直接,所以C++比C更有优越性性,而且如果你合理用好C++,并不见得C++比C速度慢。有时一个软件架构和软件运行上问题,很难取舍,对于大应用程序来说,都是一点点牺牲速度来获得好的架构,是利大于弊的事情,这里确实体现软件工程的重要性质。
2。3。3 汇编,很重要吗?
汇编语言也是你要掌握的,你说你语言学的好,但却不会汇编,是一个天大的笑话。现在很少有汇编高手能写出比编译器优化出来的汇编代码运行效率要高,因为语言的不同,思考问题的方式就会有不同,就象最早纸带机上的原语言一样(可计算性与计算复杂性就讲这东西)。如果游戏都用汇编来写,写代码效率很低,所以我们都用高级语言来写,同时还要与底层有密切联系的,C和C++担任大部分工作量。对于游戏速度频颈问题,有时我们用C和C++即使优化很多,代码精简很多,算法也改良很多,但由于语言本身设计上问题,和高效汇编来编写还是有不同的,这时就要是汇编高手来做速度最快,内存和寄存器使用最少汇编程序。所以汇编还是很重要的。
2。3。4 其他CPU硬件指令
这里只是说 INTER 和 AMD CPU 都支持的指令集,也是最常用指令集。
MMX和SSE SSE2是游戏编程中最常用的指令集,这个指令集是 SIMD(single instruction multiple data),也就是单指令多数据流指令集,一个指令可以处理多个数据流运算。汇编CPU指令,一个指令只能执行一个数据流运算。
例如:
汇编中
ADD EAX,EBX
这是一个加法指令,EAX,EBX是寄存器,是32位的。这个指令就是 EAX = EAX + EBX。这个过程只有一个数据流相加。
而SIMD思想是,如果现在有2个指令
ADD EAX,EBX 
ADD ECX,EDX 
能不能让他们一起执行?所以SIMD 指令提供这样的功能,他用很大的寄存器,前一部分装EAX值,后一部分装ECX值,再用一个寄存器,前一部分装EBX,后一部分装EDX.
SIMD 寄存器分成2部分[1部分][2部分]
SIMD ADD 指令 积存器1 ,积存器2 
运算过程为 寄存器1 [1部分] = 寄存器1 [1部分] + 寄存器2 [1部分] ;
寄存器1 [2部分] = 寄存器1 [2部分] + 寄存器2 [2部分] ;
这2个运行是在一个SIMD积寄存器用硬件来执行ADD 同时运行的。
这里只是说了SIMD思想,现在简单介绍下 MMX,SSE,SSE2。

MMX寄存器是32位的,所以它可以执行4个8bit数据同时运算,也可以执行2个16bit数据同时运算,具体要看使用哪个指令,在早期没有SSE指令时,就用MMX,但MMX有缺点,它和FPU(浮点运算单元,专门执行浮点数运算)共用同样寄存器,所以当你指令有中断,从浮点运算跳到MMX运算,要告诉CPU,从MMX跳到FPU 也要告诉CPU,这样数据要临时保存,降低了处理速度。早期2D游戏经常用这个。
现在SSE,SSE2有自己单独的寄存器可以使用,而且它们是128位的,支持4个32位整数或者浮点数同时运算。
这些指令都没有分支,所以使用时效率要我们掌握,因为执行都是并行的,一个指令完成多个计算,所以即使你编写SIMD代码很差,速度也会提高几倍,游戏中经常用SIMD处理颜色和数学运算问题。在游戏速度瓶颈地方用这样的代码,公德无量。

2。3。5 ASM SHADER语言 和 高级SHADER 语言
开始学游戏编程时,这个知识不一定要具备,因为你不了解3D流水线内部细节学起来还是比较困难,所当你做完“软引擎” 了解3D流水线,在学这个语言很容易,接下来的语言发挥,就靠你自己了。
早期的游戏,所有的图形图象处理基本都由CPU来完成,然后把处理完的数据传到显存,用显卡来显示。现在的设计理念尽量解放CPU,把与图形图象有关的运算用显卡来完成。但早期显卡只支持固定流水线,所谓的固定流水线就是所有3D数据处理过程都是事先用硬件实现好的,这个过程是一个大过程,里面封状了很多小过程细节,用户只需要输入数据,显卡负责输出数据,至于用户无法干预这个大过程,小过程更是接触不到。再说的通俗一点,一个空间3D三角形要想显示到计算机屏幕上,基本要经历2个大过程,顶点处理和象素处理,顶点处理封状了很多空间变换的小过程,象素处理包括象素混合小过程。这个过程是不可以访问的,我们只能通过显卡提供的接口来控制,而且改变方式很单一。(刚接触这些可能不明白,现在你知道的不用太详细,就知道大过程是不可以干预的就可以了,或者是只有很少一部分可以干预)为了让图形图象处理更加完善话,让人们可以参与到整个3D流水线中,实现更多丰富的效果,显卡开始出现GPU单元(图形处理单元),这时的3D流水线从固定流水编成了可编程流水线,有了早期的GPU 指令,大家都称为 SHADER指令,也就是ASM SHADER,和汇编一样,这些指令都是和GPU指令一一对应的,随着硬件更新,GPU越来越强大,支持指令越来越多,ASM SHADER 从1。0 到 1。4 ,到现在3。0版本。由于ASM SHADER 用起来不方便,就象我们用汇编写程序一样,所以又出现了高级SHADER语言,有DirectX3D下支持HLSL(high level shader language)和 OPGL下支持的GLSL(opengl shader language)这些语言都是面向过程。由于硬件设计限制,这些语言不能象C语言那样随意使用,SHADER语言有自己的使用规范,大家学习时一定要弄明白3D流水线内部实现过程,再使用SHADER简直很容易。
还有一个要说的是,GPU现在还不支持分支预测,但GPU编程语言现在已经提供了丰富的条件判断,条件判断还是会影响到速度的。

重点你要掌握的是,数学,c和c++,汇编,数据结构,基本掌握的是计算机体系结构,离散数学,编译原理,计算机网络,操作系统,软件工程,数据库,人工智能。可以说这些是计算机最基础的学科,你只有掌握了它们,无论你专研计算机哪个领域,你的基础都是足够的,游戏编程中这些学科都可以用到,我们不用每个学科都精通的要命,我们要精通的是游戏编程,也就是接触到和游戏相关的,我们有这些基础完全可以看懂,然后我们在用自己时间来去专研这些学科在游戏领域的应用。

四。游戏编程,她的大门已经为你打开。

1。 颜色之迷

计算机怎么显示图形的,这个你必须要弄明白,计算机显示彩色图象是经历了一个什么样的发展过程。
1。1 象素和屏幕显示点
计算机显示一个图象是由象素组成,我们通常说的分辨率就是屏幕上显示多少个象素。如果一个屏幕最大可以支持1024*768那么它也可以支持800*600,当你屏幕分辨率是800*600时,一个象素占据了屏幕多个屏幕显示点,也就是说,只有当你分辨率调节到最大时,屏幕显示点和象素点才是一一对应的,至于一个象素占据多个屏幕显示点后颜色怎么显示这个是硬件的事,我也不是很了解。象素都是2进制存储,然后由硬件根据显存中当前象素值,根据颜色显示模式的设定,来显示指定颜色。
1。2 颜色组成和模式
计算机要显示颜色,每个象素都有自己的颜色,通常颜色有3种模式,一个是调色板模式,一个是16bit模式,一个是32bit模式,我这里说的通常,早期也有4bit模式,我要讲出里面的细节,让看的人真正理解,不是死记硬背,你就会发现实质上只有2种模式,一个是调色版模式和bit显示模式。
我先介绍位显示模式,从4bit开始,早期颜色显示很单调,硬件只支持16个颜色,当然这16个可以是黑白的,也可以是彩色的。总之硬件就支持16个颜色。所以用4bit表示4bit 2进制正好可以代表16个。
随着硬件发展支持的颜色越来越多,发展到16bit,16bit开始有了严格限制,颜色是有三种色彩基元组成,也就是红绿蓝,人送江湖称号RGB,16bit分成1555格式和565格式,1555就是1位给ALPHA(表示透明)分给RGB分别5bit,5bit可以表示色彩基元颜色是32种,RGB组合起来就是15bit,就是2的15次方,可以表示很多颜色了。而565格式没有ALPHA位置,直接分给RGB位数为565,也就是绿色多了一位,传说中,专家说人眼对绿色明感,所以给绿色多分了一位。
而32bit分给 ALPHA 和 RGB 分别是 8888,每个都是8bit。
其实标准的颜色都是每个分量都是8bit,每个色彩基元都是256种,而16bit模式不能显示出真实世界色彩。
调色板模式一般都是针对每个分量是8bit,也就是颜色组成是32位的。调色板模式有一个映射表数组,这个映射表数组每个元素都存放的是32位的颜色,而显存存放的是一个索引,但硬件读出显存当前象素值时,然后用这个值当作索引去映射表数组里面查对应的颜色,然后显示到屏幕上。 
相比较而言,调色板模式是最早期的,例如早期FC 8bit机 每个象素只占8bit,只能表示256种颜色,而我们彩电可以表示很多颜色,为了节省显存,增加处理速度,还显示出多种颜色,FC用调色板模式,而我们想换颜色时,其实只换调色板映射表数组某一个值就可以了,索引都不用变,毕竟索引是写在显存中的,一般改写显存还是速度很慢的。16bit模式也是在处理速度上,节省存储空间上得以应用。毕竟这些显示模式都是为了应付以前硬件速度太慢而设计的,现在一般都用32bit模式。而且无论颜色基元的数字越大表示这个基元颜色越浅。
还有一个要说的就是ALPHA,这个分量是表示透明度的,这个分量如果是8bit,那么它可以表示256种透明程度,255表示不透明,0表示完全透明。
现在大家知道你设置屏幕或者游戏时1024*768*32 什么意思了吧!每个象素占32bit,屏幕显示1024*768个象素。

1。3 颜色的运算
计算机支持颜色运算都是无符号颜色运算,颜色没有负数,而且颜色运算有CLAMP和MOD
如果每个颜色占8bit,颜色表示范围为0-255
这里CLAMP指的是
if(x<0) x=0;
if(x>255) x=255;
这里MOD指
if(x>255) x = x%255;
Color1(a1,r1,g1,b1) Color2(a2,r2,g2,b2) 
颜色加减都是向量加减,每个分量做加减
1。3。1颜色加法
Color3(a3,r3,g3,b3) = Color1(a1,r1,g1,b1) + Color2(a2,r2,g2,b2) 
a3 = a1 + a2;
r3 = r1 + r2;
g3 = g1 + g2;
b3 = b1 + b2;
颜色加法一般都用CLAMP
1。3。2颜色乘法
Color3(a3,r3,g3,b3) = Color1(a1,r1,g1,b1) * Color2(a2,r2,g2,b2) 
a3 = a1 * a2;
r3 = r1 * r2;
g3 = g1 * g2;
b3 = b1 * b2;
颜色乘法一般都用MOD
颜色加法和乘法在象素混合效果上经常用,有时为了到达一个效果,加法和减法混合用,至于什么时候用加法,什么时候用乘法,没有严格的规定,还是要看效果,一般对于全局光照模型颜色之间要用加法的,但其他光照模型可能不同,纹理混合或者纹理和颜色混合,加法和乘法都有各自用途。

2。Directx OpenGL到底用来干什么?

这里只说他们支持图形和图象部分,其他部分不说。
很多人都听过这2个名词,其实他们是一个函数库,这个函数库为我们做了一些最基本的和底层打交道的处理,其他它们还提供了一些常用的3D函数库,算是一个2次开发,其实2次开发一般和底层没有关系,所以在游戏引擎中很多都自己来做,微软做了很多2次开发,可以算是一个引擎。我前面说了,引擎没有明确概念,只有适应程度之分,用它这个提供的来做游戏,还是差很远,做小游戏当然没问题。
我主要说说和底层打交道那部分,DX和OPGL最大功劳在于充分调度和发挥了显卡性能,把显卡的特性用接口的形式提供出来,他们各自都有自己的管理层次,管理方法,管理管线,至于怎么管理,我也不是很清楚,但当你使用和显卡资源相关的API时,你要仔细看这个函数各个参数说明,它会根据你的指定,来管理显卡。但他的管理只是一部分,还有很大一部分要引擎里面自己处理。
如果你不想自己写驱动的话,那么你还想控制显卡,你就要用这些API,D3D(DX中主要处理3D的)和OPGL使用上还是有很大不同,所以学习他们也还要花费一些时间。我当初学习时,由于不了解3D渲染流程,学起来特别困难,很难看懂,我就放弃了他的学习,学习制作“软引擎”(用CPU来实现显卡提供的硬件功能),然后再学D3D,很容易的。有时后放弃是为了选择更好的,并不是真正的放弃。
至于学习D3D还是OPGL,我个人认为无所谓的,但好象OPGL越更新越混乱,没有DX那么清晰,我也是听别人说的,毕竟我不是很了解OPGL。

3。游戏编程中的常用术语

游戏编程充着大量常用术语,我不打算把它们都列出来,实在太多,我想对于初学者是来说,我希望,你在学习游戏编程时,自己多查下资料究竟这些术语都有什么含义,记住一定在学习游戏编程时去查,也就是说,针对问题去查,而不是在没有遇到任何问题时去查。其实我们的教育有个弊端,任何知识我们学了,不知道怎么用。其实很多知识都是我们遇到问题时再去查资料,去找解决方式,而不是在不知道这个解决方式用来解决什么的情况下吓学。
最好大家把这些术语的中文和英文名称看见都能知道是怎么回事,因为你到以后看英文书时,如果你知道这个术语的含义,看起来会很容易。


五 游戏编程中的2D游戏,你首先要做到的。

通往神殿的第一个考验就是这个,不知道你是否能走下来,相信自己会成功,你的信念一定要不可动摇,当你走过这段路的时候,想想你现在所得到的,付出的其实不算什么。
很多人可能会问,我想做3D游戏,2D游戏学它干什么。其实3D游戏处理可以分成2个部分,一个是3D空间数据处理,经过纹理映射把象素写到屏幕缓冲,接下来其他特效处理都是归结到2D问题。
所以你想真正了解游戏图象处理过程,还是要学2D的。2D原理相对3D来说简单很多,学起来也不是很难。我建议去看《WINDOWS游戏编程大师技巧》里面的代码都读明白,它用C语言实现一个小的游戏引擎,我希望你用C++封状成类的形式,重新按照自己规划来实现,最后做出个游戏。用引擎做出的游戏和直接做游戏还是有很大区别的,这样你引擎也就符合引擎的概念,代码重用性更强。这本书用的DirectX中DDraw接口来实现的,你一定要了解你使用的工具,它能用来干什么,它不能用来干什么,这样你才能很好的游戏编程。如果你不了解C语言,怎么用C语言编程,都是一个道理的。我不想在过多详细介绍DDraw为我们提供了什么特性,你自己去看书。
2D游戏中,最常用的概念就是贴图,把一个图象贴到另一个上。2D游戏中一种处理模式是在各个图片上的处理,还有就是在象素上的处理,其实这些都可以归结到象素上的处理,象素处理,就是处理显存数据。
颜色模式,《WINDOWS游戏编程大师技巧》这本书讲的很详细。
2D动画系统,《WINDOWS游戏编程大师技巧》这本书没有详细介绍,但你看它的代码,代码写的很清楚而详细,你就知道的。
GDI 我不知道大家听说过没有,它是WINDOW自带的图形图象接口,我希望大家也能了解下,当时我是GDI和DDRAW一起学的,然后分别做了引擎,2个引擎接口也一样,游戏移植非常容易。

一个最重要的问题就是调试,8BIT模式下的游戏,用编译器带的单步调式是不可能的,我机器死机N回。我现在也没有发现好的办法,最好的办法就是自己做一个LOG日志系统,把所有调式信息都写到文件里,用任务管理器把当前程序关掉,然后看文件写的信息。
2D游戏制作细节我没有详细介绍,毕竟我不是在讲怎么制作2D游戏,我是讲你应该注意什么,怎么学,我想《WINDOWS游戏编程大师技巧》会给你想要的一切。当然我在学这本书前已经有了一些2D游戏基础,以前用VB做过游戏,用GDI也做过,所以学起来还算容易,如果你以前没有任何游戏编程基础就直接用DDraw,那么我希望你多下点工夫,把它制作游戏的流程都搞清楚,记住什么时候用自己的双手做出了自己2D游戏,你才算2D游戏编程过关了。这本书仔细看吧!直到把它所有的精髓都掌握。
还有一个要说的就是,图象处理常用算法,大家可以多看看图象处理的书,游戏中特效经常用到,其实如果你真想一心搞3D,2D上做一个坦克大战这样的游戏就可以了,很多2D处理详细东西,在学3D游戏时,都可以接触的。
六。游戏编程中的3D游戏,考验你耐力和勇气的时候到了!

前面你所遇到的一切都是小小测试,证明你有能力接受这个挑战,在3D游戏这个广阔无垠的天地里,它比2D游戏更有让你想象余地的空间,因为3D游戏不仅仅包括2D游戏所有,而且还包括很多其他东西。努力吧!朋友们,无论遇到什么挫折,都不要放弃,因为她最后会给你想要的。
我不知道其他人学习3D游戏是一个什么样的过程,这里我只介绍我自己的学习过程,因为我是从挫败中走过来的。
开始学3D,脑袋里一片模糊,只有一点点大学里学的计算机图形学相关的知识,我不得不说学校里讲的计算机图形学和游戏还是大相径庭的。
(这里允许我抱怨一下,国外很多大学都开设了3D游戏编程的课程,而且很专业,我看过老外的PPT。相对于国内,也有些,但不专业,我说游戏学院骗钱你不要打我,它确实能让你找到工作,但你做的永远是下手,学不到底层的东西。我看过游戏学院开设的课程,没有一个是有技术含量的,用“外包”形容在贴切不过。道理也很简单,中国现在牛人很少,我说搞引擎的高手全国有1000人都是保守的,真正能搞出名堂的,也不多于200人,这200人里面学习游戏编程经验10年就很多了,中国3D游戏起步很晚,相对国外,中国人爱跳槽的习惯,让任何公司都没有技术积累,发展更是困难,所以人才积累的少,而且这些人都很忙,在加上现在学校教育约束,即使他们想去高校教授游戏课程也是不可能,何况人家都不愿意去,这样中国积累的人才更少)

所以你要系统学习游戏中图形学理论。
这里我经历了游戏学习编程一次比较大的挫败,当时自己是初学者,问过很多人学3D,应该从什么入手。很多人都说从D3D开始入手,于是我做了。我不得不说的是,如果你不了解3D流水线过程,学D3D简直是看天书,当时我以为自己反复的看书,写程序,最后会理解的,浪费了我大量的时间,最后还是无法灵活掌握D3D,如果你无法掌握D3D,想做游戏可能真的很困难。我终于认识到,我选择的路是错误的,那些所谓的高手难道就学D3D学过来的?那么他们花费的时间是可想而知的。因为有些细节你无法掌握,你使用时就觉得匪夷所思。
《3D游戏编程大师技巧》这本书是每个学3D的人都应该看的,这本书把显卡硬件实现的功能都用软件来做,真正让你理解一个3D东西到最后的屏幕显示,是一个什么样的过程。作者实现了一个软引擎,软引擎就是所有的3D功能都是用代码自己写的,没有用什么显卡来做处理的引擎。这本书是一个经典巨著,如果你想学3D,即使死也要把这本书弄明白,这样不辜负作者写这本书留下的汗水,写一本书,尤其这么PERFECT,太不容易了,国内人翻译的也很出色,感谢他们。

0 0
原创粉丝点击