在粒子系统中,更新器是负责更新粒子参数的关键组件。它们确保粒子能够动态地响应各种物理和视觉效果。本文将深入探讨更新器的概念、实现方式以及如何通过优化来提高性能。
更新器遵循单一职责原则(SRP),仅用于更新粒子的参数,并最终决定粒子是否存活。可以进一步创建“杀手”更新器来销毁粒子,但这可能会过于复杂。更新器的核心功能是:
更新器的类定义如下:
class ParticleUpdater {
public:
ParticleUpdater() { }
virtual ~ParticleUpdater() { }
virtual void update(double dt, ParticleData *p) = 0;
};
以欧拉更新器(EulerUpdater)为例,它根据全局加速度更新粒子的位置、速度和加速度。以下是其实现代码:
class EulerUpdater : public ParticleUpdater {
public:
glm::vec4 m_globalAcceleration{0.0f};
public:
virtual void update(double dt, ParticleData *p) override;
};
void EulerUpdater::update(double dt, ParticleData *p) {
const glm::vec4 globalA{ dt * m_globalAcceleration.x,
dt * m_globalAcceleration.y,
dt * m_globalAcceleration.z, 0.0 };
const float localDT = (float)dt;
const unsigned int endId = p->m_countAlive;
for (size_t i = 0; i < endId; ++i)
p->m_acc[i] += globalA;
for (size_t i = 0; i < endId; ++i)
p->m_vel[i] += localDT * p->m_acc[i];
for (size_t i = 0; i < endId; ++i)
p->m_pos[i] += localDT * p->m_vel[i];
}
通过组合不同的更新器,可以创建出复杂的粒子效果。例如,为了实现“地面效果”,可以使用以下代码:
auto timeUpdater = std::make_shared();
m_system->addUpdater(timeUpdater);
auto colorUpdater = std::make_shared();
m_system->addUpdater(colorUpdater);
m_eulerUpdater = std::make_shared();
m_eulerUpdater->m_globalAcceleration = glm::vec4{0.0, -15.0, 0.0, 0.0};
m_system->addUpdater(m_eulerUpdater);
m_floorUpdater = std::make_shared();
m_system->addUpdater(m_floorUpdater);
使用结构化对象阵列(SOA)容器可以提高缓存的使用效率。例如,ColorUpdater只使用三个数组:currentColor、startColor和endColor。这样,处理器缓存将只填充这三个数组,从而提高性能。