Невозможно заставить GPU создавать все (если не использовать Геометрические шейдеры , для которых требуется SM4.0).
Если бы я создавал систему частиц для максимальной эффективности процессора, я бы предварительно создал (просто для примера выбрал число) 100 частиц в буфере вершин и индексов, например:
- Создайте буфер вершин, содержащий четыре квадрата (четыре вершины на частицу, а не шесть, как у вас)
- Используйте пользовательский формат вершин, который может хранить значение «временного смещения», а также значение «начальной скорости» (аналогично XNA Particle 3D Sample )
- Установите значение времени так, чтобы каждая частица имела временное смещение на 1/100 меньше, чем последняя (таким образом, смещения варьируются от 1,0 до 0,01 через буфер).
- Установить начальную скорость случайным образом.
- Используйте индексный буфер, который дает вам два необходимых треугольника, используя четыре вершины для каждой частицы.
И самое интересное, что вам нужно сделать это только один раз - вы можете повторно использовать один и тот же буфер вершин и индексный буфер для всех ваших систем частиц (при условии, что они достаточно велики для вашей самой большой системы частиц).
Тогда у меня будет вершинный шейдер, который будет принимать следующие данные:
- Per-Vertex:
- Смещение по времени
- Начальная скорость
- Параметры шейдера:
- Текущее время
- Время жизни частиц (которое также является значением времени обтекания частиц и долей используемых частиц в буфере)
- Положение системы частиц / вращение / масштаб (мировая матрица)
- Любые другие интересные материалы, которые вам нравятся, такие как: размер частиц, гравитация, ветер и т. Д.
- Шкала времени (чтобы получить реальное время, чтобы расчеты скорости и другие физики имели смысл)
Этот вершинный шейдер (опять же как XNA Particle 3D Sample ) может затем определить положение вершины частицы на основе ее начальной скорости и времени, в течение которого эта частица находилась в симуляции.
Время для каждой частицы будет (псевдокод):
time = (currentTime + timeOffset) % particleLifetime;
Другими словами, с течением времени частицы будут выделяться с постоянной скоростью (из-за смещения). И всякий раз, когда частица умирает в time = particleLifetime
(или это в 1,0 - модуль с плавающей запятой сбивает с толку) , время возвращается к time = 0.0
, так что частица снова входит в анимацию. *
Затем, когда пришло время рисовать мои частицы, я бы установил параметры буфера, шейдера и шейдера и вызвал DrawIndexedPrimitives
. Теперь вот умный бит: я бы установил startIndex
и primitiveCount
так, чтобы никакая частица не начиналась в середине анимации. Когда система частиц сначала запускается, я нарисую 1 частицу (2 примитива), и к тому времени, когда частица вот-вот умрет, я нарисую все 100 частиц, сотая из которых только начинается.
Затем, мгновение спустя, таймер 1-й частицы зациклится и сделает его 101-й частицей.
(Если бы я хотел, чтобы в моей системе было только 50 частиц, я бы просто установил время жизни моих частиц равным 0,5 и только нарисовал бы первые 50 из 100 частиц в буфере вершин / индексов.)
И когда пришло время выключить систему частиц - просто сделайте то же самое в обратном порядке - установите startIndex
и primitiveCount
так, чтобы частицы перестали вытягиваться после того, как они умрут.
Теперь я должен признать, что я упустил из виду математику и некоторые подробности об использовании квадратов для частиц - но это не должно быть слишком сложно выяснить. Основной принцип, который нужно понять, заключается в том, что ваш буфер вершин / индексов рассматривается как кольцевой буфер частиц.
Один недостаток кольцевого буфера заключается в том, что, когда вы прекращаете испускать частицы, если вы не остановите, когда текущее время кратно времени жизни частицы, вы получите активный набор частиц, охватывающих концы буферапромежуток в середине - таким образом, требуются два вызова отрисовки (немного медленнее).Чтобы избежать этого, вы можете подождать, пока не наступит подходящее время, перед остановкой - для большинства систем это должно быть нормально, но для некоторых это может показаться странным (например, «медленная» система частиц, которая должна мгновенно остановиться).
Другим недостатком этого метода является то, что частицы должны высвобождаться с постоянной скоростью - хотя это обычно довольно типично для систем частиц (очевидно, это для каждой системы, и скорость регулируется).С небольшой настройкой должен быть возможен эффект взрыва (все частицы, выпущенные одновременно).
Все это говорит: если возможно, возможно, стоит использовать существующую библиотеку частиц.