# 如何创建粒子系统

Tx3d Engine当前提供“手动”和“模板”两种粒子系统创建方式。

# 手动创建粒子系统

通过手动编写代码方式创建粒子系统,如下所示(创建雨粒子系统):

import { NormalBlending } from 'three';
import { 
    
    BoxZone,
    ColorBehaviour,
    ForceBehaviour,
    LifeInitializer,
    ParticleEmitter, 
    ParticleSystem,
    PositionInitializer,
    RadiusInitializer,
    SpriteParticleRenderer,
    VelocityInitializer
    
} from '@tx3d/particlesystem';

// 创建实体
const entity = engine.createEntity();

// 添加粒子系统组件
const particleSystem = entity.addComponent( ParticleSystem );

// 创建粒子渲染器
const renderer = new SpriteParticleRenderer( {

    total: 4000,
    map: './assets/textures/particle/rain.png',
    blending: NormalBlending

} );

// 创建粒子发射器
const emitter = new ParticleEmitter( {

    total: 4000,
    damping: 0,
    once: false,
    // 发射频率
    emitRate: {

        minEmitAmounts: 50,
        maxEmitAmounts: 100,
        minEmitInterval: 0.01,
        maxEmitInterval: 0.05

    }

} );

// 添加位置初始化器(使用Box初始区域)
emitter.addInitializer( new PositionInitializer( new BoxZone( {

    size: [ 1000, 10, 100 ]

} ) ) );

// 添加寿命初始化器
emitter.addInitializer( new LifeInitializer( {

    min: 2,
    max: 5

} ) );

// 添加半径初始化器
emitter.addInitializer( new RadiusInitializer( {

    min: 1,
    max: 4

} ) );

// 添加速度初始化器
emitter.addInitializer( new VelocityInitializer( {

    velocity: [ 0, -150, 0 ],
    spreadVelocity: [ 0, 0, 0 ]

} ) );

// 添加颜色行为控制器
emitter.addBehaviour( new ColorBehaviour( {

    energy: [ 0, 1.0 ],
    value: [ '#ffffff', '#eeeeee' ]

} ) );

// 添加作用力行为控制器
emitter.addBehaviour( new ForceBehaviour( {

    energy: [ 0, 1.0 ],
    value: [ [ 20, 0, 20 ], [ 20, 0, 20 ] ]

} ) );

// 添加发射器并预发射2000个粒子
renderer.addEmitter( emitter, 2000 );

// 添加粒子渲染器
particleSystem.addRenderer( renderer );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

# 使用模板创建粒子系统

粒子模板允许用户使用非手写代码方式创建粒子系统,并可以快速完成粒子系统的任何更改。通过ParticleSystemFactory的静态方法load加载预编写的模板创建粒子系统,如下所示(创建雨粒子系统):

import { ParticleSystemFactory } from '@tx3d/particlesystem';

// 创建实体
const entity = engine.createEntity();

// 加载火焰粒子系统模板
ParticleSystemFactory.load( entity, './assets/jsons/particles/rain.json' );
1
2
3
4
5
6
7

提示

模板加载完成后可以根据需求动态调整粒子属性,如下所示(使用相同的火焰粒子模板实现不同颜色火焰效果):

import { ColorRepresentation } from 'three';
import { Entity } from '@tx3d/core';
import { ColorBehaviour, ParticleSystem, ParticleSystemFactory } from '@tx3d/particlesystem';

/**
 * 创建火焰粒子 
 */ 
function createFire( position: Array<number>, colorEnergy: Array<number>, colorValue: Array<ColorRepresentation> ): Entity {

    // 创建实体
    const entity = engine.createEntity( { transform: { position: position } } );

    // 加载火焰粒子模板(注:火焰粒子模板中未定义颜色行为控制器)
    ParticleSystemFactory.load( entity, './assets/jsons/particles/fire.json' ).then( ( particleSystem: ParticleSystem ) => {

        // 获取0号渲染器的0号发射器
        const emitter = particleSystem.getRenderer( 0 ).getEmitter( 0 );

        // 动态添加一个颜色行为控制器
        emitter.addBehaviour( new ColorBehaviour( {

            energy: colorEnergy,
            value: colorValue

        } ) );

    } );

    // 返回实体
    return entity;

}

// 创建火焰1
createFire( [ 0, 0, 0 ], [ 0, 0.75, 1.0 ], [ '#ff0000', '#ff6600', '#ffff33' ] );

// 创建火焰2
createFire( [ 50, 0, 0 ], [ 0, 0.75, 1.0 ], [ '#ff0099', '#ff3399', '#ffff99' ] );

// 创建火焰3
createFire( [ -50, 0, 0 ], [ 0, 0.5, 1.0 ], [ '#6600ff', '#6633ff', '#66ffff' ] );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 粒子系统模板结构

粒子模板需要包含粒子系统、粒子渲染器、粒子发射器、粒子初始化器、粒子行为控制器的相关属性,这些属性有些是必填的有些是可选的。

# 粒子系统属性

名称 类型 描述 说明
renderers array 粒子渲染器属性数组 必填

例如:

{
    "renderers": [{...},{...},...]
}
1
2
3

# 粒子渲染器属性

粒子渲染器属性除了typeemitters是必填的,其它属性由具体的渲染器决定。目前内置了以下两种类型渲染器:

# Point类型渲染器

名称 类型 描述 说明
type string 粒子渲染器类型 必填
total numbler 粒子渲染器可渲染的最大粒子数目 可选,默认2000
renderOrder number 粒子渲染器渲染顺序 可选,默认50
emitters array 粒子发射器属性数组 必填
map string 粒子渲染使用的纹理资源路径 可选,默认null即不使用纹理
blending number 粒子渲染混合方式 可选0(NoBlending)、1(NormalBlending)、2(AdditiveBlending)、3(SubtractiveBlending)、4(MultiplyBlending),默认2

例如:

{
    "type": "Point", // 不区分大小写
    "map": "./assets/textures/particle/snow.png",
    "bending": 1,
    "emitters": [{...},{...},...]
}
1
2
3
4
5
6

# Sprite类型渲染器

名称 类型 描述 说明
type string 粒子渲染器类型 必填
total numbler 粒子渲染器可渲染的最大粒子数目 可选,默认2000
renderOrder number 粒子渲染器渲染顺序 可选,默认50
emitters array 粒子发射器属性数组 必填
map string 粒子渲染使用的纹理资源路径 可选,默认null即不使用纹理
blending number 粒子渲染混合方式 可选0(NoBlending)、1(NormalBlending)、2(AdditiveBlending)、3(SubtractiveBlending)、4(MultiplyBlending),默认2
verticalOrigin number 粒子垂直方向中心点位置 可选-1(TOP)、0(CENTER)、1(BOTTOM),默认0
vertical boolean 标识是否是垂直方向固定公告板 可选,默认true

例如:

{
    "type": "Sprite", // 不区分大小写
    "map": "./assets/textures/particle/rain.png",
    "blending": 1,
    "vertical": true,
    "verticalOrigin": 0,
    "emitters": [{...},{...},...]
}
1
2
3
4
5
6
7
8

此外,如果模板中定义了外部扩展的粒子渲染器,那么需要在加载模板前把该粒子渲染器的构造方法注册到粒子系统工厂中(通过调用ParticleSystemFactoryregisterRenderer静态方法实现)。

例如,下面模板中定义了一个"Instanced"类型粒子渲染器。

{
    "type": "Instanced",
    "url": "./assets/models/coal.glb",
    "emitters": [{...},{...},...]
}
1
2
3
4
5

加载模板前,需要先注册"Instanced"类型粒子渲染对应的构造方法。

import { ParticleRenderer, ParticleSystemFactory } from '@tx3d/particlesystem';

/**
 * Instanced粒子渲染器
 */ 
class InstancedParticleRenderer extends ParticleRenderer {

}

// 注册"InstancedParticleRenderer"粒子渲染构造方法
ParticleSystemFactory.registerRenderer( 'Instanced', InstancedParticleRenderer );

// 创建实体
const entity = engine.createEntity();

// 加载定义了"Instanced"类型渲染器的粒子模板
ParticleSystemFactory.load( entity, './assets/jsons/particles/template.json' );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 粒子发射器属性

名称 类型 描述 说明
life number 发射器寿命(单位:秒) 可选,默认Infinity
delay number 延迟发射时间(单位:秒) 可选,默认0.0
damping number 发射阻尼系数 可选,默认0.006
total number 可以发射的粒子总数 可选,默认2000
preEmitAmounts number 预发射粒子数目 可选,默认0
once boolean 是否只发射一次 可选,默认false
position number[] 发射器Local位置 可选,默认 [ 0.0, 0.0, 0.0 ]
emitRate object 粒子发射频率属性 必填
initializers array 粒子初始化器属性数组 必填
behaviours array 粒子行为控制属性数组 必填

例如:

{
    "total": 4000,
    "damping": 0,
    "once": false,
    "preEmitAmounts": 2000,
    "emitRate": {...},
    "initializers": [{...},{...},...],
    "behaviours": [{...},{...},...]
}
1
2
3
4
5
6
7
8
9

# 粒子发射频率属性

名称 类型 描述 说明
minEmitAmounts number 每次可发射的最小粒子数目 可选,默认1
maxEmitAmounts number 每次可发射的最大粒子数目 可选,默认1
minEmitInterval number 粒子发射最小时间间隔(单位:秒) 可选,默认0.1
maxEmitInterval number 粒子发射最大时间间隔(单位:秒) 可选,默认0.1

例如:

{
    "minEmitAmounts": 50,
    "maxEmitAmounts": 100,
    "minEmitInterval": 0.01,
    "maxEmitInterval": 0.05
}
1
2
3
4
5
6

# 粒子初始化器属性

同上,粒子初始化器属性除了type是必填的,其它属性由具体的初始化器决定。目前内置了以下几种类型初始化器:

# Angle类型初始化器

名称 类型 描述 说明
min number 最小角度(单位:弧度) 可选,默认0.0
max number 最大角度(单位:弧度) 可选,默认0.0
spread boolean 是否扩展 可选,默认false,true在[ max - min, max + min ]区间取随机值,false在[ min, max ]区间取随机值

例如:

{
    "type": "Angle", // 不区分大小写
    "min": 0.0,
    "max": 6.283185307179586 // Math.PI * 2
}
1
2
3
4
5

# Color类型初始化器

名称 类型 描述 说明
color string或number 基础颜色 可选,默认**#ffffff**
spreadColor string或number 扩展颜色 可选,默认**#ffffff**

例如:

{
    "type": "Color", // 不区分大小写
    "color": "#d3f8ee",
    "spreadColor": "#afcc4e"
}
1
2
3
4
5

# Life类型初始化器

名称 类型 描述 说明
min number 最小寿命(单位:秒) 可选,默认Infinity
max number 最大寿命(单位:秒) 可选,默认Infinity
spread boolean 是否扩展 可选,默认false,true在[ max - min, max + min ]区间取随机值,false在[ min, max ]区间取随机值

例如:

{
    "type": "Life", // 不区分大小写
    "min": 1.0,
    "max": 5.0
}
1
2
3
4
5

# Mass类型初始化器

名称 类型 描述 说明
min number 最小质量 可选,默认1
max number 最大质量 可选,默认1
spread boolean 是否扩展 可选,默认false,true在[ max - min, max + min ]区间取随机值,false在[ min, max ]区间取随机值

例如:

{
    "type": "Mass", // 不区分大小写
    "min": 1.0,
    "max": 2.0
}
1
2
3
4
5

# Position类型初始化器

Position类型初始化器包含一个zone(位置初始区域属性)必填属性。zone中除了type是必填的,其它属性由具体的区域类型决定。目前内置了以下几种类型区域:

🌏 Box类型区域

名称 类型 描述 说明
center [ number, number, number ] 中心点坐标 可选, 默认 [ 0, 0, 0 ]
size [ number, number, number ] 尺寸 可选,默认 [ 100, 100, 100 ]

例如:

{
    "type": "Position", // 不区分大小写
    "zone": {
        "type": "Box",  // 不区分大小写
        "size": [ 1000, 20, 1000 ]
    }
}
1
2
3
4
5
6
7

🌏 Circle类型区域

名称 类型 描述 说明
center [ number, number, number ] 中心点坐标 可选,默认 [ 0, 0, 0 ]
radius number 半径 可选,默认1.0
emitFromShell boolean 是否从外壳发射 可选,默认false

例如:

{
    "type": "Position",     // 不区分大小写
    "zone": {
        "type": "Circle",   // 不区分大小写
        "radius": 2.0
    }
}
1
2
3
4
5
6
7

🌏 Hemisphere类型区域

名称 类型 描述 说明
center [ number, number, number ] 中心点坐标 可选,默认 [ 0, 0, 0 ]
radius number 半径 可选,默认1.0
emitFromShell boolean 是否从外壳发射 可选,默认false

例如:

{
    "type": "Position",         // 不区分大小写
    "zone": {
        "type": "Hemisphere",   // 不区分大小写
        "radius": 2.0
    }
}
1
2
3
4
5
6
7

🌏 Line类型区域

名称 类型 描述 说明
start [ number, number, number ] 起点坐标 可选,默认 [ 0, 0, 0 ]
end [ number, number, number ] 终点坐标 可选,默认 [ 0, 0, 0 ]

例如:

{
    "type": "Position",         // 不区分大小写
    "zone": {
        "type": "Line",         // 不区分大小写
        "start": [ 0, 0, 100 ],
        "end": [ 100, 0, -20 ]
    }
}
1
2
3
4
5
6
7
8

🌏 Ring类型区域

名称 类型 描述 说明
center [ number, number, number ] 中心点坐标 可选,默认 [ 0, 0, 0 ]
innerRadius number 内圈半径 可选,默认0.5
outerRadius number 外圈半径 可选,默认0.5

例如:

{
    "type": "Position",         // 不区分大小写
    "zone": {
        "type": "Ring",         // 不区分大小写
        "innerRadius": 1.0,
        "outerRadius": 1.5
    }
}
1
2
3
4
5
6
7
8

🌏 Route类型区域

名称 类型 描述 说明
points [ [ number, number, number ] ] 路径关键点坐标数组 必填且数组长度必须大于1

例如:

{
    "type": "Position",     // 不区分大小写
    "zone": {
        "type": "Route",    // 不区分大小写
        "points": [ 
            [ 0, 0, 0 ],
            [ 10, 0, 20 ],
            [ 20, 0, -15 ]
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11

🌏 Sphere类型区域

名称 类型 描述 说明
center [ number, number, number ] 中心点坐标 可选,默认 [ 0, 0, 0 ]
radius number 半径 可选,默认1.0
emitFromShell boolean 是否从外壳发射 可选,默认false

例如:

{
    "type": "Position",     // 不区分大小写
    "zone": {
        "type": "Sphere",   // 不区分大小写
        "radius": 2.0
    }
}
1
2
3
4
5
6
7

此外,如果模板中定义了外部扩展的位置初始区域,那么需要在加载模板前把该位置初始区域的构造方法注册到粒子系统工厂中(通过调用ParticleSystemFactoryregisterZone静态方法实现)。

例如,下面模板中定义了一个"Sector"类型位置初始区域。

{
    "emitters": [{
        ......,
        "initializers": [{
            "type": "Position",
            "zone": { 
                "type": "Sector",
                "radius": 2.0
            }
        }]
        ......
    }]
}
1
2
3
4
5
6
7
8
9
10
11
12
13

加载模板前,需要先注册"Sector"类型位置初始区域的构造方法。

import { ParticleSystemFactory, Zone } from '@tx3d/particlesystem';

/**
 * 扇形位置初始区域
 */ 
class SectorZone extends Zone {

}

// 注册"SectorZone"位置初始区域构造方法
ParticleSystemFactory.registerZone( 'Sector', SectorZone );

// 创建实体
const entity = engine.createEntity();

// 加载定义了"Sector"类型位置初始区域的粒子模板
ParticleSystemFactory.load( entity, './assets/jsons/particles/template.json' );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Radius类型初始化器

名称 类型 描述 说明
min number 最小半径 可选,默认10
max number 最大半径 可选,默认10
spread boolean 是否扩展 可选,默认false,true在[ max - min, max + min ]区间取随机值,false在[ min, max ]区间取随机值

例如:

{
    "type": "Radius", // 不区分大小写
    "min": 1.0,
    "max": 10.0
}
1
2
3
4
5

# Rotation类型初始化器

名称 类型 描述 说明
min number 最小角度(单位:弧度) 可选,默认0.0
max number 最大角度(单位:弧度) 可选,默认0.0
spread boolean 是否扩展 可选,默认false,true在[ max - min, max + min ]区间取随机值,false在[ min, max ]区间取随机值

例如:

{
    "type": "Rotation", // 不区分大小写
    "min": 0.0,
    "max": 6.283185307179586 // Math.PI * 2
}
1
2
3
4
5

# Size类型初始化器

名称 类型 描述 说明
size [ number, number ]或[ number, number, number ] 基础尺寸 可选
spreadSize [ number, number ]或[ number, number, number ] 扩展尺寸 可选

例如:

{
    "type": "Size", // 不区分大小写
    "size": [ 10, 10 ],
    "spreadSize": [ 5, 5 ]
}
1
2
3
4
5

# Velocity类型初始化器

名称 类型 描述 说明
velocity [ number, number, number ] 基础速度 可选
spreadVelocity [ number, number, number ] 扩展速度 可选

例如:

{
    "type": "Velocity", // 不区分大小写
    "velocity": [ 0, -150, 0 ],
    "spreadVelocity": [ 0, 0, 0 ]
}
1
2
3
4
5

此外,如果模板中定义了外部扩展的粒子属性初始化器,那么需要在加载模板前把该粒子属性初始化器的构造方法注册到粒子系统工厂中(通过调用ParticleSystemFactoryregisterInitializer静态方法实现)。

例如,下面模板中定义了一个"Alpha"类型粒子属性初始化器。

{
    "emitters": [{
        ......,
        "initializers": [{
            "type": "Alpha",
            "min": 0.0,
            "max": 1.0
        }]
        ......
    }]
}
1
2
3
4
5
6
7
8
9
10
11

加载模板前,需要先注册"Alpha"类型粒子属性初始化器的构造方法。

import { Initializer, ParticleSystemFactory } from '@tx3d/particlesystem';

/**
 * 透明度属性初始化器
 */ 
class AlphaInitializer extends Initializer {

}

// 注册"AlphaInitializer"粒子属性初始化器构造方法
ParticleSystemFactory.registerZone( 'Alpha', AlphaInitializer );

// 创建实体
const entity = engine.createEntity();

// 加载定义了"Alpha"类型粒子属性初始化器的粒子模板
ParticleSystemFactory.load( entity, './assets/jsons/particles/template.json' );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 粒子行为控制器属性

同上,粒子行为控制器属性除了type是必填的,其它属性由具体的行为控制器决定。目前内置了以下几种类型行为控制器:

# Alpha类型行为控制器

名称 类型 描述 说明
energy number[] 能量数组 必填
value number[] 透明度数组 必填

例如:

{
    "type": "Alpha", // 不区分大小写
    "energy": [ 0.0, 0.25, 1.0 ],
    "value": [ 0.15, 0.25, 1.0 ]
}
1
2
3
4
5

# Color类型行为控制器

名称 类型 描述 说明
energy number[] 能量数组 必填
value number[] 或 string[] 颜色数组 必填

例如:

{
    "type": "Color", // 不区分大小写
    "energy": [ 0, 1.0 ],
    "value": [ "#ffffff", "#eeeeee" ]
}
1
2
3
4
5

# Force类型行为控制器

名称 类型 描述 说明
energy number[] 能量数组 必填
value number[ [ number, number, number ] ] 作用力数组 必填

例如:

{
    "type": "Force", // 不区分大小写
    "energy": [ 0, 1.0 ],
    "value": [ [ 20, 0, 20 ], [ 20, 0, 20 ] ]
}
1
2
3
4
5

# Gravity类型行为控制器

名称 类型 描述 说明
energy number[] 能量数组 必填
value number[] 重力加速度数组 必填

例如:

{
    "type": "Gravity",
    "energy": [ 0, 1.0 ],
    "value": [ 9.8, 9.8 ]
}
1
2
3
4
5

# Scale类型行为控制器

名称 类型 描述 说明
energy number[] 能量数组 必填
value number[] 缩放量数组 必填

例如:

{
    "type": "Scale",
    "energy": [ 0.0, 0.75, 1.0 ],
    "value": [ 1.0, 0.5, 1.5 ]
}
1
2
3
4
5

此外,如果模板中定义了外部扩展的粒子行为控制器,那么需要在加载模板前把该粒子行为控制器的构造方法注册到粒子系统工厂中(通过调用ParticleSystemFactoryregisterBehaviour静态方法实现)。

例如,下面模板中定义了一个"PositionClamp"类型粒子行为控制器器。

{
    "emitters": [{
        ......,
        "behaviours": [{
            "type": "PositionClamp",
            "minHeight": 0.0
        }]
        ......
    }]
}
1
2
3
4
5
6
7
8
9
10

加载模板前,需要先注册"PositionClamp"类型粒子行为控制器的构造方法。

import { Behaviour, ParticleSystemFactory } from '@tx3d/particlesystem';

/**
 * 粒子下落位置行为控制器器
 */ 
class PositionClampBehaviour extends Behaviour {

}

// 注册"PositionClampBehaviour"粒子行为控制器构造方法
ParticleSystemFactory.registerZone( 'PositionClamp', PositionClampBehaviour );

// 创建实体
const entity = engine.createEntity();

// 加载定义了"PositionClamp"类型粒子行为控制器的粒子模板
ParticleSystemFactory.load( entity, './assets/jsons/particles/template.json' );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

提示

下面是一个完整的粒子系统模板,用于实现“雨”粒子效果:

{
    "renderers": [{
        "type": "Sprite",
        "total": 4000,
        "map": "./assets/textures/particle/rain.png",
        "blending": 1,
        "emitters": [{
            "total": 4000,
            "damping": 0,
            "once": false,
            "emitRate": {
                "minEmitAmounts": 50,
                "maxEmitAmounts": 100,
                "minEmitInterval": 0.01,
                "maxEmitInterval": 0.05
            },
            "initializers": [{
                "type": "Position",
                "zone": {
                    "type": "Box",
                    "size": [ 1000, 10, 1000 ]
                }
            },{
                "type": "Life",
                "min": 2,
                "max": 5
            },{
                "type": "Radius",
                "min": 1,
                "max": 4
            },{
                "type": "Velocity",
                "velocity": [ 0, -150, 0 ],
                "spreadVelocity": [ 0, 0, 0 ]
            }],
            "behaviours": [{
                "type": "Color",
                "energy": [ 0, 1.0 ],
                "value": [ "#ffffff", "#eeeeee" ]
            },{
                "type": "Force",
                "energy": [ 0, 1.0 ],
                "value": [ [ 20, 0, 20 ], [ 20, 0, 20 ] ]
            }],
            "preEmitAmounts": 2000
        }]
    }]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 如何生成粒子系统模板

1️⃣ 手动编写粒子系统模板。

2️⃣ 调用已完成设置的粒子系统组件的toJSON方法生成粒子系统模板,如下所示:

import * as fs from 'fs';

// 粒子系统属性转JSON
const data = particleSystem.toJSON();

// 生成模板文件
fs.writeFile( './assets/jsons/particles/template.json', JSON.stringify( data ) );
1
2
3
4
5
6
7
Last Updated: 9/18/2023, 3:24:59 PM