粒子系统的性能

时间:2015-07-24 14:53:32

标签: javafx particles

场合

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

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

enter image description here

粒子处理循环是一个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个粒子:

enter image description here

我学到了什么:

  • 不使用parallel()更慢
  • 使用带透明度的圆形比使用ImageView
  • 使用混合模式非常慢
  • 使用PixelWriter来改变图像颜色是难以忍受的慢。问题出现了:ColorAdjust如何改变颜色(通过d3d和硬件)?我还没有在JavaFX源代码中找到这种机制。

问题

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

如果有人想玩玩具,我可以发布一些代码。

非常感谢您的专业知识!

编辑:自问询以来,您可以获得使用this gist coloradjust的粒子作为粒子的完整代码。顺便说一句,即使您预先渲染图像并且不使用coloradjust,性能也会很低。

然而,问题更多的是理论上的问题,因此挖掘代码并不是必需的。

2 个答案:

答案 0 :(得分:4)

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

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

  • 使用渐变预先计算图像,i。即它们的颜色和大小取决于粒子的寿命
  • 动画计时器中的
  • 获取预先计算的图像并将其绘制在画布上

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

您可以使用“设置”类来指定分辨率,每帧新粒子数等等。

此屏幕截图以全高清分辨率显示屏幕上的3个驱逐者和 25400 粒子,运行速度为60fps:

enter image description here

答案 1 :(得分:0)

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

// 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();
});

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