2015-07-24 5 views
4

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

Я создал систему частиц с JavaFX, используя следующую методику:

Каждая частица является ImageView, который содержит изображение с радиальным градиентом:

enter image description here

Цикл обработки частиц - это AnimationTimer, в котором список частиц обрабатывается через метод stream(). List(), он фактически дает вся система повышает. Что-то вроде этого:

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

Что я узнал:

  • не используя параллельно() является медленнее
  • , используя круг с прозрачностью медленнее, чем при использовании ImageView
  • с использованием режима наложения очень медленно
  • с использованием PixelWriter для изменения цвета изображения небезопасен он медленный. Возникает вопрос: как ColorAdjust меняет цвет (через аппаратное обеспечение d3d &)? Я не нашел механизм в исходном коде JavaFX.

Вопрос

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

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

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


Edit: Так как был задан вопрос, вы можете получить полный код, который использует узлы в виде частиц с coloradjust от this gist. Кстати, даже если вы предварительно визуализируете изображения и не используете coloradjust, производительность низкая.

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

+0

Можете ли вы изложить методы частиц? Возможно, вы видели эту статью об AnimationTimer? http://blog.netopyr.com/2012/06/14/using-the-javafx-animationtimer/ – NwDev

+0

В приведенной здесь «KineticModel» [здесь] (http://stackoverflow.com/a/7425460/230513) также используется пользовательский, полупрозрачный 'RadialGradientPaint', но он предварительно вычисляет требуемые изображения; вы могли бы создать подходящую гамму, используя 'javafx.scene.paint.Color.hsb()'. – trashgod

+0

@NwDX: да, я знаю эту страницу, спасибо. Это более или менее, как я это сделал. Завтра отправлю код, сначала я должен свести его к минимуму. – Roland

ответ

4

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

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

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

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

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

Этот скриншот показывает 3 репеллеров и частиц на экране в Full-HD разрешении, работает на 60fps:

enter image description here

+0

Только мои 2cents: лучший способ проверить ваши перфоманс - просто рисовать 1px на 1px прямоугольники с несколькими цветами, измененными случайным образом через холст и изображение в течение небольшой продолжительности. По какой-то причине вы заметите, что холст превосходит изображение, когда у вас большие очки для окраски или рисования. В другом случае то же самое можно сделать с помощью Java2D, используя awt, рисуя на изображение, но потребляя много памяти. Итак, мой вывод, если вы слишком много хотите рисовать, вы можете использовать холст JavaFX. Поскольку я пробовал 1 миллион очков, чтобы рисовать каждые 1 с, на приличной машине и работает хорошо. – zIronManBox

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

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

+1

Это может привести к неточному моделированию, поскольку это означает, что силы вычисляются в соответствии с нереалистичным промежуточным состоянием. Проще говоря - вы должны сначала вычислить все силы * в соответствии с текущим состоянием * и только затем перейти (перейти) в новое состояние. – Itai

+0

Это зависит от того, действуют ли частицы друг на друга. Если они этого не делают, тогда не о чем беспокоиться. –