[Unity学习教程] 粒子体系实现与原理

[复制链接]
查看664 | 回复0 | 2023-8-23 11:48:53 | 显示全部楼层 |阅读模式 来自 中国北京
粒子体系简介:

粒子体系是指计算机图形学中模仿特定现象的技能,它在模仿天然现象、物理现象及空间扭曲上具备得天独厚的优势,能为我们实现一些真实天然而又带有随机性的效果(如爆炸、烟花、水流)提供了方便。Cocos2d-x引擎中就为我们提供了强大的粒子体系(确实Billboard Particle 是参考的cocos的源代码)。
cocos粒子体系源代码
粒子体系的分类:

今世的 Particle 有三种
• Billboard Particle
• Mesh Particle
• Ribbon Particle


作者本人先实现的是第一种 Billboard Particle粒子,背面还会实现 Mesh Particle。其实这两种斌没有本质上的区别,都是mesh+实例化+内存粒子+粒子的活动变换(可以各种物理量模仿仿真,以致实现对象群)的管理等等,但是Billboard Particle粒子这种是最原始最简朴的粒子,可以直接一张纹理或者播放序列帧,额Mesh Particle更通用,起首理论上可以是任意模子,而Billboard Particle粒子只是公告板或者普通的说是四边形。再者发射的Mesh的材质可以任意,比Billboard Particle粒子效果更美更机动~
相较而言,UE的粒子更多,尚有别的三种:

粒子的属性:

粒子的属性包罗很多,也包罗各种受力,物理量的粒子。好比最常见的基本, 粒子属性: 坐标,初速率巨细、速率的方向,巨细,颜色,生命周期、质量、粒子的纹理(可以作成序列帧)等等。同时包罗随机量!这个很关键 随机范围为 [start - variance/2, start + variance/2]-[end - variance/2, end + variance/2];
粒子发射器:

获取到全部的粒子,掌管整个粒子体系中该发射器发射的粒子,包罗生命周期、死亡等等!除此之前粒子发射器有三个作用:
– 具体规定粒子产生的规则
– 具体规定粒子模仿的逻辑
– 形貌怎样渲染粒子(特殊是透明混淆等等的标题)

发射器属性:
发射器也有很多的属性,包罗发射器的位置,好比我在项目中经常用的区域发射器,就有区域坐标属性,在该区域内随机new 粒子cell,以致还可以做一个镂空,所以需要镂空坐标。对于线性发射器属性包罗start的坐标,尚有end的坐标
粒子的活动物理量-力场:

除此之外粒子还要受力场的影响
除此之外粒子还要受力场的影响,常见的三种力场:

本人身为物理课代表大学后特殊工作以来物理有一些还给物理老师,所以复习啦一下下面理出各种力,匀变速活动,圆周活动等等的公式
1、 最常见的重力是一种全局设置,实用于场景中的全部物理体系。G = g*m;此中m为质量,g为重力加速率,G为重力。
2、氛围阻力特殊要指出,氛围阻力跟速率的平方程正比,而且!氛围阻力方向与活动方向或者说速率方向相反!

3、引力N/R^2 引力的巨细N与所粒子当前与引力中央点的间隔R,根据欧拉公式获取sqrt((x1-x2)2+((y1-y2)2+(z1-z2)^2)
匀变速活动公式:
速率:v1 = v0+at 此中v0初速率,a为加速率,t通常为当前一帧的时间。
位置公式 S=v0
t + (1/2 *a *t)
均匀速率:V =( v1 +v2)/2
牛二定律:F=am 此中a为加速率,m为粒子的质量
圆周活动公式
   1、v(线速率)=S/t=2πr/T=ωr=2πrf (S代表弧长,t代表时间,r代表半径) 。
2、ω(角速率)=θ/t=2π/T=2πn (θ表现角度或者弧度) 。   3、T(周期)=2πr/v=2π/ω 。
4、n(转速)=1/T=v/2πr=ω/2π 。
5、Fn(向心力)=mrω2=mv2/r=mr4π2/T2=mr4π2f2 。
6、an(向心加速率)=rω2=v2/r=r4π2/T2=r4π2n2 。   
7、vmax(过最高点时的最小速率)=√gr (无杆支持)。。
  粒子体系的通用焦点实现:

这里重要是抛砖引玉,粒子更关注的是位置、与生命周期管理以及内存性能等等标题!至于渲染都是通用的就好比粒子也可以使用PBR,或者各种殊效好比溶解,自觉光、Glitter等等都是通用的这里就不特地在重复。
生命周期管理:

  1. GLuint nr_particles = 500;             //预设置粒子的总数*每个粒子消耗内存数量 = 总数
  2. std::vector<Particle> particles;       //粒子数组 方便管理粒子
  3. for (GLuint i = 0; i < nr_particles; ++i)
  4.     particles.push_back(Particle());
  5. GLuint nr_new_particles = 2;
  6. // Add new particles
  7. for (GLuint i = 0; i < nr_new_particles; ++i)
  8.     {
  9.          int unusedParticle = FirstUnusedParticle();
  10.          RespawnParticle(particles[unusedParticle], object, offset);
  11.     }
  12. // Update all particles for
  13. (GLuint i = 0; i < nr_particles; ++i)
  14.     {
  15.         Particle &p = particles[i]; p.Life -= dt;
  16.         // reduce life
  17.         if (p.Life > 0.0f) {
  18.             // particle is alive, thus update
  19.             p.Position -= p.Velocity * dt;
  20.             p.Color.a -= dt * 2.5;
  21.     }
  22. }
  23. //但是为了提高利用率,找到第一个消亡的粒子然后用一个新产生的粒子来更新它
  24. GLuint lastUsedParticle = 0;
  25.     GLuint FirstUnusedParticle()
  26.         {
  27.             // Search from last used particle, this will usually return almost instantly  for
  28.             (GLuint i = lastUsedParticle; i < nr_particles; ++i)
  29.                 {
  30.                     if (particles[i].Life <= 0.0f)
  31.                         {
  32.                             lastUsedParticle = i;
  33.                              return i;
  34.                     }
  35.     }
  36.             // Otherwise, do a linear search for
  37.      (GLuint i = 0; i < lastUsedParticle; ++i)
  38.             {
  39.                 if (particles[i].Life <= 0.0f)
  40.                     { lastUsedParticle = i; return i;
  41.                 }
  42.             }
  43.      // Override first particle if all others are alive
  44.      lastUsedParticle = 0;
  45.      return 0;
  46.     }
复制代码
粒子的渲染极点着色器:

帧粒子或者 Billboard Particle 的vs:
  1. #version 330 core
  2. layout (location = 0)
  3. in vec4 vertex;     // <vec2 position, vec2 texCoords>
  4. out vec2 TexCoords;
  5. out vec4 ParticleColor;
  6. uniform mat4 projection;
  7. uniform vec2 offset;
  8. uniform vec4 color;
  9.      void main() {
  10.                     float scale = 10.0f;
  11.                     TexCoords = vertex.zw;
  12.                     ParticleColor = color;
  13.                     gl_Position = projection * vec4((vertex.xy * scale) + offset, 0.0, 1.0);
  14.                     }
复制代码
粒子的渲染片元着色器:

最简朴的帧粒子或者 Billboard Particle 的实现ps:
  1. #version 330 core
  2. in vec2 TexCoords;
  3. in vec4 ParticleColor;
  4. out vec4 color;
  5. uniform sampler2D sprite;
  6.     void main() {
  7.                      color = (texture(sprite, TexCoords) * ParticleColor);
  8.      }
复制代码
粒子材质的设置:

  1. particleRender:getStateBlock():setDepthTest( true );    --始终开着
  2. particleRender:getStateBlock():setDepthWrite( );        --可以选择true 或者 false来设置是否深度写入。需要粒子的遮挡关系:粒子最后渲染队列中渲染,开启混合,深度测试始终打开,深度写入关闭,片元 将无法通过深度测试。
  3. particleRender:getStateBlock():setBlend( true );        --公告板的粒子要开启混合,粒子的渲染顺序要当做半透明的方式排序
复制代码
特殊粒子的几种实现:

1、point sprites实现拖尾的粒子

在filament中的案例有point_sprites 效果如图:

//拖尾的焦点
  1.            static Vertex kVertices[NUM_POINTS];
  2.     static float kPointSizes[NUM_POINTS];
  3.     static uint16_t kIndices[NUM_POINTS];
  4.     constexpr float dtheta = M_PI * 2 / NUM_POINTS;
  5.     constexpr float dsize = MAX_POINT_SIZE / NUM_POINTS;
  6.     constexpr float dcolor = 256.0f / NUM_POINTS;
  7.     for (int i = 0; i < NUM_POINTS; i++) {
  8.         const float theta = dtheta * i;
  9.         const uint32_t c = dcolor * i;
  10.         kVertices[i].position.x = cos(theta);
  11.         kVertices[i].position.y = sin(theta);
  12.         kVertices[i].color = 0xff000000u | c | (c << 8u) | (c << 16u);
  13.         kPointSizes[i] = MIN_POINT_SIZE + dsize * i;
  14.         kIndices[i] = i;
  15.     }
复制代码
2、追随粒子


本人最近实现了一种追随的粒子,跟随着某一点活动而活动,活动的轨迹是曲线的。
实现焦点原理:每次update,识别点的pos 减去粒子当前的位置pos1得到的向量修改粒子的速率的方向(发射器或者粒子初始位置任意),速率巨细恒定稳固。
3、基于GPU的粒子

上述的两种都是基于CPU的粒子,由于它们都是在GPU中举行运算的,其实对于大量的极点或者变换还是GPU最擅长,而且能充实发挥GPU的性能!感兴趣的可以具体看一下

github地址:keijiro/Skinner: Special Effects with Skinned Mesh in Unity (github.com)
   Skinner is a collection of special effects that use vertices of an
animating skinned mesh as emitting points. It uses a special
replacement shader to convert vertex positions into GPU-friendly data,
and thus it avoids spending extra memory and CPU time for handling
them (uses GPU resources instead).
  

  • Skinner 是一种殊效,它使用动画技能中的蒙皮网格的极点作为发射点。 它使用特殊的替换着色器将极点位置转换为GPU能识别而且使用的数据,从而制止耗费额外的内存和CPU时间来处理它们(而是使用GPU资源)。
粒子体系的性能优化:

CPU的粒子:

GPU的粒子:



  • 高并行运算,得当大量粒子的模仿计算
  • 可以开释CPU功耗来举行游戏本身计算
  • 方便得到深度缓冲来做遮挡判断
参考资料:

Skinned Mesh原明白析和一个最简朴的实现示例_n5的博客-CSDN博客
联合源码看《我所明白的cocos2dx-3.0》—— 粒子体系_fztfztfzt的博客-CSDN博客
GAMES104_Lecture12_Effects.pdf (boomingtech.com)

来源:https://blog.csdn.net/chenweiyu11962/article/details/127130466
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则