一、粒子是什么?
以我个人的理解,粒子就是一个最小单元,粒子系统就是若干个粒子单元。先构造出最小单元,然后复制多个,添加一些不同变换,就可以实现粒子系统的多样性,构造出不同的最小单元,就是粒子的多样性了。
二、粒子的工作原理
从单个粒子出发,从产生到结束,是有生命周期的,可以通过时间加以限制。当然也有长期存在的粒子,没有生命周期的。粒子从产生,绕一个指定的轨迹运动,通过限制一个频率,每隔一段时间产生一批粒子,就这样一直运转下去。
三、粒子多样性
1.最简单的圆球,矩形等等
这种用于实现一些烟花效果,通过简单辉光的办法,做出闪闪发光的效果。
2.绘制的一些图形
一般可以是花瓣,或者树叶等可简单绘制的具有规则的图形,当然,如果多费些功夫,可以绘制复杂的图形,比如花朵,雪花等。
3.通过纹理导入的图片
这种其实是在第二种的基础上发展的,但是这种可能需要费一些功夫,因为粒子都是按中心来定位置,如果是不规则的纹理图案,中心就不太好确定了。
四、粒子系统的多样性
单个粒子,复制若干个就成了粒子系统,可是单纯的复制并不能体现多样性。为了体现多样性,需要尽可能的让每一个粒子都不一样。
1.颜色多样性
随机每个粒子的颜色,让其不一样。这种办法可能是最粗糙的,勉强算一个办法,但并不实用。
2.运动轨迹多样性
随机每个粒子的运动轨迹和位置,制造出散乱的效果。这种办法尚可,有一些散乱的感觉,还算常见。
3.粒子图形多样性
让每一个粒子都长得不一样。可通过构造随机矩阵来改变每一个粒子的形态,效果比较好,附加位置随机,常见的有花瓣飘散,雪花飘散效果。
五、代码示例
float rand(float n) {
return fract(sin(n) * 43758.5453123);
}
void main()
{
vec2 textSize = 1.0/textureSize(uTexture1,0);
vec4 nColor = texture(uTexture1, vTexPosition1);
vec2 pos = vTexPosition1 - 0.5;
pos /= textSize;
nColor.rgb = vec3(0.0);
int Scount = 40; //指定时间发射粒子的个数
float speed = 60; //粒子运动的速度
float dtime = 1.0; //粒子发射间隔时间
float delay = 3.5; //粒子生命周期
float particleSize = 5; //粒子半径大小
vec3 Viewcolor = vec3(0.0,1.0,1.0);
float N = floor(vtime/dtime); //根据时间计算发射粒子批数
for(int i = 0;i <N+1;i++)
{
float seed = rand(i+1.0); //不同批数的粒子随机数不一样
for(int j = 0;j<Scount;j++)
{
if(dtime*(vtime/dtime - i) > delay) //计算当前批次粒子生命周期是否结束
break;
float rad = speed*(rand(seed*j * 1.8372 + 3.3459)*0.8 + 0.2); //对速度随机
float a = 2.0*PI*rand(seed*j*2.1312 + 2.8923); //对发射角度随机
vec2 pdir = vec2(rad * cos(a), rad * sin(a)); //发射方向
vec2 sparkPos = max(vtime/dtime - i,0.0)*pdir; //偏移距离
float psize = length(sparkPos - pos); //计算当前位置与发射点的距离(加与减只是方向的区别,由于是圆,都可,不做分辨)
if(psize< particleSize) //在粒子大小范围内的取色
{
vec3 colorR = vec3(rand(seed*j*2.13454),rand(seed*j*1.78345),rand(seed*j*3.26187)); //对粒子颜色随机
nColor.rgb = smoothstep(0.95,1.05,particleSize/psize) * colorR; //颜色混合
nColor.rgb = nColor.rgb*smoothstep(delay,0.0,dtime*(vtime/dtime - i)); //根据生命周期变淡
}
}
}
FragColor = nColor;
}