Performance for particle system

时光毁灭记忆、已成空白 提交于 2019-12-12 11:26:30

问题


Situation

I created a particle system with JavaFX using the following technique:

Each particle is an ImageView which contains an Image with a radial gradient:

The particle handling loop is an AnimationTimer in which the list of particles is handled via the list's stream().parallel() method, it actually gives the whole system a boost. Something like this:

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

    }
};

The particle's color changes via ColorAdjust during its lifecycle. I used fire colors for testing, something like this which contains 1700 particles:

What I've learned:

  • not using parallel() is slower
  • using Circle with transparency is way slower than using an ImageView
  • using a Blend Mode is very slow
  • using a PixelWriter to change the image color is unbearable slow. Question arises: how does ColorAdjust change the color (via d3d & hardware)? I haven't found the mechanism in the JavaFX source code.

Question

Is there a better way to implement a particle system in JavaFX (other Node types, Thread, etc) in regards to performance?

I can post some code if anyone wants to toy around.

Thank you very much for the expertise!


Edit: Since it was asked, you can get the full code which uses nodes as particles with coloradjust from this gist. Btw, even if you pre-render the images and don't use coloradjust, the performance is low.

However, the question is more of a theoretical kind, so digging through the code isn't really necessary.


回答1:


I think I can add an answer to my own question. But I hope someone else with more experience can share their knowledge, because what I came up with was just the result of toying around:

Painting on a Canvas instead of using JavaFX ImageView nodes surprisingly resulted in a factor of at least 10x speed increase. This is basically what I did:

  • pre-calculate the images with the gradients, i. e. the color and the size of them depending on the particle's lifespan
  • in the animation timer get the pre-calculated image and paint it on the canvas

If anyone is interested, you can get the full code from this gist. Just click "Download Zip" and put the code of the zip in an "application" package of a JavaFX project and start the Main class. The difference to the code in the question is in the Particle.java class. In the question the particles are used as nodes and moved in the animation timer, but in this answer only the data is used for drawing an image on a canvas in the animation timer, the node itself isn't put on the scene.

You can use the Settings class in order to specify resolution, number of new particles per frame, etc.

This screenshot shows 3 repellers and 25400 particles on the screen in Full-HD resolution, running at 60fps:




回答2:


I think it might also help to combine these two lines:

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

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

kind of like this:

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

This way you don't get twice the overhead.



来源:https://stackoverflow.com/questions/31613669/performance-for-particle-system

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!