[译]02.打造灵活高效的粒子系统——粒子的容器问题

02_1

粒子系统中很重要的一部分是保存粒子的容器,它必须保存粒子的全部数据,并且也要容易扩展。本文将介绍多种解决方案和它们各自的问题以及如何取舍。

转载请注明[本文连接]和  [原文链接],谢谢!

  • 引言

以下代码有什么问题?

class Particle {

public:

bool m_alive;

Vec4d m_pos;

Vec4d m_col;

float time;

// … other fields

public:

// ctors…

 

void update(float deltaTime);

void render();

};

然后这样使用这个类:

std::vector<Particle> particles;

 

// update function:

for (auto &p : particles)

p.update(dt);

 

// rendering code:

for (auto &p : particles)

p.render();

实际上可以说上面的代码没有问题,对于一些简单的使用场景来说的确挺好。

但是我们来问几个问题:

  1. 这符合单一职责原则(SRP:Single Responsibility Principle)吗?
  2. 如果我们要给粒子添加一个属性怎么办呢?或者一个粒子系统需要位置和颜色的属性,另外一个需要位置、颜色、旋转和大小的属性怎么办?目前这个结构能满足这种需求吗?
  3. 如果我们要添加新得更新方法怎么办?需要把新方法放到子类里实现吗?
  4. 上面的代码效率高吗?

我的回答:

  1. 上面的代码违反了单一职责原则。 Particle类不仅负责保存粒子数据,也负责更新、创建和渲染粒子。我觉得更好的设计是,一个类负责保存数据,一个类负责更新,另外一个类负责渲染。其中保存数据的类可以任意配置需要的字段。
  2. 目前这个Particle类无法实现动态添加属性。问题是这里我们用了AoS(Arry of Sturcts)而不是SoA(Struct of Arrays)。如果使用SoA的话就可以方便的给粒子添加各种属性。
  3. 就像第一点说的,这个类违反了单一职责原则,应该将更新逻辑和渲染分开。现在这个做法对简单的粒子系统来说够用了,但是如果想要模块化、灵活性和可用性高的话,这种方法就不行了。
  4. 这种设计有三点效率问题:
    1. AoS方式会影响效率。
    2. 在update()函数中不仅有计算粒子运动的开销,也有虚函数调用的开销。目前100个粒子根本看不出区别,但是粒子数量增长到10万甚至更多的是时候,这个问题就很明显了。
    3. 同样的问题渲染也会碰到,我们不能单个粒子渲染,而应该通过合批尽量降低DrawCall次数。

以上这些问题应该在设计阶段就考虑到。

  • 添加删除粒子

上面的代码中并没有提及的,粒子系统另一个重要的课题,就是怎么添加删除粒子:

void kill(particleID) { ?? }

void wake(particleID) { ?? }

怎么做高效呢?

第一:粒子池

运行中粒子的数量是随时改变的,我们需要动态的添加删除粒子,当然可以用std::vector,但是每添加一个粒子都有可能引发内存重新分配,这样做效率高吗?

也可以假定初始化的时候就分配一块超大的buffer,可以保存最大数量的粒子,这样就运行时就不会有内存分配了。

02_2

我们解决了前一个问题:频繁重分配内存的问题,但是也引入了新问题“存储碎片”。在同一个buffer里怎么管理一部分粒子活着,它们需要更新,另外部分粒子挂了不需要更新这个问题?

第二:管理

我们可以用两种方式管理buffer:

  • 使用alive标志,在遍历的时候根据这个标志选择性更新。
    • 这个方式引发渲染的一个问题,就是渲染需要连续的一段buffer,如果将整段buffer传给GPU,在shader里不能轻松判断某个粒子是活着的。一个解决办法是创建另一个buffer然后将活着的粒子拷进去,再用这个buffer渲染。
  • 将挂掉的粒子移动到buffer尾部,活着的粒子放在头部并且连续存储。

02_3

如上图所示,当删除一个粒子的时候把它和最后一个激活的粒子交换。

这个方法比之前那个快:

  • 渲染时不需要将激活的粒子拷到其他buffer里。
  • 因为只更新buffer前部激活的粒子,所以粒子在更新的时候不需要判断其是否处于激活状态。
  • 下一步

本文讲述了设计粒子容器时碰到的问题,下一篇我将讲述如何解决这些问题以及我的实现。

另外,如果你觉得这个设计有问题,欢迎留言讨论。

原文地址:http://www.bfilipek.com/2014/04/flexible-particle-system-container.html

No Responses

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

You must enable javascript to see captcha here!