基于DIRECTX的3D粒子系统构建1

来源:互联网 发布:克洛普 知乎 编辑:程序博客网 时间:2024/06/05 21:20

                                  

 

“电实际上是由极细的微粒构成,称为电子,通常无法用肉眼看到,除非喝醉了。”

                                                                               ————大卫.巴利

    在游戏制作的2D时代,我们就见到过不少加入了粒子系统的特效。比如暗黑破坏神中的魔法效果,就大量使用了粒子效果。进入3D时代,在游戏使用粒子系统的情况变得更为普遍,对游戏设计者来说,基于DIRECTX制作粒子系统也变得更方便——尤其在微软从DIRECTX8.0开始加入Point Sprites 之后。

 

    本文将会介绍粒子系统在3D游戏中的应用,然后,会在基于DIRECTX环境下给出一些3D粒子系统实现的具体方案。

 

 

一、3D粒子系统在游戏中的应用。

 

    在自然界中,有很多难以用具体的形状,大小来描述的物体,比如一堆火,一团烟雾,一群蜜蜂。但组成这个物体的每一个元素,我们都能描述出来,比如火是由很多不同大小的火苗组成的,烟雾是由细小的粉尘组成的,蜂群是由一只只蜜蜂组成的。而这种类似的情况,我们都能用粒子系统来描述。

 

    什么是粒子系统?粒子系统是由总体具有相同的表现规律,个体却随机表现出不同的特征的大量显示元素构成的集合。

 

       这个定义有几个要素:

1、 群体性:粒子系统是由“大量显示元素”构成的。因此,用粒子系统来描述一群蜜蜂是正确的,但描述一只蜜蜂没有意义。

 

2、 统一性:粒子系统的每个元素具有相同的表现规律。比如组成火堆的每一个火苗,都是红色,发亮,向上跳动,并且会在上升途中逐渐变小以至消失。

3、 随机性:粒子系统的每个元素又随机表现出不同特征。比如蜂群中的每一只蜜蜂,它的飞行路线可能会弯弯曲曲,就象布郎运动一般无规则可寻,但整个蜂群,却是看起来直线向一个方向运动(这就是上一点所说的统一性)。

 

 

 

 

设计这样的粒子系统,能够在游戏中产生与自然云雾相似的物体,并且这些物体由于随机性的作用,使环境变化丰富多彩,能够给游戏增加强烈的视觉吸引力。

 

下面看一些粒子系统在当前流行的3D游戏中的应用:

 

1、《魔兽世界》

 

 

    

              2:绷带的粒子效果

 

 

 

       魔兽中打绷带,加血,人物周围都会出现图示的符号在缓慢上升最后逐渐消失,这个粒子系统是由两种元素组成的——红十字符号和星星光效,每个元素都会上升,消失,而每个元素上升的速度和消失的时间都在一定范围内随机。

 

 

 

       2、《帝国时代3

 

 

 

 

 

 

 

 

《帝国时代3》的炊烟,也是由粒子系统构成的(图3),为了看得更清楚,笔者调整了游戏设置(图4),可以看到在没有ALPHA镂空的情况下,烟雾很明显是由一些片元构成的,每一个片元都会由小变大,而且逐渐变得透明。并且每个片元在上升过程中都会不断旋转,而这些片元的扩大和旋转,变透明的时间都在一定范围内随机。

 

 

 

 

 

 

 

 

二、粒子系统的构成

 

1、发射器(枪)

 

发射器好比一把的枪,粒子往往是由这把枪产生并发射的,发射器将每个粒子的参数初始化,并且提供所有粒子共同的属性参数(将粒子的共同属性保存在发射器而不是每个粒子里面会很大的节省内存空间)。

发射器的一个重要参数是每个粒子的初始位置,一般而言,可能用到的发射器有点发射器(每个粒子都是从同一点发射),比如爆炸的火花,喷泉等,如果粒子的产生有一定的范围,那就需要矩形发射器,定义一个确定的长宽,粒子在这个矩形范围内随机生成。比如一片沼泽中的雾气,一片区域中的雨雪。总体来说,发射器都具有一定的范围参数,他给粒子的初始位置提供了最初的参数,发射器还保存了其他很多类似的参数,比如粒子的速度范围,透明度范围,渲染方式,以及粒子类型——你将用何种基本显示元素来描绘粒子。

 

 

 

2、粒子类型(子弹)

 

每一个粒子都是枪里的子弹,用何种子弹,将影响你的杀伤力,有些子弹细小,发射缓慢,有些子弹能够迅速发射,而且威力巨大。

 

在粒子系统的最初设计中,所产生的粒子是具有不同颜色,但无法贴上贴图的单象素微粒,采用 D3DPT_POINTLIST of D3DPRIMITIVETYPE绘制

这种粒子类型尽管也能产生丰富的粒子效果,但每个粒子只有一个象素大小,而且无法映射贴图, 因此,在Point Sprites 出现以前,我们都采用BILLBOARD来表现一个微粒元素,BILLBOARD用一个三角扇(两个三角形)表现一个粒子,采用D3DPT_TRIANGLELIST绘制,无论镜头怎样旋转,BILLBORAD都会自动面向镜头,用这种方法,可以表现丰富的自然景物,比如前面看到的所有粒子系统的例子,都有可能全部用BILLBOARD实现(大家可以清楚的看到《帝国3》的每一片烟雾其实就是一个矩形片上面贴了一张烟雾的贴图 ,然后在渲染时做透明处理,而那些矩形片,就可能都是BILLBOARD)。关于BILLBOARD的细节,读者可以在《游戏创作》200509月中查阅笔者的另一篇文章《葵花朝太阳的BILLBORAD算法》。

在微软自从DIRECTX8.0引入Point Sprites之后,建立粒子系统的元素多了一个选择,

 

ordinary point primitives相比,Point Sprites可以有不同大小,并且可以映射贴图;与BILLBOARD相比,Point Sprites在数据结构上就是一个点(BILLBOARD是包含四个顶点,六个索引值的结构),减少了内存消耗,并且在各方向上Point Sprites的显示都是统一的,避免BILLBOARD每次渲染都要计算自身旋转角度的开销。Point Sprites采用D3DPT_POINTLIST绘制。

       当然,要制造一个基本粒子,你可以采用任何你想得到的可见元素,从一个点到一条线、一个面,甚至一个模型,都有可能成为一个基本粒子,但由于粒子系统的群体性特征,你必须选择最简练,占用系统资源最少的类型,因此原则上我们应该避免使用一个有上百个面的模型作为一个有上千个粒子的粒子系统的基本元素。

 

 

3、 粒子池(弹匣)

 

粒子池中存储了粒子系统可能用到的所有粒子,并且用栈,链表等数据结构快速产生删除粒子,它好比一个弹匣,里面放了所有备用的子弹,他比弹匣更强的是,发射完的子弹他还能找回来,下次继续发射。

 

我们知道在粒子系统中会有很多粒子不断产生,消亡。如果每次产生一个粒子,我们

 

new一块内存来存储这个粒子,每次粒子消亡我们都delete掉他,这种操作将产生大量的开销,影响粒子系统的整体运行速度。

 

       利用一个静态的粒子数组可以很好的解决这个问题,在粒子系统刚开始产生时,我们就申请一大块内存区域,填充最大数量的粒子,我们称这个存储区域为粒子池。池中的每个粒子都有自己的编号,并且一开始我们把这些粒子的编号压到一个空闲栈中。在我们发射粒子时,我们从空闲栈中取出所需数量的粒子的编号,然后从静态数组中取得这个粒子。粒子发射器赋予这些粒子新的参数,并且把他加入渲染链表中。在粒子消亡以后,我们把死亡粒子的编号压回空闲栈,并且从渲染链表中删除他。

 

       利用粒子池,我们无须频繁申请和释放内存,可以有效的模拟粒子的产生和消亡过程。

原创粉丝点击