13 Babylonjs基础入门 粒子

本教程将讨论Babylon.js中的粒子系统。粒子通常是小型的精灵,用于模拟难以再现的现象,如火,烟,水,或抽象的视觉效果,如魔法闪光和技能特效。这是通过一个区域发出很多粒子组成的云来完成的。从V3.2版本开始,有特定的发射器将该区域约束为一个盒子、球体或圆锥体的形状。你还可以编写自己的自定义函数来控制粒子云和约束区域。
GPU粒子是粒子系列的最新成员,可以使用适当的浏览器来提高性能。
13 Babylonjs基础入门 粒子
点击查看粒子系统

粒子系统

要实现这一个神奇的效果,首先需要创建粒子系统ParticleSystem对象。

var particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);

创建时需要设置粒子的总量。粒子系统还设置纹理以便在粒子上查看和发射器设置粒子的起始点和扩散方式。
请注意你可以使用ParticleHelper来创建一个默认的配置:

BABYLON.ParticleHelper.CreateDefault(emitter);

完成后,使用粒子系统启动:

particleSystem.start();

停止:

particleSystem.stop();

要延迟粒子系统启动,可以设置particleSystem.startDelay = 3000;定义延迟(以毫秒为单位)。
你也可以设置particleSystem.start(3000);在启动时设置延迟。如果当前设置,当前值将会覆盖particleSystem.startDelay的值。
注意:停止粒子系统将会停止创建新的粒子,但是已经创建的粒子将会继续运行。如果要清空粒子,则需要调用particleSystem.reset()
如果你需要设置粒子系统的运行时间,并且后面可能还会继续运行系统:

particleSystem.targetStopDuration = 5;  //五秒后粒子效果会停止

运行一次就销毁掉,你可以调用粒子系统的particleSystem.dispose()方法。这对于制作射击粒子系统是非常有用的。

particleSystem.disposeOnStop = true;  //粒子效果停止后销毁粒子系统

预运行

从Babylon.js v3.3版本开始,你可以设置粒子提前运行,以确保在显示之前达到预期显示的效果。
为此,你需要设置两个属性:

  • system.preWarmCycles: 获取或设置一个值,设置在首次渲染之前提前执行多少帧(必须在启动系统之前设置此值)。默认值为0
  • system.preWarmStepOffset:获取或设置一个值,指在预启动模式下时每一帧运行的速度和默认速度比。(默认值为1)
    因此,你将系统设置为:
system.preWarmCycles = 100;
system.preWarmStepOffset = 5;
system.start();

它设置将在运行前提前运行100帧,并且每一帧的运算为原来的五倍。如果你要提前运行的周期越长,系统程序启动的越慢。虽然减少运行周期增加每一帧的运行率很有趣。但是记住,如果粒子的生命周期小于单帧运行的帧率,那么将会出现问题。
以下是一个提前启动运行的案例:点击这里

粒子纹理

将纹理图片应用于粒子,例如:
13 Babylonjs基础入门 粒子
设置particleTexture:

particleSystem.particleTexture = new BABYLON.Texture("PATH TO IMAGE", scene);

你还可以将蒙版应用于纹理以过滤某些颜色,或过滤透明通道的一部分

particleSystem.textureMask = new BABYLON.Color4(0.1, 0.8, 0.8, 1.0);

将产生以下效果:
13 Babylonjs基础入门 粒子
要在场景中使用多个纹理,请使用多个粒子系统,所有粒子系统都可以使用相同的发射器对象。

粒子发射器

粒子发射器可以受用三维向量或者模型网格定位,在这种情况下,网格的位置用于定位。

particleSystem.emitter = new BABYLON.Vector3(-1, 2, 3);
var source = BABYLON.Mesh.CreateBox("source", 1.0, scene);
particleSystem.emitter = source;

世界偏移量

从Babylon.js v4.0开始,你可以使用以下方法设置粒子的世界偏移量:

particleSystem.worldOffset = new BABYLON.Vector3(100, 20, -453);

此代码使用世界偏移移动粒子(当你的相机需要保持在世界坐标的原点以提高精度,然后移动世界坐标时)。

粒子扩散和位置

粒子的扩散来至于我们定义的一个盒子,盒子的位置是相对于发射器的位置。发射器的盒子需要知道六个面的位置,这里我们只需要知道盒子的最大点和最小点既可以设置出发射器的扩散位置,即设置粒子系统的minEmitBox和完成的maxEmitBox:

particleSystem.minEmitBox = new BABYLON.Vector3(-2, -3, 4); 
particleSystem.maxEmitBox = new BABYLON.Vector3(4, 2, 3);

盒子可以压缩成一条线,例如x轴:
13 Babylonjs基础入门 粒子

particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0); 
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0);

基础的粒子案例

你可以查看下面两个案例,创建了一个普通的粒子系统,尽管很普通。只有一些粒子出现并扩散到空中消失。
小区域粒子示例
大区域粒子示例
但是,通过我们设置其它属性,很快将粒子变得特别的有趣。

调整粒子系统

下面,我们将了解如何修改粒子的生命周期,大小和颜色,粒子发射器的产生粒子速度,方向(可选是否受重力影响)。你还可以修改它们的旋转,速度和形状。你可以在下面找到修改其参数的配置。

生命周期

一个单独的粒子的生命周期是在产生后到消失(或死亡)所花费的时间。一旦粒子死掉,粒子就会被回收。它的寿命可以通过配置一下两个配置,并从里面随机一个时间作为存活时间:

//存活时间从最小到最大值中间取一个随机时间
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;

从Babylon.js v3.3版本开始,你还可以为有声明周期的粒子系统定义它的粒子的生命周期。比如,如果你设置粒子系统的生命周期为particleSystem.targetStopDuration = 5; 就是粒子系统的生命周期为5秒,那么你可以:

particleSystem.addLifeTimeGradient(0, 0.5);
particleSystem.addLifeTimeGradient(1, 0);

addLifeTimeGradient()方法的第一个参数定义了粒子在粒子系统生命周期出现的时间(0为粒子系统启动时间,1为粒子系统结束时间)。第二个参数是粒子的存活时间。
上面分别设置了粒子在粒子系统开始时的存活时间为0.5秒,而如果在结束时出现,则存活时间接近0秒。
建议至少要为开始和结束设置一个粒子的存活时间。
只要渐变值介于0到1之间,就可以根据需要添加任意渐变。
你还可以通过为每个渐变增加第三个值来定义更复杂的渐变:

particleSystem.addLifeTimeGradient(0, 0.5, 0.8);
particleSystem.addLifeTimeGradient(1.0, 0, 0.1);

在这种情况下,第一个值还是定义了处于粒子系统存活的时间段,后两个值代表粒子将会在两个值中间随机一个粒子的寿命。
要删除某个渐变,你可以调用particleSystem.removeLifeTimeGradient(0.5)

粒子大小

粒子的大小也可以通过设定范围,并在范围内随机生成:

// 设置大小的最大值和最小值
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;

如果将粒子修改为长方形,而不是必须为正方形,则可以使用ScaleX/Y来设置最大值和最小值:

particleSystem.minScaleX = 0.1;
particleSystem.maxScaleX = 0.5;

particleSystem.minScaleY = 0.2;
particleSystem.maxScaleY = 0.4;

从Babylon.js v3.3版本开始,你还可以定义粒子系统生命周期内的粒子大小渐变。
要添加大小渐变,请使用以下代码:

particleSystem.addSizeGradient(0, 0.5);

第一个参数定义了粒子的某个时间点(0代表粒子生成时,1代表粒子消失时间)。第二个参数是粒子处于当前时间时的大小。当前的设置,是粒子产生的初始大小为设置的随机出来的大小的一半(从minScale和maxScale计算)。建议至少为0和1(开始和结束)定义一个渐变:

particleSystem.addSizeGradient(0, 0.5);
particleSystem.addSizeGradient(1.0, 3);

只要渐变值介于0和1之间,就可以根据需要添加任意渐变。
你还可以通过提供第三个值来定义更复杂的渐变:

particleSystem.addSizeGradient(0, 0.5, 0.8);
particleSystem.addSizeGradient(1.0, 3, 4);

在这种情况下,大小缩放会从第二个值和第三个值中间随机一个值来设置粒子大小缩放。
要删除渐变,你可以调用particleSystem.removeSizeGradient(0.5)
处理粒子大小时,你可能需要移动变换中心。默认情况下,变换中心为粒子的中心,如果你需要在粒子的顶部或者底部。值需要调用:

particleSystem.translationPivot = new BABYLON.Vector2(0, -0.5); //这个的变换中心在粒子的底部

下面是一个将变换中心移动到底部的一个案例:冒烟的效果

粒子颜色

可以为粒子设置三种颜色,两种颜色在粒子的生命周期内混合生成,第三种颜色会在粒子消失之前生成。

particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);

从Babylon.js v3.3版本开始,你还可以定义颜色的渐变。如果定义颜色的渐变,则将忽略掉color1,color2和colorDead属性。
要添加颜色渐变,请调用以下代码:

particleSystem.addColorGradient(0, new BABYLON.Color4(1, 1, 1, 0));

第一个参数定义了粒子的某个时间点(0代表粒子生成时,1代表粒子消失时间)。第二个参数是粒子处于当前时间时的颜色。

particleSystem.addColorGradient(0, new BABYLON.Color4(1, 1, 1, 0));
particleSystem.addColorGradient(1.0, new BABYLON.Color4(1, 1, 1, 1));

只要渐变值介于0和1之间,就可以根据需要添加任意渐变。
你还可以通过设置第三个值的一个颜色来定义更复杂的渐变:

particleSystem.addColorGradient(0, new BABYLON.Color4(1, 1, 1, 0), new BABYLON.Color4(1, 0, 1, 0));
particleSystem.addColorGradient(1.0, new BABYLON.Color4(1, 1, 1, 1)new BABYLON.Color4(1, 0, 1, 1));

这种情况下,当到达相应的梯度时,粒子颜色将会从两个颜色中间随机出来一个颜色。
要删除一个设置的渐变,你可以调用particleSystem.removeColorGradient(0.5)
一下是颜色渐变的案例:太阳特效