转载地址:https://www.devbean.net/2016/01/qt-study-road-2-qml-particles/#attachment wp-att-3324/0/
Qt 学习之路 2(90):粒子系统
粒子系统是一种计算机图形学的技术,用于模拟一些特定的模糊现象,这些现象用传统的渲染技术难以达到一定的真实感。虽然名为“粒子”,但却可以模拟爆炸、烟、水流、落叶、云、雾、流星尾迹或其它发光轨迹这样的抽象视觉效果。粒子系统的特色是“模糊”,其渲染效果并非完全取决于像素,而是使用特定的边界参数描述随机粒子。幸运的是,使用 QML 可以很方便的实现粒子系统。
粒子系统的核心是ParticleSystem
,用于控制共享时间线。一个场景可以有多个粒子系统,每一个都有自己独立的时间线。粒子由Emitter
元素发射,使用ParticlePainter
进行可视化显示,这个显示可以是图像、QML 项目或者阴影元素等。Emitter
还使用向量空间定义了粒子的方向。粒子一旦发射,就完全脱离了发射器的管理。粒子模块则提供了Affector
,允许控制发射出的粒子。系统中的粒子可以通过ParticleGroup
共享时间变换,默认情况下,粒子都是属于空组(即”)。
按照上面的简介,粒子系统包含以下重要的类:
-
ParticleSystem
– 管理发射器共享的时间线 -
Emitter
– 向系统中发射逻辑粒子 -
ParticlePainter
– 使用粒子画笔绘制粒子 -
Direction
– 已经发射出的粒子使用的向量空间 -
ParticleGroup
– 每一个粒子都隶属于一个组 -
Affector
– 维护已经发射出的粒子
下面我们从一个简单的示例开始。使用 Qt Quick 粒子系统非常简单,我们需要使用:
- 为模拟系统构建所有元素的
ParticleSystem
- 向系统中发射粒子的
Emitter
- 继承自
ParticlePainter
的元素,用于实现粒子可视化的
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
|
import
QtQuick
2.0
import
QtQuick
.
Particles
2.0
Rectangle
{
id
:
root
;
width
:
300
;
height
:
160
color
:
"#1f1f1f"
ParticleSystem
{
id
:
particles
}
Emitter
{
id
:
emitter
anchors
.
centerIn
:
parent
width
:
160
;
height
:
80
system
:
particles
emitRate
:
10
lifeSpan
:
1000
lifeSpanVariation
:
500
size
:
16
endSize
:
32
Rectangle
{
anchors
.
fill
:
parent
color
:
'transparent'
border
.
color
:
'green'
border
.
width
:
2
opacity
:
0.8
}
}
ItemParticle
{
system
:
particles
delegate
:
Rectangle
{
id
:
rect
width
:
10
height
:
10
color
:
"red"
radius
:
10
}
}
}
|
程序运行如下:
首先,我们创建了一个 300×160 的深色矩形作为背景;然后声明一个ParticleSystem
组件。通常这是使用粒子系统的第一步:正是ParticleSystem
组件连接起其它元素。第二步一般是创建Emitter
,定义了一个粒子发射区域以及发射粒子的相关参数。Emitter
使用system
属性将其自己与一个粒子系统关联起来。在这个例子中,发射器所定义的区域每秒发射 10 个粒子(emitRate: 10
),每个粒子的生命周期是 1000 毫秒(lifeSpan : 1000
),发射出的粒子的生命周期变动区间为 500 毫秒(lifeSpanVariation: 500
)。每一个粒子发出时的起始大小为 16px(size: 16
),消失时的大小为 32px(endSize: 32
)。
为了显示出发射器的范围,我们特意添加了一个绿色矩形,用于标记处发射器的边框。注意观察,大部分粒子都会出现在这个绿色矩形内,但是也会有少量粒子超出边界。粒子渲染的位置取决于其生命周期和粒子的方向。我们会在后面详细介绍有关粒子方向的概念。
发射器仅仅发射逻辑上的粒子,每一个逻辑粒子都要通过ParticlePainter
绘制出来,以便可视化显示。在这个例子中,我们使用了ItemParticle
类型。ItemParticle
可以设置一个代理,用于渲染每个粒子。注意,我们同样使用system
属性,将ItemParticle
与ParticleSystem
关联起来。
下面着重说明几个参数:
emitRate
:每秒钟射出的粒子数(默认是每秒 10 个)lifeSpan
:粒子生命周期的毫秒数(默认是 1000 毫秒),注意,这个参数是一个“建议值”,系统并不会严格设置每一个粒子都是这么长的生命周期,可以看作有一个误差范围size
,endSize
:粒子的起始大小和终止大小(默认是 16px)
修改这些参数,可以非常明显的影响到一个粒子系统的运行行为。例如,我们将上面的Emitter
修改为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
Emitter
{
id
:
emitter
anchors
.
centerIn
:
parent
width
:
160
;
height
:
80
system
:
particles
emitRate
:
40
lifeSpan
:
2000
lifeSpanVariation
:
500
Rectangle
{
anchors
.
fill
:
parent
color
:
'transparent'
border
.
color
:
'green'
border
.
width
:
2
opacity
:
0.8
}
}
|
运行结果如下:
注意观察由于增大了emitRate
,同时延长了lifeSpan
和lifeSpanVariation
,系统中同时存在的粒子比之前的版本增加了很多。
除了ItemParticle
,我们还可以使用ImageParticle
。顾名思义,ImageParticle
使用图像渲染粒子。我们可以设置其source
属性指定图像,例如下面的代码片段:
1
2
3
4
|
ImageParticle
{
system
:
particles
source
:
"star.png"
}
|
其中,star.png 图像放在下面,有兴趣的话可以右键另存为保存在本地运行代码。
代码运行结果如下:
如果所有粒子都使用同一个图像,这个粒子系统会显得很假。事实上,即便使用图像,粒子也可以设置其颜色,例如,下面我们将粒子的主体颜色设置为金色,但是允许一个 +/-60% 的误差范围:
1
2
|
color
:
'#FFD700'
colorVariation
:
0.6
|
为了让场景更生动,我们还可以旋转粒子:将每一个粒子顺时针旋转 15 度,另外有一个 +/-5 度的误差范围;然后,这些粒子继续以每秒 45 度的速度旋转。这个速度因粒子而异,会有一个 +/-15 度每秒的误差范围。
1
2
3
4
|
rotation
:
15
rotationVariation
:
5
rotationVelocity
:
45
rotationVelocityVariation
:
15
|
我们还可以修改粒子进入场景的效果。当粒子的生命周期开始时,就会应用这个效果。在这个例子中,我们希望添加一个缩放效果:
1
|
entryEffect
:
ImageParticle
.
Scale
|
最后,我们的代码变成了这个样子:
1
2
3
4
5
6
7
8
9
10
11
|
ImageParticle
{
system
:
particles
source
:
"star.png"
color
:
'#FFD700'
colorVariation
:
0.6
rotation
:
0
rotationVariation
:
45
rotationVelocity
:
15
rotationVelocityVariation
:
15
entryEffect
:
ImageParticle
.
Scale
}
|
现在,我们有了一堆能够旋转的五颜六色的星星:
现在,我们介绍了两种粒子:基于代理的ItemParticle
和基于图像的ImageParticle
。另外还有第三种粒子,基于着色器的CustomParticle
。CustomParticle
使用 OpenGL 着色器语言定义,由于这部分内容需要结合 GLSL 语言,感兴趣的朋友可以自己查阅相关文档,这里不再详述。