Дизайн Системы Частиц?

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

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

Я думал о классе "система частиц",

этот класс будет содержать следующие ссылки:

particlesList: список частиц, которые составляют система.

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

particleController: управляет, например, вращением вокруг точки, переменной размеры частиц, переменные цвета частиц, области вокруг системы, на которые частицы реагируют по-разному, обнаружение столкновений (с другими объектами или внутри частиц, если это необходимо ).

Рендерер Частиц: на попечении рисовать эту систему, переменные смешивая типы, текстуры частицы, типы частицы как треугольники, круги, таможня...

эти четыре элемента составят класс системы частиц. Некоторые FX могут потребовать более одного система частиц, например Fire FX, может использовать одну систему для огня, одну систему для дыма и одну систему для искр.

Это то, что у меня на уме, но я бы очень хотел знать, хорош ли этот подход к дизайну, или если вы видите, что я что-то упускаю или могу/должен сделать что-то другое. Я не думал о каком-то простом способе "сохранить" FX, например, что было бы лучшим способом сказать моему двигателю, "нарисовать огонь", "нарисовать взрыв", "нарисовать фонтан" и т. д., Возможно, сохраняя FX информация в xml-файлах была бы хорошей идеей и т. д..

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

4 ответов


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

Что касается управления данными, которые должны быть довольно прямыми. Я бы предложил вариант xml и двоичного формата для загрузки. таким образом, вы можете легко настроить материал во время разработки (и не имея инструмент.) После того, как у вас есть инструмент или сделаны настройки я бы преобразовать xml в двоичный для быстрой загрузки.

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

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

Я предполагаю, что это использует API, такой как DirectX или OpenGL для рендеринга. В этом отношении у меня были бы эффекты частиц, которые разделяют один и тот же пул памяти для вашей информации о вершинах. Это очень помогает скорости рендеринга. Я также буду отслеживать границы области повлияно на системой частицы для пользы с отбраковкой фруста (AABB или кругом).

огромная часть обновления системы частиц как атрибуты перейти от одного значения к другому. Чем динамичнее вы можете сделать интерполяцию значений, тем лучше ваши эффекты могут выглядеть. Простая линейная интерполяция может быть достаточно хорошей, но может быть лучше иметь динамический график, который используется для интерполяции значений. Например, вместо того, чтобы идти от 0 до 255 синий в секунду, это может быть круто идти От 0 до 128 за 0,2 секунды, затем 128-255 за 0,8 секунды. Добавление этого значительно увеличит параметры того, как выглядят ваши эффекты.

кроме того, я думаю, что у вас есть довольно хорошее представление о том, что вы хотите сделать. Ваше упоминание о рендеринге различных типов частиц говорит мне, что вы думаете об этом правильно. Я видел, как люди делают двигатели частиц, просто фокусируясь на рендеринге рекламного квадроцикла. Имея возможность испускать 3D-геометрию, все выглядит великолепно. Вы можете также хотите подумать (если вы еще этого не сделали) о возможности вашей системы принимать информацию о модели и динамически разбивать ее на отдельные частицы, которые будут испускаться. На самом деле взрыв модели выглядит намного лучше, чем отображение какой-то частицы взрыва и выцветание объекта или переключение его в поврежденное состояние.


просто некоторые идеи для оптимизации простых, 2D частиц спрайта.

хорошей идеей является отправка всех частиц в массив вершин / VBO и использование шейдера вершин для обновления их позиций с течением времени. Это здорово, если у вас есть простое движение, которое можно легко описать с помощью математической формулы, где x(t) и y(t) (то есть, они зависят только от времени).

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


в моем космическом симуляторе я реализовал самый тривиальный подход: частицы, отправленные как текстурированные квадроциклы, используя glBegin()/glEnd(). Они сбрасываются в текущий "сектор" как отдельные объекты и полностью независимы от времени сброса и далее. Это самая примитивная, глупая и идиотская вещь, и она ответственна за большое снижение производительности, тем более, что я делаю итерацию через объекты через итератор STL vector и отправить каждый из них последовательно.

вам нужно рассмотреть, сколько частиц вы хотите, и что вы хотите, чтобы они сделали. * Вы хотите, чтобы они реагировали на окружение и сталкивались? Затем вам нужно обновить обработанные на CPU и данные, отправленные снова и снова. * Они просто летают самым глупым образом? Тогда вы сможете уйти от отправки всех частиц как VBO и TBO и обновить их в шейдерный.

удачи!


обновлено для связи с комментарием #1 от asker: -)

то, что я бы сделал, это использовать принцип KISS. Это означает: класс под названием ParticleEmitter содержащий массив вершин, массив скоростей и STL vector с примерами простых коллайдеров, таких как плоскость, сфера, треугольник. Кроме того, есть "глобальный"* STL vector С коллайдерами. Затем обновите скорости в соответствии с коллайдерами.

подобное можно сделать с аффекторами (гравитация, ветер и т. д.): другой вектор STL в ParticleEmitter С аффекторами и другим "глобальным" STL vector С affectors.

Affectors и коллайдеры будут классы, которые будут реализовывать affectParticle(particle_t*). где struct particle_t { float x,y,z; float vx,vy,vz; }. Я бы сохранил структуру POD и запустил обновление в ParticleEmitter::update().

однако, если вы используете это на iPhone, может ли это быть чрезмерное усложнение? Возможно, тебе сойдет с рук то, что ты уже сделал. реализовано? Я понятия не имею, как мой дизайн может повлиять на результаты тестов, но для меня это звучит достаточно разумно, если вы держите частицу, коллайдер и аффектор в отсчете, потому что похоже, что он может масштабироваться примерно n*c+n*a.

это всего лишь мои мысли ad-hoc, и как я лично его реализую. Ваш дизайн или дизайн других людей, вероятно, будет лучше : -)

* "Глобальный" в кавычках, потому что, вероятно, имеет смысл сделать использование любого используемого разделения пространства.


я реализовал тот же хороший дизайн для моего собственного движка на C++. Я не использовал ссылки и шаблон политики (стратегии чтения Alexandresku это "современный c++ дизайн") вместо. Статический полиморфизм дает лучшую производительность.


Я хочу сделать несколько комментариев в соответствии с моим опытом.

  1. традиционно большинство частиц использует AOS (массив структуры) для хранения атрибутов частиц. Но это не лучшее решение. Использование представления SOA (Struct of Array) даст вам большую гибкость для добавления атрибутов каждой системы частиц. А также, вам будет намного проще улучшить производительность с SIMD с SOA. Например, выполнение 4 частиц вместе с помощью SSE инструкции.
  2. позицию, в которой частица излучает только инициализация атрибутов частиц. Когда вы испускаете частицы, вам, вероятно, нужно инициализировать другие атрибуты, такие как время жизни, скорость и т. д. Вы можете абстрагировать все эти функции как инициализаторы. Для установки, вы можете иметь инициализатор диск, инициализатор коробка, etc.
  3. некоторая современная система частиц принимает концепцию события. Система частиц может генерировать событие (например, дождь сталкивается с местностью) и другие система частиц может слушать и выполнять некоторые действия (например, испускать всплеск).

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