Производительность для системы частиц

Ситуация

Я создал систему частиц с помощью 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 & hardware)? Я не нашел механизм в исходном коде JavaFX.

Вопрос

Есть ли лучший способ реализовать систему частиц в JavaFX (другие типы узлов, потоки и т. д.) в отношении производительности?

Я могу опубликовать код, если кто-то хочет поиграть.

Большое спасибо за экспертизу!


Редактировать: так как вас спросили, вы можете получить полный код, который использует узлы в качестве частиц с настройкой цвета, из этот смысл< /а>. Кстати, даже если вы предварительно визуализируете изображения и не используете настройку цвета, производительность будет низкой.

Однако вопрос носит скорее теоретический характер, поэтому копаться в коде на самом деле не нужно.


person Roland    schedule 24.07.2015    source источник
comment
Не могли бы вы опубликовать методы частиц? Может быть, вы видели эту статью о AnimationTimer? blog.netopyr.com/2012/06/14/using -the-javafx-animationtimer   -  person aw-think    schedule 24.07.2015
comment
В приведенном здесь KineticModel также используется пользовательский полупрозрачный RadialGradientPaint, но он предварительно вычисляет необходимые изображения; возможно, вы сможете создать подходящую гамму, используя javafx.scene.paint.Color.hsb().   -  person trashgod    schedule 24.07.2015
comment
@NwDX: да, я знаю эту страницу, спасибо. Примерно так я и поступил. Код выложу завтра, надо сначала уменьшить до минимума.   -  person Roland    schedule 24.07.2015
comment
@trashgod: Спасибо, я только что поигрался с предварительным расчетом изображений частиц и использованием Canvas вместо узлов. Я не ожидал, что это будет так быстро, но в настоящее время у меня более 12000 частиц с очисткой холста и рисованием предварительно рассчитанных изображений снова и снова.   -  person Roland    schedule 24.07.2015


Ответы (2)


Думаю, я могу добавить ответ на свой вопрос. Но я надеюсь, что кто-то еще с большим опытом может поделиться своими знаниями, потому что то, что я придумал, было просто результатом игры:

Рисование на холсте вместо использования узлов JavaFX ImageView неожиданно привело к увеличению скорости как минимум в 10 раз. Это в основном то, что я сделал:

  • предварительно вычислить изображения с градиентами, т.е. е. цвет и размер их в зависимости от продолжительности жизни частицы
  • в таймере анимации получить предварительно рассчитанное изображение и нарисовать его на холсте

Если кому-то интересно, вы можете получить полный код из здесь. Просто нажмите «Загрузить Zip» и поместите код zip в пакет «приложения» проекта JavaFX и запустите класс Main. Разница с кодом в вопросе заключается в классе Particle.java. В вопросе частицы используются как узлы и перемещаются в таймере анимации, но в этом ответе используются только данные для рисования изображения на холсте в таймере анимации, сам узел не помещается на сцену.

Вы можете использовать класс Settings, чтобы указать разрешение, количество новых частиц на кадр и т. д.

На этом снимке экрана показаны 3 репеллера и 25400 частиц на экране в разрешении Full-HD со скоростью 60 кадров в секунду:

введите описание изображения здесь

person Roland    schedule 24.07.2015
comment
Просто мои 2 цента: лучший способ проверить ваши изменения производительности — это просто нарисовать прямоугольники размером 1 пиксель на 1 пиксель с несколькими случайными изменениями цвета на холсте по сравнению с изображением в течение небольшого промежутка времени. Вы обнаружите, что по какой-то причине холст превосходит изображение, когда у вас есть большие точки для раскрашивания или рисования. В другом случае то же самое может быть достигнуто с помощью Java2D с использованием awt путем рисования на изображении, но потребляет много памяти. Итак, мой вывод: если у вас слишком много точек для рисования, используйте холст JavaFX. Поскольку я пробовал рисовать 1 миллион точек каждую 1 секунду, на приличной машине и работает хорошо. - person zIronManBox; 15.03.2016

Я думаю, что это также может помочь объединить эти две строки:

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

Таким образом, вы не получите вдвое больше накладных расходов.

person EzPizza    schedule 13.12.2017
comment
Однако это может привести к неточному моделированию, поскольку это означает, что силы рассчитываются в соответствии с нереалистичным промежуточным состоянием. Проще говоря - нужно сначала рассчитать все силы по текущему состоянию и только потом переходить (перемещаться) в новое состояние. - person Itai; 13.12.2017
comment
Это также зависит от того, воздействуют ли частицы друг на друга силами. Если нет, то не о чем беспокоиться. - person EzPizza; 14.12.2017