粒子系统的性能
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 个粒子的东西:
我学到了什么:
- 不使用 parallel() 速度较慢
- 使用带透明度的 Circle 比使用 ImageView 慢得多
- 使用混合模式非常慢
- 使用 PixelWriter 更改图像颜色速度慢得令人难以忍受。问题出现了:ColorAdjust 如何改变颜色(通过 d3d 和硬件)?我没有在JavaFX源代码中找到该机制。
问题
在性能方面,是否有更好的方法在 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();
});
这样你就不会得到两倍的开销。
情况
我使用以下技术用 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 个粒子的东西:
我学到了什么:
- 不使用 parallel() 速度较慢
- 使用带透明度的 Circle 比使用 ImageView 慢得多
- 使用混合模式非常慢
- 使用 PixelWriter 更改图像颜色速度慢得令人难以忍受。问题出现了:ColorAdjust 如何改变颜色(通过 d3d 和硬件)?我没有在JavaFX源代码中找到该机制。
问题
在性能方面,是否有更好的方法在 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();
});
这样你就不会得到两倍的开销。