粒子
粒子
粒子系统作为渲染引擎中非常重要的一个系统,主要用于模拟一些特定的效果现象的技术,而这些现象用其它传统的渲染技术难以实现真实感的效果,经常使用粒子系统模拟的现象有火、爆炸、烟、水流、水花、落叶、云、雾、雪、尘、流星尾迹或者像发光轨迹这样的抽象视觉效果等。以下粒子效果均是基于当前引擎能力实现,相关代码下载请见下方 示例代码 。
要实现上述粒子效果,需要在json里配置相应的粒子系统文件,并在lua文件里控制粒子发射或者粒子相关参数的修改。
粒子制作准备
粒子的渲染材料通常为一张 N*N 的jpg或者png的纹理图片,发射的粒子会以该图片中的元素为基础进行渲染。
以樱花项目为例,该项目用到了三张粒子素材,素材图片统一放在res/texture文件下。
1、第一张素材图是4*4、有着不同花朵样式的图片,通过在json和lua中修改粒子参数及发射时间等,在视频中产生点击屏幕出现花瓣片的效果。
示例case中名称为flower.png:
2、第二张素材图是3*4、有着不同形态花瓣的图片,在视频中产生的效果是从上方飘落。
示例case中名称为yinhua3.png:
3、第三张素材图是张1*1的花瓣片图,在视频中产生的效果为点击屏幕后花朵周围会出现一圈花瓣片。
示例case中名称为yinhuapian.png:
粒子系统在场景中的配置
{
"name": "yinhua1",
"type": "particle", //粒子类型节点
"visible": 1,
"touchable": 0,
"particleSystemSuppl": {
"particlePath": "res/particle-yinhua.json" //粒子系统对应配置文件
},
"position": "0, 0, 0",
"scale": "1, 1, 1",
"rotation": "0, 0, 0",
"children": []
},
{
"name": "yinhua2",
"type": "particle",
"visible": 1,
"touchable": 0,
"particleSystemSuppl": {
"particlePath": "res/particle-yinhua2.json"
},
"position": "0, 0, 0",
"scale": "1, 1, 1",
"rotation": "0, 0, 0",
"children": []
},
{
"name": "yinhua3",
"type": "particle",
"visible": 1,
"touchable": 0,
"particleSystemSuppl": {
"particlePath": "res/particle-yinhua3.json"
},
"position": "0, 0, 0",
"scale": "1, 1, 1",
"rotation": "0, 0, 0",
"children": []
},
说明:
- 樱花case中引入了三个粒子文件,particle-yinhua.json、particle-yinhua2.json、particle-yinhua3.json,这三个粒子文件即具体粒子参数的含义在粒子API一节中有详解。
- yinhua1、yinhua2、yinhua3为三个粒子系统的节点名,在lua里可直接对这三个节点进行操作,即为对粒子系统进行操作。
例如
app.on_loading_finish = function()
scene.yinhua3.particle.emit_status = 1
end
在进入Case时,发射yinhua3节点配置的粒子文件。
应用
下面配置particle-yinhua.json、particle-yinhua2.json和particle-yinhua3.json三个粒子文件。
从上而下飘洒樱花
particle-yinhua.json文件定义了樱花从上而下飘落。
效果:
{
"name": "yinhua",
"particleCountMax":1000,
"material": {
"blendMode":"alpha",
"textureName":"yinhua3.png",
"frameLoop":1,
"frameCount":12,
"frameColums":3,
"frameRows":4,
"frameRandomOffset":12,
"frameDuration":100
},
"emission":{
"emissionLoop":-1,
"emissionRate":200,
"emissionDuration":3000,
"emitterPosition":"500, 0, 2500",
"emissionVelocityMode":"axis",
"emissionAccelecationMode":"axis",
"emitterShape":"box",
"emitterShapeStrectchScale":"1,1,1",
"emitterShapeParam":{
"box":{
"boxLengthX":1500,
"boxLengthY":1500,
"boxLengthZ":10
}
}
},
"particle":{
"lifeTimeMin":3000,
"lifeTimeMax":6000,
"sizeStartMin":60,
"sizeStartMax":60,
"sizeEndMin":40,
"sizeEndMax":40,
"colorStart":"255, 255, 255, 255",
"colorEnd":"255, 255, 255, 255",
"velocity":"-120, 0, -350",
"velocityVar":"70, 100, 100",
"spinAngleMin":30,
"spinAngleMax":120
}
}
- "emitterPosition":"500, 0, 2500"定义了发射器的位置,屏幕中心为(0,0,0),(500,0,2500)表示发射器在右上方。
- "emitterShape":"box"字段定义了发射器的形状,是一个长方体,"emitterShapeParam"字段定义了长方体发射器的长宽高。
- "velocity":"-120, 0, -350"字段定义了粒子的速度,粒子x轴及z轴的负方向都产生了一个速度。
因此樱花会从右上方向左下方运动,且发射器的范围比较大,粒子在这个空间范围内飘落不会显得特别多。
- yinhua3.png如粒子制作准备中所示是一张3*4的贴图,对应设置行为"frameColums":3,列为"frameRows":4;"frameLoop":1, "frameRandomOffset":12,设置了播放序列帧,且粒子初始发射时会从图里的12个樱花样式里随机选出一种发射。
点击屏幕出现樱花
particle-yinhua2.json文件定义了点击屏幕时出现的樱花样式。
效果:
{
"name": "kongmingdeng",
"particleCountMax":1000,
"material": {
"blendMode":"alpha",
"textureName":"flower.png",
"frameAnimated":0,
"frameLoop":1,
"frameCount":4,
"frameColums":2,
"frameRows":2,
"frameRandomOffset":4,
"frameDuration":100
},
"emission":{
"emissionLoop":-1,
"emissionRate":100,
"emissionDuration":3000,
"emitterRotationAxisAngleMin":2,
"emitterRotationAxisAngleMax":180,
"emitterRotationAxisVar":"1, 1, 1",
"emissionVelocityMode":"axis",
"emissionAccelecationMode":"axis",
"emitterShape":"box",
"emitterShapeStrectchScale":"1,1,1",
"emitterShapeParam":{
"box":{
"boxLengthX":100,
"boxLengthY":100,
"boxLengthZ":100
}
}
},
"particle":{
"lifeTimeMin":2000,
"lifeTimeMax":3000,
"sizeStartMin":80,
"sizeStartMax":80,
"sizeEndMin":80,
"sizeEndMax":80,
"colorStart":"255, 255, 255, 255",
"colorEnd":"255, 255, 255, 0",
"velocityVar":"100, 100, 100",
"spinAngleMin":30,
"spinAngleMax":120,
"rotationAxisAngleMin":0,
"rotationAxisAngleMax":0
},
}
- "emitterRotationAxisAngleMin":2,设置了发射器绕轴旋转角度的最小值,"emitterRotationAxisAngleMax":180,设置了发射器绕轴旋转角度的最大值,发射器会绕z轴在2~180度来回旋转。
- "velocityVar":"100, 100, 100",设置了初始粒子速度范围。
- "lifeTimeMin":2000,设置了粒子的最小生存时间,"lifeTimeMax":3000,设置了粒子的最大生存时间,发射的粒子在2s~3s范围内会消失。
- "colorStart":"255, 255, 255, 255",设置了初始粒子颜色,"colorEnd":"255, 255, 255, 0",设置了粒子消失前的颜色,会逐渐透明直至消失。
- "spinAngleMin":30,设置了粒子的最小旋转角度,"spinAngleMax":120,设置了粒子的最大旋转角度,粒子自身会在30度~120度之间来回旋转。
因此点击屏幕后出现的粒子效果为花朵粒子会有一个速度朝着x轴、y轴以及z轴扩散直至消失。
- flower.png如粒子制作准备中所示是一张2*2的贴图,对应设置行为"frameColums":2,列为"frameRows":2;"frameLoop":1, "frameRandomOffset":4,设置了播放序列帧,且粒子初始发射时会从图里的4个花朵样式里随机选出一种发射。
花瓣片以圆圈形式出现
particle-yinhua3.json文件定义了花瓣片以圆环的形式扩散至消失。
效果:
{
"name": "kongmingdeng",
"particleCountMax":300,
"material": {
"blendMode":"alpha",
"textureName":"yinhuapian.png",
"frameLoop":1,
"frameCount":1,
"frameColums":1,
"frameRows":1,
"frameRandomOffset":0,
"frameDuration":100
},
"emission":{
"emissionLoop":-1,
"emissionRate":500,
"emissionDuration":100,
"emissionIdleDuration":2500,
"emitterRotationAxisAngleMax":179,
"emitterRotationAxisVar":"1, 1, 1",
"emissionVelocityMode":"shape",
"emissionAccelecationMode":"shape",
"emitterShape":"circle",
"emitterShapeStrectchScale":"1,1,1",
"emitterShapeParam":{
"circle":{
"circleOutRadius":50,
"circleInRadius":49
}
}
},
"particle":{
"lifeTimeMin":3000,
"lifeTimeMax":3000,
"sizeStartMin":50,
"sizeStartMax":50,
"sizeEndMin":50,
"sizeEndMax":50,
"colorStart":"255, 255, 255, 255",
"colorEnd":"255, 255, 255, 0",
"velocity":"0, 500, 0",
"spinAngleMin":30,
"spinAngleMax":120
},
}
- "emitterShape":"circle",发射器的形状为圆环;"circleOutRadius":200,设置了圆环发射器的外圆半径;"circleInRadius":150,设置了圆环发射器的内圆半径 ;因此粒子发射的时候会从内圆向外圆发射。
- "velocity":"0, 500, 0",设置了粒子的速度,沿y轴方向有一个速度,所以向y轴扩散的速度会比较快。
- yinhuapian.png如粒子制作准备中所示是一张1*1的贴图,对应设置行为"frameColums":1,列为"frameRows":1。
粒子系统在手势交互中的应用
手指接触屏幕出现粒子还需要在Lua里进行相关配置,通过on_touch_event接口开发者可以拿到发生在屏幕上的交互信息的坐标以及状态,已知坐标以及状态可以组合实现多种粒子效果,要拿到这些信息首先我们需要注册手势回调的函数来监控在屏幕上发生的交互。
代码示例:
scene.on_touch_event = function(etype, ex, ey)
if (etype == ESCROLL_UP) then
//该判断里为单指抬起时需要进行的操作
scene.yinhua2.particle.emit_status = "0"
scene.yinhua3.particle.emit_status = "0"
return;
end
if (etype == ESCROLL) then
//该判断里为单指滑动屏幕时需要进行的操作
local pos = scene:unproject(ex, ey, 1500)
scene.yinhua2.particle.emitter_position = pos.x..","..pos.y..","..pos.z
scene.yinhua2.particle.emit_status = "1"
scene.yinhua3.particle.emitter_position = pos.x..","..pos.y..","..pos.z
scene.yinhua3.particle.emit_status = "1"
return;
end
if (etype == ESCROLL_DOWN) then
//该判断里为单指按下屏幕时需要进行的操作
local pos = scene:unproject(ex, ey, 1500)
scene.yinhua2.particle.emitter_position = pos.x..","..pos.y..","..pos.z
scene.yinhua2.particle.emit_status = "1"
scene.yinhua3.particle.emitter_position = pos.x..","..pos.y..","..pos.z
scene.yinhua3.particle.emit_status = "1"
return;
end
end
说明:
-
on_touch_event接口获取的ex、ey为屏幕像素点的位置坐标,粒子的position为3D世界坐标,如果需要在指定的像素点设置粒子发射器位置,可通过以下接口将2D坐标转换为3D坐标。
local pos = scene:unproject(ex, ey, ez)
如代码示例中,当判断为单指滑动屏幕时,通过scene.yinhua2.particle.emitter_position接口和scene.yinhua3.particle.emitter_position动态改变粒子发射器的位置,使得滑动屏幕时出现由flower.png及huabanpian.png素材渲染出来的粒子。
粒子API
粒子系统在json中详细版配置
一个完整的粒子配置文件(如particle-yinhua3.json)参数及意义详解如下:
{
"name": "kongmingdeng", //配置文件名称
"useGLPoints":0, //是否用点来渲染粒子,0不用 1用,默认为0不用。(提升粒子数量但是部分字段失效,包括frameAnimated,frameLoop,frameCount,frameColums,frameRows,frameRandomOffset,frameDuration,spinAngleMin,spinAngleMax,render中的所有子字段)
"particleCountMax":300, //最大总粒子数 默认为200
"material": {
"blendMode":"additive", //混合模式。支持additive、multiply、alpha,screen.默认additive
"textureName":"kongmingdeng.png", //纹理名称
"frameAnimated":1, //是否采用序列帧动画 默认为0否
"frameLoop":1, //是否循环播放序列帧 默认为0否
"frameCount":64, //总序列帧数 默认为1
"frameColums":8, //序列帧帧列数 默认为1
"frameRows":8, //序列帧行数 默认为1
"frameRandomOffset":0, //初始序列帧随机范围,不能超过总序列帧数 默认为0
"frameDuration":300 //单序列帧停留时间,单位毫秒 默认为0
},
"emission":{
"emissionLoop":-1, ///发射次数:-1无限次周期,0,1一个周期,N表示N个周期 默认为-1
"emissionRate":1000, //每秒发射粒子数 默认为200
"emissionDuration":3000, //发射器每次发射时长,单位毫秒 默认为100
"emissionIdleDuration":0, //发射间隔时长,单位毫秒 默认为0
"emitterPosition":"-20, 100, 100", //发射器位置 默认为0,0,0
"emitterRotationAxisAngleMin":0, //发射器绕轴旋转角度最小值 默认为0;当设置最小值大于最大值时,将其置为和最大值相同
"emitterRotationAxisAngleMax":0, //发射器绕轴旋转角度最大值 默认为0
"emitterRotationAxis":"0, 0, 0", //发射器所绕旋转轴 默认为0,0,0
"emitterRotationAxisVar":"0, 0, 0", //发射器所绕旋转轴变化值 默认为0,0,0
"emissionVelocityMode":"axis", //速度的产生方式。axis:表示沿着xyz三个轴的方向去产生; shape:表示速度会沿着粒子初始位置与发射器位置连线方向产生(如circle发射器形状下,当velocity的三个分量之和大于0时,会向外扩散,三个分量之和小于0时会向内收拢,其速度大小为velocity向量的模加上velocity_var的模范围内随机值);camera:粒子速度与相机的朝向一致(比如子弹效果)(值可通过velocity和velocity_var产生一定随机性) 默认为axis
"emissionAccelecationMode":"axis",//加速度产生方式,与速度同理
"emitterShape":"sphere", //发射器形状。box:长方体 ,sphere:球体 ,hemisphere 半球 ,cone:圆锥, cylinder:圆柱 ,circle :圆环 mesh:模型表面 默认为box
"emitterShapeStrectchScale":"1,1,1", //发射器形状的xyz的拉伸系数(用于制作椭圆等效果) 默认为1,1,1
"emitterShapeParam":{
"box":{
"boxLengthX":100, // box发射器长宽高 默认为50
"boxLengthY":200, // box发射器长宽高 默认为50
"boxLengthZ":300, // box发射器长宽高 默认为50
},
"sphere":{
"sphereRadius":200 //球体发射器半径 默认为100
},
"hemisphere":{
"hemisphereRadius":100 //半球发射器半径 默认为100
},
"cylinder":{
"cylinderRadius":100, //圆柱发射器半径 默认为100
"cylinderHeight":200, //圆柱发射器高 默认为100
},
"cone":{
"coneRadius":200, //圆锥发射器的半径 默认为100
"coneAngle":30 //圆锥发射器的角度 默认为30
},
"circle":{
"circleOutRadius":200, //圆环发射器的外圆半径 默认为130
"circleInRadius":150 //圆环发射器的内圆半径 默认为100
},
"mesh":{
"meshScale":1.0,//缩放比例 默认为1.0
"meshName":""// scene 中pod节点名称
}
}
},
"particle":{
"lifeTimeMin":5000, //粒子最小生存时长,单位毫秒 默认为1000;当设置最小值大于最大值时,将其置为和最大值相同
"lifeTimeMax":10000, //粒子最大生存时长,单位毫秒 默认为1000
"sizeStartMin":1.0, //初始粒子最小缩放倍数 默认为1;当设置最小值大于最大值时,将其置为和最大值相同
"sizeStartMax":1.5, //初始粒子最大缩放倍数 默认为40
"sizeEndMin":0.5, //粒子消失前最小缩放倍数 默认为1;当设置最小值大于最大值时,将其置为和最大值相同
"sizeEndMax":1.5, //粒子消失前最大缩放倍数 默认为1
"colorStart":"255, 255, 255, 255",//初始粒子颜色,RGBA 默认为255,255,255,255
"colorStartVar":"0, 0, 0, 0", //初始粒子颜色范围,RGBA 默认为0,0,0,0
"colorMid":"255, 255, 255, 255", //粒子中期颜色,RGBA 默认为255,255,255,255 若不设置,则与start相同,下同
"colorMidVar":"0, 0, 0, 0", //粒子中期颜色范围,RGBA 默认为0,0,0,0
"colorEnd":"255, 255, 255, 255", //粒子消失前颜色,RGBA 默认为255,255,255,255
"colorEndVar":"0, 0, 0, 0", //粒子消失前颜色范围,RGBA 默认为0,0,0,0
"velocity":"0, 0, 1.0", //初始粒子速度 默认为300,0,0
"velocityVar":"1, 1, 0", //初始粒子速度范围 默认为0,0,0
"acceleration":"0, 0, 0.5", //初始粒子加速度 默认为0,0,0
"accelerationVar":"0, 0, 0.3", //初始粒子加速度范围 默认为0,0,0
"spinAngleMin":0, //每秒粒子最小自转角度,单位角度 默认为0;当设置最小值大于最大值时,将其置为和最大值相同
"spinAngleMax":0, //每秒粒子最大自转角度,单位角度 默认为0
"rotationAxisAngleMin":0, //每秒粒子绕轴公转最小角度,单位角度 默认为0;当设置最小值大于最大值时,将其置为和最大值相同
"rotationAxisAngleMax":0, //每秒粒子绕轴公转最大角度,单位角度 默认为0
"rotationAxis":"0, 0, 0", //粒子围绕的公转轴 默认为0,0,0
"rotationAxisVar":"0, 0, 0", //粒子围绕的公转轴范围 默认为0,0,0
},
"render":{
"imuType":0, //IMU类型,支持0,1 默认为0
"billboardType":"billboard", //粒子渲染朝向,billboard(面向camera),horizontalBillboard(水平放置),verticalBillboard(垂直放置),none(不进行修正) 默认为billboard
"stretchScale":"0,0", //粒子渲染时沿着横向纵向的拉伸系数 默认为0,0(现在只开放2维)
"stretchType":"speed", //拉伸方式,speed:根据速度大小拉伸,速度越拉伸越大;position:根据距离远近拉伸,越远拉伸越大;constant:直接根据stretch_scale的大小进行拉伸 默认为position。
"spinAlignToSpeedDirection":1 //粒子贴图是否沿粒子速度方向:0否即初始方向,1速度方向,-1速度反方向 默认为0
},
"subEmitter": { //二级发射器,可配置多个完整子系统
"birth":[], //粒子生成时产生二级发射器,可配置多个完整的子系统
"deadth":[] //粒子消失时产生二级发射器,可配置多个完整的子系统,
}
}
粒子系统在场景交互脚本里的调用(参数范围范围见jSON说明)
1.如何获取粒子系统对象引用
[scene object].[node name].particle
e.g.: scene.node_name.particle
2.如何修改粒子发射器位置
[scene object].[node name].particle.emitter_position = "x, y, z"
e.g.: scene.node_name.particle.emitter_position = "x, y, z"
3.修改发射器的大小
[scene object].[node name].particle.shape_strectch_scale = "x, y, z"
e.g.: scene.node_name.particle.shape_strectch_scale = "x, y, z"
发射器形状大小按照json中的配置参数按x,y,z进行三个分量的比例拉伸。
4.如何启动/停止播放粒子
[scene object].[node name].particle.emit_status = {0,1}
e.g.: scene.node_name.particle.emit_status = 1
参数为1的时候为发射粒子系统,参数为0的时候为停止发射粒子系统。
5.让粒子系统对象发射一定数量粒子(不能超过最大值)
[scene object].[node name].particle.emit_particle = [0, N]
e.g.: scene.node_name.particle.emit_particle = 10
6.修改粒子模型的值
让粒子整体拉伸
[scene object].[node name].particle.particle_stretch_scale = "x, y"
设置粒子速度
[scene object].[node name].particle.particle_velocity = "x, y, z"
设置粒子速度范围
[scene object].[node name].particle.particle_velocity_var = "x, y, z"
设置粒子加速度
[scene object].[node name].particle.particle_acceleration = "x, y, z"
设置粒子加速度变化范围
[scene object].[node name].particle.particle_acceleration_var = "x, y, z"
设置粒子大小范围
[scene object].[node name].particle.particle_size = "x, y, z, w"
7.修改粒子颜色值
[scene object].[node name].particle.particle_color_start = "x, y, z, w"
[scene object].[node name].particle.particle_color_start_var = "x, y, z, w"
[scene object].[node name].particle.particle_color_end = "x, y, z, w"
[scene object].[node name].particle.particle_color_end_var = "x, y, z, w"
8.修改发射器旋转轴
[scene object].[node name].particle.emitter_rotation_axis = "x, y, z"
[scene object].[node name].particle.emitter_rotation_axis_variance = "x, y, z"
[scene object].[node name].particle.emitter_rotation_angle_min = [-N, N] N∈(0, 2*PI)
[scene object].[node name].particle.emitter_rotation_angle_max = [-N, N]
9.修改发射器发射率
[scene object].[node name].particle.emission_rate = [0, N]
10.修改粒子自转角度(z轴)
[scene object].[node name].particle.spin_angle_min = [0, N]N∈(0, 2*PI)
[scene object].[node name].particle.spin_angle_max = [0, N]N∈(0, 2*PI)
示例代码
樱花:代码下载
喷火龙:代码下载
火焰:代码下载
烟花:代码下载
燃烧的树:代码下载
雷电下雨:代码下载
屏幕写字:代码下载