В прошлом посте мы разобрали новую модель хранения данных об атрибутах частиц (положение, цвет, размер и т.д).
Теперь поговорим о самой важной части новой системы частиц, о том как происходит пересчет атрибутов и их сбор для отрисовки на GPU.
Ранее изменение атрибутов производилось с помощью специальных сущностей "ParticleModificator". Теперь их больше нет. Долой теранию Модификаторов! Всю власть Операторам!
Так стоп! Скажите вы, "Что за Операторы? И в чем разница?" Все очень просто!
Раньше как выглядел пайплайн. Мы передавали структуру частицы в каскад модификаторов. Модификатор, как правило, производил очень простую операцию.
Скажем:
position += velocity * deltaTime
Для этого нам нужно было для каждой частицы вызывать виртуальный метод модификатора поститать и пройти к следующему модификатору. Вы, конечно, можете заметить что можно вызывать один раз для всего пула частиц. На что я паррирую, что были корнер кейсы которые делали такой подход жутко неудобным.
Теперь же сама суть действия:
position += velocity * deltaTime
Может быть разделена на 2 операции:
1. local = velocity * deltaTime
2. position = position + local
Эти 2 операции легко сериализуются как:
1. Тип операции
2. Набор из двух аргументов над которыми будет произведена операция (тут могут быть разные области откуда берутся данные для аргументов)
3. И оффсет куда нужно положить результат.
Вот и все! Почти ассемблерные инструкции! Редактор формирует цепочки таких
Операторов на исполнение и сериализует его в новый вид ресурса
VisualEffect бывший
ParticleEffect.
Далее, мы каждую итерацию пропускаем через цепочку операторов все частицы и наслаждаемся супер гибкостью получившейся системы!
Самое интересное, что этот подход позволяет обновлять состояние не только частиц но и самого эмиттера, а так-же формировать компактные буферы для отправления на GPU
Так-же, очень приятным бонусом будет возможность без проблем сформировать
Compute Shader, что позволит, в будущем, делать симуляцию частиц на GPU (там где это возможно).