Cesium粒子系统(八)
粒子系统
本教程将引导您了解Cesium的粒子系统API以及如何向Cesium应用添加烟雾,火焰和火花等特殊效果。
什么是粒子系统?
粒子系统是一种模拟复杂的物理效应的图形技术。粒子系统是小图像的集合,它们一起形成更复杂的“模糊”对象,如火焰,烟雾,云彩或烟花。通过使用诸如初始位置,速度和寿命之类的属性来指定单个粒子的行为来控制这些复杂效应。
粒子系统效应在电影和视频游戏中很常见。例如,为了表示对飞机的伤害,技术人员可以使用粒子系统来表示飞机发动机上的爆炸,然后渲染一个不同的粒子系统,以表示飞机坠毁时的烟道。
粒子系统基础
我们来看看基本粒子系统的代码。
var particleSystem = viewer.scene.primitives.add(new Cesium.ParticleSystem({
// Particle appearance
image : '../../SampleData/fire.png',
width : 20,
height : 20,
startScale : 1.0,
endScale : 4.0,
// Particle behavior
life : 1.0,
speed : 5.0,
// Emitter parameters
emitter : new Cesium.CircleEmitter(0.5),
rate : 5.0,
emitterModelMatrix : computeEmitterModelMatrix(),
// Particle system parameters
modelMatrix : computeModelMatrix(),
lifetime : 16.0
}));
得到的粒子系统如下所示:
上面的代码创建了一个ParticleSystem,一个对象参数化来控制粒子对象的外观和行为。粒子是从粒子发射器中诞生的 ,然后死亡一段时间。
粒子系统配置的参数可控制单个粒子的外观和行为,发射器的类型和位置以及粒子系统本身的位置和寿命。
其中一些属性是动态的。注意,例如,不是一个颜色属性,而是一个startColor
和endColor
。这些指定了在出生和死亡时会出现什么样的颜色颗粒,并且它们的颜色在其整个生命周期中在这两个值之间平滑地混合。startScale
和 endScale
类似的工作。其余的参数是静态的,虽然一些粒子造型允许用户指定最大值和最小值,并随机分配每个粒子在该范围内的值。
通过更改这些参数可以创建各种不同的效果 – 请在我们的粒子系统演示中尝试。
掌握铯粒子系统只是熟悉不同参数的问题。让我们更详细地讨论这些粒子系统属性。
发射器
粒子诞生时,其初始位置和速度矢量由粒子发射器控制。发射器将每秒生成一些粒子数,由rate
参数指定,使用随发射器类型而定的随机速度进行初始化。
铯具有各种可直接使用的粒子发射器。
BoxEmitter
所述BoxEmitter
类在一个盒子内随机取样位置初始化颗粒,并引导它们从6个框面中的一个的。它接受Cartesian3
指定框的宽度,高度和深度尺寸的参数。
particleSystem : {
image : '../../SampleData/fire.png',
rate: 50.0,
emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(10.0, 10.0, 10.0))
}
CircleEmitter
所述CircleEmitter
类发射器的向上轴的方向初始化的圆内随机在采样位置的颗粒。它接受指定圆的半径的单个浮点参数。
particleSystem : {
image : '../../SampleData/fire.png',
rate: 50.0,
emitter: new Cesium.CircleEmitter(5.0)
}
如果未指定发射器,则会默认创建CircleEmitter。
ConeEmitter
所述ConeEmitter
类在一个锥形的尖端初始化粒子和以随机的角度出锥体的引导它们。它需要一个指定锥体角度的浮点参数。锥体沿着发射器的上轴线定向。
particleSystem : {
image : '../../SampleData/fire.png',
rate: 50.0,
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(30.0))
}
SphereEmitter
所述SphereEmitter
类在一个范围内随机地取样的位置初始化颗粒和从球的中心向外引导它们。它需要一个指定球体半径的浮点参数。
particleSystem : {
image : '../../SampleData/fire.png',
rate: 50.0,
emitter: new Cesium.SphereEmitter(5.0)
}
配置粒子系统
铯具有许多用于微调粒子行为的选项。
粒子发射率
该rate
属性控制每秒发射多少个粒子,这会改变系统中粒子的密度。
您也可以指定一个burst
对象数组,以在指定的时间发射粒子猝发(如上面的动画所示)。这是添加一些变体或爆炸到你的粒子系统的好方法。
将此属性添加到您的particleSystem。
bursts : [
new Cesium.ParticleBurst({time : 5.0, minimum : 300, maximum : 500}),
new Cesium.ParticleBurst({time : 10.0, minimum : 50, maximum : 100}),
new Cesium.ParticleBurst({time : 15.0, minimum : 200, maximum : 300})
],
这些爆发将在给定时间内在最小和最大粒子之间发射。
一生
一些属性控制着粒子系统的寿命。默认情况下,粒子系统将永远运行。
要使粒子系统运行一段时间,请将lifetime
属性设置为所需的持续时间(以秒为单位),并将该loop
属性设置为false。例如,要运行粒子系统5秒钟,请使用:
particleSystem : {
lifeTime: 5.0,
loop: false
}
许多控制粒子行为的属性都有成对的最小值和最大值。这是因为为了创造逼真的效果,粒子会在最小值和最大值之间产生一个随机值。对于这些属性,还有第三个属性可以将最小值和最大值设置为相等,以防您不希望跨粒子进行变化。
发射的每个粒子将在minimumLife
和maximumLife
属性值之间生存一段随机数。例如,要让粒子在5到10秒之间生存,请使用:
particleSystem : {
minimumLife: 5.0,
maximumLife: 10.0
}
设置life
会同时设置。
造型微粒
颜色
除了使用该image
属性指定的基本粒子纹理之外,还可以使用可改变粒子寿命的颜色对粒子进行样式设计。这有助于创建更具动态效果的效果。
例如,下面的代码会使得火粒在出生时变成红色,然后在死亡时转变为部分透明的黄色:
particleSystem : {
startColor: Cesium.Color.RED.withAlpha(0.7),
endColor: Cesium.Color.YELLOW.withAlpha(0.3)
}
尺寸
颗粒的大小一般被控制与minimumWidth
,maximumWidth
,minimumHeight
,和maximumHeight
特性。每个颗粒将与之间的像素的宽度生minimumWidth
和maximumWidth
和之间的高度minimumHeight
和maximumHeight
。
这将创建30至60像素大小的粒子:
particleSystem : {
minimumWidth: 30.0,
maximumWidth: 60.0,
minimumHeight: 30.0,
maximumHeight: 60.0
}
使用width
和height
设置最小和最大尺寸是相同的。
像颜色,颗粒的尺寸可以在其与寿命进行调制startScale
和endScale
特性。这可以让你随着时间的推移使粒子成长或变暗。
这段代码会使粒子的年龄增长到他们开始大小的4倍:
particleSystem : {
startScale: 1.0,
endScale: 4.0
}
速度
当发射器控制粒子的初始位置和方向时,速度由minimumSpeed
和maximumSpeed
设置控制。让我们使粒子在5到10米之间变化。
particleSystem : {
minimumSpeed: 5.0,
maximumSpeed: 10.0
}
设置speed
为使最大值和最小值相同。
军队
为了增加效果的真实性,粒子系统还可以施加重力或风力。
每个粒子系统都有一个强制回调数组,可以在模拟过程中修改粒子的属性。强制回调是一个函数,它接受粒子和模拟时间步骤。大多数基于物理的效果会修改速度矢量以改变方向或速度。以下是一个可以使粒子对重力产生反应的例子:
var gravityScratch = new Cesium.Cartesian3();
function applyGravity(p, dt) {
// Compute a local up vector for each particle in geocentric space.
var position = p.position;
Cesium.Cartesian3.normalize(position, gravityScratch);
Cesium.Cartesian3.multiplyByScalar(gravityScratch, viewModel.gravity * dt, gravityScratch);
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity);
}
该函数计算重力矢量并使用重力加速度(-9.8米每平方)来改变粒子的速度。
现在像下面这样将力加入到粒子系统强制数组中:
particleSystem: {
forces: [applyGravity]
}
定位
粒子系统使用两个Matrix4变换矩阵进行定位:
modelMatrix
:将粒子系统从模型转换为世界坐标。*`emitterModelMatrix:在粒子系统本地坐标系中转换粒子系统发射器。
您可以只使用这些变换矩阵中的一个,并将另一个作为单位矩阵,但我们同时提供了两个方便。要练习创建矩阵,让我们逐步介绍将粒子发射器相对于另一个实体进行定位的过程。
首先让我们为我们的粒子系统创建一个实体来强调。打开Hello World Sandcastle示例并添加以下代码:
var entity = viewer.entities.add({
// Load the Cesium plane model to represent the entity
model : {
uri : '../../SampleData/models/CesiumAir/Cesium_Air.gltf',
minimumPixelSize : 64
},
position : Cesium.Cartesian3.fromDegrees(-112.110693, 36.0994841, 1000.0)
});
viewer.trackedEntity = entity;
这将创建一个以观看者为中心的平面模型。
接下来,让我们确定如何将粒子系统放置在我们的场景中。在这种情况下,让我们添加来自其中一个飞机引擎的火效果。首先让我们创建一个模型矩阵,它将定位和定位与平面实体相同的粒子系统。这意味着我们也想使用飞机的粒子系统的模型矩阵,可以像这样得到modelMatrix:
function computeModelMatrix(entity, time) {
var position = Cesium.Property.getValueOrUndefined(entity.position, time, new Cesium.Cartesian3());
if (!Cesium.defined(position)) {
return undefined;
}
var orientation = Cesium.Property.getValueOrUndefined(entity.orientation, time, new Cesium.Quaternion());
if (!Cesium.defined(orientation)) {
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position, undefined, new Cesium.Matrix4());
} else {
modelMatrix = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()), position, new Cesium.Matrix4());
}
return modelMatrix;
}
现在我们有一个矩阵,它将我们的粒子系统放置在飞机的中心。我们希望发射器位于我们的一架飞机发动机上,因此我们可以创建一个没有旋转的矩阵,并在模型空间中对发动机进行平移。我们可以像这样计算变换矩阵:
function computeEmitterModelMatrix() {
hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, new Cesium.HeadingPitchRoll());
var trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(2.5, 4.0, 1.0, new Cesium.Cartesian3());
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion());
return Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
}
现在我们有了计算变换矩阵的方法,我们可以继续使用一些基本参数创建粒子系统。代码如下:
var particleSystem = viewer.scene.primitives.add(new Cesium.ParticleSystem({
image : '../../SampleData/fire.png',
startScale : 1.0,
endScale : 4.0,
life : 1.0,
speed : 5.0,
width : 20,
height : 20,
rate : 5.0,
lifeTime : 16.0,
modelMatrix : computeModelMatrix(entity, Cesium.JulianDate.now()),
emitterModelMatrix : computeEmitterModelMatrix()
}));
这使我们可以像我们之前的所有例子中描述的那样,在发动机上定位火焰粒子效应。
还要注意,我们可以更新模型或发射器转换矩阵以随时间变化。例如,如果我们想要在飞机上对发射器位置进行动画制作,我们可以修改emitterModelMatrix
而不改动modelMatrix
。这使得在模型空间中重新定位效果变得容易。
这种定位方法并不像指定一个位置那样简单,但它提供了高效灵活的转换,可以实现各种各样的效果。
这就是粒子系统的基础!我们迫不及待地想看看你们会对他们造成什么样的影响。
更多示例代码请参阅: