粒子系统的性能

Performance for particle system

情况

我使用以下技术用 JavaFX 创建了一个粒子系统:

每个粒子都是一个 ImageView,其中包含一个具有径向渐变的图像:

粒子处理循环是一个 AnimationTimer,其中粒子列表是通过列表的 stream().parallel() 方法处理的,它实际上给了整个系统一个提升。像这样:

loop = new AnimationTimer() {

    @Override
    public void handle(long now) {

        addParticle();

        // apply force: gravity
        allParticles.stream().parallel().forEach(Particle::applyForceGravity);

        // move particle
        allParticles.stream().parallel().forEach(Particle::move);

        // update position in fx scene
        allParticles.forEach(Particle::display);

        // remove all particles that aren't visible anymore
        removeDeadParticles();

    }
};

粒子的颜色在其生命周期内通过 ColorAdjust 改变。我使用了火色来测试,像这样包含 1700 个粒子的东西:

我学到了什么:

问题

在性能方面,是否有更好的方法在 JavaFX(其他节点类型、线程等)中实现粒子系统?

如果有人想玩,我可以post一些代码。

非常感谢您的专业知识!


编辑:自从有人问起,您可以从 this gist 获得使用节点作为带有颜色调整的粒子的完整代码。顺便说一句,即使您预渲染图像并且不使用 coloradjust,性能也会很低。

但是,这个问题更多的是理论性的,所以没有必要深入研究代码。

我想我可以添加我自己的问题的答案。但我希望其他有更多经验的人可以分享他们的知识,因为我想出的只是玩弄的结果:

在 Canvas 上绘画而不是使用 JavaFX ImageView 节点令人惊讶地导致速度至少提高了 10 倍。这基本上就是我所做的:

  • 用梯度预计算图像,i。 e.它们的颜色和大小取决于粒子的寿命
  • 在动画计时器中获取预先计算好的图像并将其绘制在canvas

如果有人感兴趣,可以从 this gist 获取完整代码。只需单击 "Download Zip" 并将 zip 代码放入 JavaFX 项目的 "application" 包中,然后启动 Main class。问题中代码的不同之处在于 Particle.java class。在这个问题中,粒子被用作节点并在动画计时器中移动,但在这个答案中,只有数据用于在动画计时器中的 canvas 上绘制图像,节点本身没有放在场景.

您可以使用设置 class 来指定分辨率、每帧新粒子数等。

此屏幕截图以全高清分辨率在屏幕上显示了 3 个推斥极和 25400 个粒子,运行 60fps:

我认为将这两行结合起来可能也会有所帮助:

// apply force: gravity
allParticles.stream().parallel().forEach(Particle::applyForceGravity);

// move particle
allParticles.stream().parallel().forEach(Particle::move);

有点像这样:

allParticles.stream().parallel().forEach(particle -> {
  particle.applyForceGravity();
  particle.move();
});

这样你就不会得到两倍的开销。