Answers:
确实不需要为每个粒子存储内存并分别为每个粒子设置动画。您可以通过使用经典的物理方程式在绘制过程中重建粒子位置来程序上进行此操作。s = ut + 1 / 2.at ^ 2
一个简单的例子(没有恒定的粒子加速):
void drawExplosion(ExplosionParameters& s)
{
Random rng;
rng.seed(s.startSeed);
glBegin(GL_POINTS);
for (int i = 0; i < s.numParticles; i++)
{
vec3 vel = rng.getRandomVector(-1.0f, 1.0f) * s.explosionSpeed;
float timeBias = rng.getRandom(0, s.particleTimeBias);
vec3 pos = s.explosionCentre + (vel * (s.timeElapsed + timeBias));
glPoint3fv(&pos);
}
glEnd();
}
然后,您只需在更新循环的每次迭代中增加s.timeElapsed。
它也完全可以在GPU上实现,从而使CPU免于执行任何工作。一个gpu实现可能看起来像这样:
void drawExplosion(ExplosionParameters& s)
{
//bind Vertex Shader If Not Already Bound();
...
// bindVertexBuffer of Zeroes If Not AlreadyBound();
glVertexPointer(...)
//uploadShaderUniformsForExplosion(s);
glUniform3f(...)
...
glDrawArrays(GL_POINTS, 0, s.numParticles);
}
然后,GPU顶点着色器将通过物理方程式以及传递给它的均匀性/常量来重建粒子位置-就像CPU版本一样。
要增加一些差异,您可以使用更多同时爆炸的参数,这些参数略有不同,为颜色/ alpha设置动画,并选择不同的起始位置。等等
我进行了几次测试,而最快的方式(不是最快的编码方式)是由GL_LINE组成的粒子,它们知道它们的位置和速度,并将其用作渲染时的点(因此,粒子走得越快,最“线”它变得越来越慢,变得很重要。
效果非常酷(观看任何几何图形战争视频都可以看到),而且效果也非常快。将废话踢出四边形(特别是因为四边形会使我需要计算两倍的顶点)
而且,它比使用已经完成的粒子系统更好,因为我想要一个特定的FAST效果,粒子系统通常支持许多功能,并且开销成比例。
通常,我认为您会将粒子作为纹理映射的四边形。基本上将它们视为2D精灵,并随着时间的推移逐渐淡出,在不可见时将其破坏。更好的是,在制作新的时重用旧的,这样就不会浪费内存。
如果您在艺术作品上使用预乘alpha,那么除了通过一种类型的混合操作,您还可以轻松地支持灯光,火焰,烟雾等等。
对于处理粒子的生成/删除/更新的一种巧妙的小方法,假设您有一个简单的粒子数组-Particles [MAX_PARTICLES]:
跟踪活动粒子(从NumActiveParticles = 0开始)
新粒子总是添加在数组的末尾:
pNewParticle = &Particles[NumActiveParticles++];
聪明的地方-移除“死”粒子时-将其与最后一个活动粒子交换,并递减NumActiveParticles:
if ( DeadParticle < NumActiveParticles-1 )
{
Particles[ DeadParticle ] = Particles[ NumActiveParticles-1 ];
}
NumActiveParticles--;
这样可以避免在生成时搜索“未使用的粒子”,并且避免在不使用任何MAX_PARTICLES数组的情况下进行扫描。
请注意,这仅在更新/渲染顺序不重要的情况下才有效(许多粒子效果就是这种情况,它们使用加法混合)-因为这种删除粒子的方法会对数组重新排序