13.1 公告板
公告板在多数的英文教程中译为Billboard,我们平时逛街的时候,总会看到路边摆放着的交通指示牌、商场周围的广告牌等。这一章我们所学的“公告板”就跟这些指示牌、广告牌等在概念上很类似。只不过这里的“公告板”的概念和用法会更加简单。
在Ogre中(事实上在计算机图形学中也是如此),公告板是在场景中随摄像机角度的变化而变换方向的简单四边形。也就是说,公告板的角度会根据摄像机的位置进行相应的调整,使公告板的正面法向量总是与摄像机方向相同。
通常公告板随着摄像机的视方向旋转以便与摄像机的视线方向对齐。为了效率考虑,公告板与摄像机的视线方向对齐,而不是与从公告板到摄像机的向量对齐。大部分情况下两者没有明显的区别。如果想使用后一种的对齐形式,也可以办到,可以牺牲一些性能作为代价,这个我们在之后的章节会介绍。
图13-1中展示了公告板的朝向位置。
图13-1:在(a)中公告板正朝向摄像机。
在(b)中,摄像机已经移动并且公告板也旋转自动朝向摄像机。
具体来讲,公告板的应用是十分广泛的,我们可以把它想象成一个可以放置任何东西的大的容器,也或者是可以把它想象成一个表层。我们可以将公告板放置在场景中的任何位置,放置好以后,它就会一直朝向摄像机方向,即随着摄像机方向的变换而转动自己的角度。我们可以把普通的文本或是渲染纹理等一些基础的东西放置在公告板上,也可以通过放置一张图片来实现这个图片上的内容要反映的效果,比如我们可以放置一张硝烟滚滚的图片来模拟这种烟雾缭绕的效果。在一些大型的网络游戏中,我们通常会看到一些角色的头上会顶着一些随着角色移动而移动的文字或是图标等等,比如角色名字,这就是通过公告板实现的。
笔者注: 为了提高执行效率,公告板虽然面向摄像机方向,但实际上并不是严格面向从公告板到摄像机的向量,而是有一定的误差,在大多实际应用中,这些误差并不明显。 我们在设计程序的时候可以实现让公告板来“分毫不差”的与摄像机向量对应,不过这会影响系统地执行效率。公告板本身看似很神奇,但是它只提供了一种在三维世界中创建特效的装置。公告板在默认情况下是有Ogre进行管理的,当然我们也可以从Ogre的手中将公告板“接管”过来,但这种做法是不被推荐的。 |
13.1.1公告板集合
公告板不能独立存在,它们也不能自我渲染,它们必须属于某个公告板集合。公告板集合可认为是一组公告板的管理器,公告板集合内的所有公告板有相同的尺寸、相同的材质等等,这样做的原因是相同的尺寸和材质有助于提升计算机的计算和渲染效率。如果一个公告板集合拥有的公告板数量比较多的时候,使用相同的尺寸、相同的材质是十分必要的;不过当公告板集合中的公告板数量很少时,就没必要非得限制其中的公告板尺寸和材质等的一致性了。当然,我们单独改变一个公告板集合中的某一个或某几个公告板的尺寸或材质,但这样做会导致计算机计算和渲染性能的下降,因为公告板集合本身在设计的时候就是针对相同尺寸或材质的公告板进行优化的。
Ogre认为公告板集合是一个独立可操作的单位,集合中的公告板要么都不渲染,要么全部进行渲染。当然,我们也可以对集合中的某个单独的公告板进行操作,但这样做也会导致系统效率的下降。
笔者注: 集合中公告板的位置是相对于集合在场景中挂载场景节点的相对位置。因为所有集合中的公告板都是用了相同的材质,进而可以在相同批次中被渲染,这就意味着对于GPU渲染来说200个公告板和2000个并没有什么大的不同。 |
13.1.2公告板池(Billboard Pools)
在Ogre中使用公告板以及公告板集合的时候,我们需要像使用其他资源一样,对公告板以及公告板集合进行管理,公告板集合聚集在一起就形成了公告板池,公告板池的尺寸对应着公告板池内公告板集合的数量。Ogre会提前做好创建公告板的工作,以便在必要的使用提供给用户使用。公告板池内有两个队列:活动队列和空闲队列,分别用于盛放活动状态和空闲状态的公告板。公告板池的大小可以动态的扩大,可以通过代码将其在需要的时候扩大到原有尺寸的2倍,当然,公告板池尺寸的扩大就意味着要消耗更多的计算机资源来对其进行处理,从而会影响计算机的运行效率,实际应用中并不推荐这种扩大公告板池尺寸的做法,通常为保证系统的效率还是会选择原有公告板池的大小。
13.2 粒子系统
下面请读者思考一下,当我们在3D场景中添加一个人物模型的时候,只需要在程序中添加一句代码就可以轻松的实现,这是因为这个要添加在场景中的3D模型是一个“整体”。那么,我们在3D场景中要如何实现下雨的效果、喷泉喷放的效果、以及爆竹爆炸的效果?相信细心的读者已经可以发现,诸如下雨的效果、喷泉喷放的效果、以及爆竹爆炸的效果这些效果的对象:雨水、喷泉、炸裂的爆竹等等都不是一个独立的“整体”,那么这些效果在Ogre中要如何实现呢?下面,让我们马上来学习粒子系统这一节,相信在这之后读者朋友就可以轻松的实现这些效果了。事实上,粒子系统是3D程序中产生多种视觉特效的基础。虽然有些时候我们也可以用一些其他的方式来实现这些特效,不过使用粒子系统的好处就在于它的简单性。
13.2.1 粒子系统基础与3D场景
粒子系统可以使用相应的脚本来定义,相对于硬编码的实现方式,脚本显得更加容易修改、而且脚本可以更好的为读者使用。如同Ogre系统中任何其它可以通过脚本来定义的系统一样,你也可以完全通过代码来创建和配置粒子系统。在粒子系统中所使用的粒子脚本在实际的使用中其实是一个粒子模板,你可以通过它在程序中产生多个实例。换句话说,你如果想创建多个相同的粒子效果,你不用定义多个粒子脚本,只要从一个脚本创建多个实例就好了。
粒子系统会被挂到场景节点上,因此,节点的平移,缩放,旋转会关联到粒子系统,影响粒子反射。进一步说,粒子会被发射到世界空间中,这意味着当场景移动时,它会牵连到发射器,但已经发射出去的粒子不受影响。但是随着场景节点的变换,粒子发射器却跟随着一同产生相应的变换,发射出来的粒子却被遗留在后面(这就好像,移动的燃烧物遗留下来的烟迹一般)。假如需要这些粒子受结点的影响,可以把粒子发射到本地空间(local space)中。粒子系统不能无限制的发射粒子,它有一个限额(quota)。一旦到达限额,粒子系统不会再发射粒子,直到已经存在的粒子消亡。在默认的情况下,这个限制的数量是10,所以在你真正的应用中,需要把这个数值扩大到你需要的量上面。
笔者注: 粒子系统必须拥有一个发射数量的配额,这就是它发射粒子的数量限制。一旦发射出来的粒子总数达到了这个限额,粒子系统就会停止发射,直到已经存在的粒子在达到其生命周期消失后,然后才能继续发射新的粒子。在默认的情况下,这个限制的数量是10,所以在实际应用中,需要及时设置这个数值已达到我们期望的目的。 |
13.2.2 创建第一个粒子系统
在进行详细介绍Ogre的粒子系统之前,我们同样先来看一个简单的示例,让我们一睹Ogre中的粒子效果。
同样,我们使用我们在前面章节保存的模板代码,修改createScene函数中的内容如下:
void createScene() { Ogre::ParticleSystem*partSystem =mSceneMgr->createParticleSystem("Smoke","Examples/Smoke"); mSceneMgr->getRootSceneNode()->attachObject(partSystem); } |
编译并运行程序,你将会看到以下效果:
代码分析:
我们可以看到通过简单的两行代码就可以看到一个相当不错的烟雾特效,其实读者朋友应该不难想象,虽然我们在程序中只加了两行代码,但是大部分的内容都和我们定义材质的时候一样,粒子脚本允许你实例化的在你的脚本中定义粒子系统,而不必在源代码中进行设置,使得你做任何修改都能得到快速回应。在程序代码中,我们只需要知道我们定义的粒子名,创建之后把它挂接在相应的节点上即可。知道了这些,我们下面的内容就像大家逐步介绍粒子脚本中各项内容的定义及其各参数的意义。
粒子系统脚本在系统初始化时被装载,默认情况下它在普通资源所在位置寻‘.particle’后缀的文件并分析它。一旦脚本被分析完,你就可以基于这些代码使用SceneManager::createParticleSystem()方法对其进行实例化。
几个粒子系统可以被定义在单个脚本中。脚本格式是伪C++的,用大括号({})作为段分隔符,用'//'开始一行表示注释(注意,不允许嵌套注释)。一般格式如下面典型例子所示:
// A sparkly purple fountain particle_system Examples/PurpleFountain { material Examples/Flare2 particle_width 20 particle_height 20 cull_each false quota 10000 billboard_type oriented_self
// Area emitter emitter Point { angle 15 emission_rate 75 time_to_live 3 direction 0 1 0 velocity_min 250 velocity_max 300 colour_range_start 1 0 0 colour_range_end 0 0 1 }
// Gravity affector LinearForce { force_vector 0 -100 0 force_application add }
// Fader affector ColourFader { red -0.25 green -0.25 blue -0.25 } } |
脚本中每个粒子必须被给一个名字,第一个大括号之前的那行,上面例子中是'Examples/PurpleFountain'。这个名字必须是全局唯一的。可以包含路径字符(就像上面例子那样),从逻辑上区分开你的粒子系统,并且可以避免重名,但是引擎并不把它视作是一种层次结构,而是把它当作是一个字符串。
Ogre中一个粒子系统通常由三部分构成:粒子发射器、粒子、粒子影响器(可选)。其中最重要的是粒子本身,一个粒子通常使用一个四边形(quad)或者点,然后赋予指定的颜色或纹理之后显示出来。
下面我们来介绍一下发射器和影响器的概念。
·发射器(emitter)
粒子发射器可以看作一个发射粒子的“装置”,这应该非常容易理解。在Ogre中添加一个发射器非常简单,只需要一句代码即可完成,只要以关键字“emitter”开头,然后后面跟上发射器的类型名字即可。
Ogre现在支持的发射器类型有一下几种:
(1)点(Point)发射器,从某一点处向外发射粒子;
(2)盒子(Box)发射器,在一个类似于盒子的四方体内向外发射粒子;
(3)圆柱体(Cylinder),在圆柱体空间内向外发射粒子;
(4)椭圆体(Ellipsoid)发射器,从一个椭圆体空间内向外发射粒子;
(5)空心椭圆体(HollowEllipsoid)发射器,与上一中“椭圆体发射器”不同,这种发射器是空心的,也就是说它只从椭圆体的表面向外发射粒子;
(6)环形(Ring)发射器,在一个环形上面向外发射粒子。
与场景中的普通物体一样,粒子系统也是被绑定到场景节点上的,而且发射器发射出来的粒子的速度、方向都是可以设置的。粒子发射的速度用粒子数/秒来表示,我们可以将这个衡量粒子发射速度的值设置为一个固定值,也可以将其设置为一个随机值。另外,发射器的持续喷射粒子的时间、颜色等等参数都与发射速度类似,可以将其设置为一个固定值,也可以将其设置为一个随机值。在粒子系统中有一个angle参数,用来设置粒子发射方向的角度,例如:如果angle的值被设为0,那么粒子将沿直线发射;如果angle的值被设置为180,那么粒子将会在180°的角度内向外发射,也就是全方向发射。
·影响器(affector)
粒子影响器的作用是,在粒子发射期间对粒子的属性进行修改。粒子影响器的种类有如下几种
(1)LinerForce影响器。这种影响器用于对发射出的粒子产生一个作用力;
(2)ColourFader影响器。这种影响器用于改变发射出的粒子的颜色;
(3)Scaler影响器。这种影响器用来改变发射出的粒子的大小;
(4)Rotator影响器。这种影响器通过旋转粒子上面的贴图纹理来实现对粒子的选择操作。
笔者注: 在Ogre中也可以通过插件的形式添加新的粒子影响器。通常,粒子影响器并没有一个统一的属性,需要用户根据实际情况进行设置。 |
13.2.3 粒子系统基本属性及其发射器分析
下面我们就通过自己手动创建一个简单的粒子系统来逐步了解里面每一部分的内容。
粒子系统定义在*.particle的文件中,因此,我们在media/particle文件夹下新建一个文件名叫MyParticle1.particle的,用文本编辑器打开这个文件:
第一步,定义粒子系统的名字为MySmoke1:
particle_system MySmoke1 { |
第二步,定义粒子系统的材质属性,并设置粒子的宽度和高度为10个单位:
material Examples/Smoke particle_width 10 particle_height 10 |
这里material属性是设置这个系统中的全体粒子将要使用的材质的名字。此系统中的全部粒子使用相同的材质,尽管每一个粒子可以通过使用它自己的颜色属性为材质附加颜色。
第三步,我们想要最多同时出现500个粒子,并设置粒子渲染器的属性:
quota 500 billboard_type point |
这里quota设置这个系统在某一时刻所允许包含的最多粒子数,当达到这个限制时,粒子发射器不允许再发射粒子,直到某些粒子被消灭(例如,它们的time_to_live存续时间用尽)。值得注意的是,你几乎肯定是要改变这个设置的,因为默认值太短了(粒子池只能增加,而不能减少)。
我们再来看看billboard_type这个属性,这实际上是‘公告板’粒子渲染器(默认)的一个属性,同时也是通过在系统声明中直接声明的方法给粒子渲染器传递属性的一个示例。使用默认渲染器的粒子被用公告板进行渲染(前面在公告板部分我们已经分析过公告板的概念),即由两个旋转到面向指定方向的三角形组成的矩形构成的平面。但是,定向一个公告板有不止一种方法,传统方法是公告板直接面对摄像机:这也是默认的方法。但是,这种安排只是对于表现像光晕一样的模糊的球状物看上去还算可以。对于更多的诸如激光射线这样的线性效果,事实上你想要粒子有自己的方向。读者朋友可以查看帮助文档学习一下其它几个参数的意义,我们这里使用point也是默认的选项,它近似于球状粒子并且公告板总是完全面对摄像机。
第四步,我们再定义一个发射器,让它从一个单一的点处以每秒3个的频率发射粒子,并且设置粒子发射器的方向为(1,0,0),粒子发射时的速率为每秒移动20个单位:
emitter Point { emission_rate 3 direction 1 0 0 velocity 20 } |
到此为止,我们的整个脚本就编写完毕了,不要忘了最后还有一个大括号别忘记加上:
} |
完整的脚本代码如下:
particle_system MySmoke1 { material Examples/Smoke particle_width 10 particle_height 10 quota 500 billboard_type point emitter Point { emission_rate 3 direction 1 0 0 velocity 20 } } |
最后,我们把程序里createScene函数中对粒子名调用的代码改为我们新创建的粒子名即可:
Ogre::ParticleSystem*partSystem =mSceneMgr->createParticleSystem("Smoke","MySmoke1"); |
编译并运行程序,你可以看到如下效果:
13.2.3 粒子系统更多功能介绍
前面我们已经创建了我们的第一个粒子系统,现在我们在此基础上添加修改更多的参数,让我们的粒子系统内容更丰富。
修改前面我们定义的粒子脚本文件中的Point发射器的内容,在其中增加如下内容:
angle 30 time_to_live 10 colour 0 1 0 1 |
编译并运行程序,由于我们会看到以下效果:
代码分析:
这里我们给粒子发射器新添加了三个属性:angle、time_to_live、colour。
其中angle设置发射器的粒子可以偏离发射器方向的最大角(按照角度计算),我们这里设置为30表示允许粒子在任一方向上最多偏离发射方向30度,如果我们设置为180则意味着可以朝任意方向发射,设置为0则意味着总是精确地沿发射器方向发射。
time_to_live是设置每个粒子在被销毁之前存活的秒数,粒子影响器是可以改变这个数值的,但是这个值是发射时才传给粒子的。如果我们想给粒子的存活时间设定一个范围,我们可以使用time_to_live_min和time_to_live_max,这两个属性除了是设置一个生命时间范围以外,其它的与time_to_live一样,并且每个粒子在发射时得到这一范围内的一个随机的数值,作为其存在时间。
colour是为所有发射的粒子设置一个静态颜色,也可以参看colour_range_start和colour_range_end属性,设置一组颜色,这样的话实际的颜色将会在这两个值之间随机选择。颜色参数的格式是“r g b a”,每个分量的取值范围是从0到1,alpha值是可选项(如果未指定,则假定alpha为1)。还有一点需要注意的是如果我们在设置这个属性时看不到预想的颜色效果,请检查一下是不是我们把colour写成了color,因为Ogre中采用的是英式英语的用法,所以很多时候如果我们用美式英语的单词拼写方式可能会出现拼写错误。
修改前面我们定义的粒子脚本文件中的Point发射器的内容,如下所示:
emitter Point { emission_rate 30 //修改 direction 1 0 0 velocity 20 duration 1 //新增加 repeat_delay 1 //新增加 } |
编译并运行程序,你会看到以下效果:
代码分析:
这次我们又对Point发设置做了一些修改,首先把发射频率修改为每秒30个;然后我们又新添加了两个例子发射器的属性:duration和repeat_delay。repeat_delay属性是设置重新开始发射需要等待的秒数,我们也可以使用repeat_delay_min和repeat_delay_max两个属性设置一个时间范围,而不是设置一个固定的值;duration属性是设置发射器处于活动状态的秒数,当然发射器可以被通过repeat_delay再次打开。数值0意味着无限时,同样我们也可以通过duration_min和duration_max两个属性设置一个时间范围,而不是一个固定值。
·其它发射器
前面我们一直在使用Point发射器,但是我们应该知道Ogre中不仅仅只有它,还有一些功能更强的粒子发射器,下面我们就介绍几个,学习之后大家就可以很好地了解各种粒子发射器的使用技巧以及什么情况下该用什么发射器了。
修改我们前面定义的Point发射器类型为为Box,内容如下所示:
emitter Box { height 50 width 50 depth 50 emission_rate 10 direction 0 1 0 velecity 20 } |
代码分析:
这里我们使用的Box发射器是从一个三维盒子里的随机位置发射粒子,我们用到的它的三个属性width、height、depth分别代表了宽度、高度和高度,除此之外我们这里用到的它的其它属性和Point发射器是一样的,这里就不再讲解。
我们再来看一个发射器:Ring发射器。它从一个环状区域发射粒子,其中两个参数inner_width和inner_height分别代表不发射任何粒子的内部宽度和高度。编译并运行程序,你将看到如下效果:
影响器分析
我们已经为我们的系统增加了一些基本属性以及增加了发射器,我们已经知道了通过粒子发射器在我们创建粒子的时候可以改变它的行为和外观,但是一旦粒子发射出去,粒子发射器对它就没有多大的可控性了,那么现在我们再来看一下粒子影响器的使用,使用它可以在一个粒子的整个生命周期中改变它的外观和行为。
改变我们前面我们定义的粒子脚本文件中的发射器类型为Point,内容如下所示:
emitter Point { emission_rate 30 direction 1 0 0 velocity 20 time_to_live 100 } |
然后,由于这里我们想让粒子每秒增大5被,因此我们增加一个Scaler影响器:
affector Scaler { rate 5 } |
编译并运行,你会看到以下效果:
代码分析:
前面的内容,我们并没有多大修改,只是为我们的粒子系统增加了一个Scaler类型的粒子影响器,这个粒子影响器调节飞行中的粒子的大小,rate属性是设置每秒内在x和y方向上对粒子的调节量。
为了更好的了解各种不同的粒子影响器,现在我们再为粒子系统增加一个ColourFader类型的影响器,用来修改飞行中的粒子的颜色(由于我们可以同时增加多个粒子影响器,所以原来的Scaler影响器不用删除)。
affector ColourFader { red -0.25 green -0.25 blue -0.25 } |
编译并运行程序,你会看到以下粒子有个又白到绿逐渐渐变的效果:
代码分析:
ColourFader影响器,它的中red、green、blue、alpha这几个熟悉想必大家已经知道,分别代表着设置每秒时间内粒子颜色中的各个分量的调整量。由于red和blue分量逐渐递减,而green分量一直不变,所以最终呈现的效果是绿色。
颜色的渐变效果我们已经实现了,但这不足以满足我们的需求,因为单一的颜色渐变效果并不能满足我们复杂的效果要求,这里我们或许会首先想到,如何实现二级渐变?Ogre中还为我们提供了另一个和ColourFader影响器类似的ColourFader2影响器,只不过这个影响器有两个颜色改变状态,在粒子存续期内,指定还剩一段时间时,激活第二个颜色改变状态。
第一步:修改粒子中Point发射器的time_to_live属性,设置为4,如下:
time_to_live 4 |
第二步:删掉我们前面增加的ColourFader影响器,增加一个新的ColourFader2影响器,如下:
affector ColourFader2 { red1 -0.5 green1 0 blue1 -0.5
state_change 2
red2 0.5 green2 -0.5 blue2 0 } |
编译并运行程序,你将看到以下效果,粒子颜色有白色到绿色然后再到红色的转变:
代码分析:
ColourFader2中的red1、green1、blue1代表了第一个状态期间每秒时间内粒子颜色的各分量的调整量,red2、green2、blue2代表了第二个状态期间每秒时间内粒子颜色的各分量的调整量,而state_change属性是表示当一个粒子还有这么多存续时间时,它将转入状态二。这样我们就可以知道,每个粒子存续时间为4秒,在前两秒时粒子颜色为状态一,也就是红和蓝颜色分量每秒减去0.5,而绿色分量不变,因此在前两秒结束的那一刻颜色值为(0,1,0),所以前两秒整个过程是由白(1,1,1)到绿(0,1,0)的渐变;在后两秒,时颜色为状态二,也就是红颜色分量每秒加去0.5,绿颜色分量每秒减去0.5,蓝颜色分量不变,因此在后两秒结束的那一刻颜色值为(1,0,0),所以后两秒整个过程是由绿(0,1,0)到红(1,0,0)的渐变。
了解了二级颜色渐变,我们再发散一下思维,就不难想到多级颜色渐变,那我们如何实现这个效果呢?Ogre中同样给我们提供了另外一个和ColourFader、ColourFader2类似的ColourInterpolator影响器,它也是修改飞行中的粒子颜色,只不过这个影响器有一组不定个数的已经定义好的状态,它在粒子存续期内在几种状态间插值变换粒子的颜色。属性格式如下所示:
time0
状态0的时间点。
格式:time0 <0到1,基于粒子的存续时间>
示例:time0 0
默认:1
colour0
状态0时的颜色。
格式:colour0 <r g b> [<a>]
示例:colour0 1 0 0 1
默认:0.5 0.5 0.5 0.0
time1
状态1的时间点。
格式:time1 <0到1,基于粒子的存续时间>
示例:time1 0.5
默认:1
colour1
状态1时的颜色。
格式:colour1 <r g b> [<a>]
示例:colour1 0 1 0 1
默认:0.5 0.5 0.5 0.0
time2
状态2的时间点。
格式:time2 <0到1,基于粒子的存续时间>
示例:time2 1
默认:1
colour2
状态2时的颜色。
格式:colour2 <r g b> [<a>]
示例:colour2 0 0 1 1
默认:0.5 0.5 0.5 0.0
[...]
为了和原来的代码进行对比,我们在MyParticle.particle文件中新创建一个粒子系统名叫MySmoke2,大部分内容不变,只修改颜色影响器的部分,如下所示:
particle_system MySmoke2 { material Examples/Smoke particle_width 10 particle_height 10 quota 500 billboard_type point emitter Point { emission_rate 30 direction 1 0 0 velocity 20 time_to_live 4 } affector Scaler { rate 5 } affector ColourInterpolator { time0 0 colour0 1 1 1 time1 0.25 colour1 1 0 0 time2 0.5 colour2 0 1 0 time3 0.75 colour3 0 0 1 time4 1 colour4 1 1 1 } } |
编译并运行程序,我们就可以看到多级渐变的效果了:
ColourInterpolator影响器和前面我们提到的ColourFader、ColourFader2两个影响器相比有两个主要的不同,第一就是我们看到的它可以设置多级颜色渐变,第二个就是属性的设置方式不同,因为ColourInterpolator影响器不是通过设置每秒时间内粒子颜色中分量的调整量来设置颜色的,而是通过在各个状态时间点标记不同的状态颜色的方式来我们脚本中的格式的,虽然在底层实现来说都是通过插值运算的方式实现,但是笔直认为ColourInterpolator这样方式各符合我们编写脚本的习惯。
Ogre中提供了很多标准粒子影响器,下面我们再来了解一个比较有趣的粒子影响器DeflectorPlane,deflector在英文中有偏转、导向的意思。的确,DeflectorPlane影响器的功能和其名字所表达的意思很类似,它通过定义一个平面,这个平面会反弹碰到它的粒子,从而达到改变粒子方向的目的。
接着在前面的MySmoke2中增加一个DeflectorPlane影响器,如下:
affector DeflectorPlane { plane_point 30 0 0 plane_normal -1 1 0 bounce 1.0 } |
编译并运行程序,你将会看到如下效果:
代码分析:
这里DeflectorPlane影响器中添加了三个属性:plane_point、plane_normal、bounce。plane_point指的是反弹平面,它与plane_normal一起使用,plane_normal指的是反弹平面的法线向量,这样通过反弹平面上的一点和法线向量就能确定的平面就是我们所需的反弹平面;bounce代表了当一个粒子被反弹时的弹力大小,0表示没有反弹,1表示100%反弹。由于我们定义了一个反弹平面,因此我们最终会看到粒子碰到反弹平面的时候发生了偏转。
我们可以在此基础上在增加一个DeflectorPlane影响器,如下:
affector DeflectorPlane { plane_point 0 40 0 plane_normal -1 -1 0 bounce 1.0 } |
编译并运行,我们可以发现粒子偏转了两次,原因很简单,因为我们添加了两个反弹平面:
学习了这么多关于粒子系统的内容,想必现在大家已经可以通过脚本来写一些较为复杂的粒子效果了吧,下面我们列举一个比较复杂的示例,让大家再来温习一下自己前面的所学,看看是否能看明白这些,并真正动手写出来,不要把它想得多么复杂,这里面用到的基本上都是上面介绍过的概念:
particle_system MyEffect1 { quota 2000 material Examples/Flare particle_width 3 particle_height 3 renderer billboard billboard_type point
emitter Ring { colour 0 0.4 1 1 direction 0 1 0 emission_rate 200 position 0 -20 0 velocity 0.01 time_to_live 3 width 60 height 60 depth 2 inner_width 0.9 inner_height 0.9 }
emitter Point { angle 4 colour 0.23 0.54 0.35 1 direction 0 -1 0 emission_rate 80 position 0 20 0 velocity_min 10 velocity_max 20 time_to_live_min 1.5 time_to_live_max 2.5 }
emitter Point { colour 0.96 0.63 0.77 1 colour_range_start 0.96 0.63 0.77 1 colour_range_end 0.39 0.39 0.84 1 direction 0.6 0.8 0 emission_rate 20 position -30 -20 0 velocity 40 time_to_live 1.2 duration 4 repeat_delay 2 }
emitter Point { colour_range_start 0.96 0.63 0.77 1 colour_range_end 0.39 0.39 0.84 1 direction -0.593886 0.804549 0 emission_rate 20 position 30 -20 0 velocity 40 time_to_live 1.2 duration 4 repeat_delay 2 }
emitter Point { angle 10 colour 1 1 1 1 direction 0 1 0 emission_rate 10 position 0 20 0 velocity_min 40 velocity_max 50 time_to_live_min 4 time_to_live_max 6 duration 0 repeat_delay_min 0.5 repeat_delay_max 1.5 } /*去掉注释将会是另一种效果 affector LinearForce { force_vector 0 -500 0 force_application add } 去掉注释将会是另一种效果*/ } |
把程序中对应粒子系统名改为“MyEffect1”,编译并运行程序,去掉上面脚本最后几行的注释,前后你会看到如下两种效果:
PS:很久以前就打算把学习Ogre中遇到的知识分享给大家(虽然只是一些皮毛),但是说来惭愧,一直很懒,直到最近才抽出点时间写一些自己的理解(Ogre入门级的东西),所以难免会有很多不足之处,分享是一种快乐,同时也希望和大家多多交流!
(由于在Word中写好的东西发布到CSDN页面需要重新排版(特别是有很多图片时),所以以后更新进度可能会比较慢,同时每章节发布的时间可能不一样(比如说我首选发布的是第二章,其实第一章就是介绍下Ogre的前世今生神马的,相信读者早就了解过~~~),但是我会尽量做到不影响大家阅读,还望大家谅解。)
上述内容很多引用了网上现有的翻译或者内容,在此一并谢过(个人感觉自己有些地方写得或者翻译的不好),还望见谅,转载请注明此项!