Найшвидший спосіб створити простий ефект частинок


12

Я шукаю найшвидший спосіб створити дійсно простий ефект частинок, який буде спам як пекло в грі ...

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

Є щось швидше, ніж просто переміщатися по деяких точках і надавати за допомогою GL_Point?


+1 просто для посилання на Vectrex. Я провів веселі години на Scramble and Tempest як дитина на початку 80-х. Без цього я, мабуть, не став би сьогодні розробником гри.
Кілотан

Так, Tempest є приголомшливим: D
швидкість

Як я можу сказати, що жоден не є правильним?
швидкісник

Відповіді:


13

Дійсно не потрібно зберігати пам'ять для кожної частинки та анімувати кожну частинку окремо. Ви можете це зробити процедурно, реконструюючи положення частинок під час малювання, використовуючи класичне рівняння фізики. s = ut + 1 / 2.at ^ 2

Простий приклад (без постійного прискорення частинок):


void drawExplosion(ExplosionParameters& s)
{
  Random rng;
  rng.seed(s.startSeed);
  glBegin(GL_POINTS);
  for (int i = 0; i < s.numParticles; i++)
  {
    vec3 vel = rng.getRandomVector(-1.0f, 1.0f) * s.explosionSpeed;
    float timeBias = rng.getRandom(0, s.particleTimeBias);
    vec3 pos = s.explosionCentre + (vel * (s.timeElapsed + timeBias));
    glPoint3fv(&pos);
  }
  glEnd();
}

Тоді ви просто збільшуєте s.timeElapsed на кожній ітерації циклу оновлення.

Це також повністю піддається впровадженню в GPU, тим самим звільняючи ваш процесор від необхідності виконувати будь-яку роботу. Реалізація gpu може виглядати приблизно так:

void drawExplosion(ExplosionParameters& s)
{
    //bind Vertex Shader If Not Already Bound();
    ...
    // bindVertexBuffer of Zeroes If Not AlreadyBound();
    glVertexPointer(...)
    //uploadShaderUniformsForExplosion(s);
    glUniform3f(...)
    ...
    glDrawArrays(GL_POINTS, 0, s.numParticles);
} 

Потім вершина шейдера GPU буде реконструювати положення частинок за допомогою рівняння фізики та уніформи / константи, що передаються до неї - так само, як це робила версія CPU.

Щоб додати деяку дисперсію, ви можете використовувати більше одночасних вибухів із дещо різними параметрами, анімацію кольорів / альфа, вибираючи різні вихідні положення. тощо.


Крім того, ви можете використовувати передбачуваність псевдо випадкових чисел для генерації всіх початкових векторів частинок, створюючи сотні частинок з даних, що варті кількох інт. Використання графічного процесора для створення квадратиків - це дійсно гарна ідея для простих частинок.
Skizz

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

7

Я зробив кілька тестів, і найшвидший спосіб (не найшвидший для кодування) - це частинки, зроблені з GL_LINE, які знали своє положення та швидкість, і використовували це як точки при візуалізації (тож, чим швидше йде частинка, найбільше "лінія" він стає, тим повільніше, він стає пунктом).

Ефект ДУЖЕ класний (подивіться будь-яке відео з геометрії війн, щоб побачити його), і СТАРОШЕ швидко теж. Виведіть лайно з квадроциклів (особливо тому, що квадратики змусять мене обчислити подвійну кількість вершин)

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


2
+1 для пояснення того, що ви закінчили, хоча мені буде цікаво дізнатися більше деталей на ваших тестах. =)
орендувач

Btw: Все це було в режимі негайного (це єдине, що я знаю, як кодувати, і я дізнався цю назву вчора ...)
speeder

6

Як правило, я думаю, ви б робили частинки як квадрати з текстурованою картиною. Поводьтеся з ними як до двовимірних спрайтів і з часом вицвіте, знищуючи їх, коли непомітні. Ще краще, використовуйте старі, коли ви робите нові, щоб ви не роздували пам’ять на ці речі.

Якщо ви використовуєте попередньо розмножену альфа в мистецтві, ви можете легко підтримувати світло, вогонь, дим та інше, окрім усіх, одним типом операцій змішування.


Гум ... бали не швидші за текстури?
швидкісник

2
Графічне обладнання спеціально оптимізоване для раструризації текстур до фреймбуфера. Якщо бали швидше, це, швидше за все, незначно, і ви втрачаєте всі можливості, які отримуєте з текстуруванням.
Kylotan

як що? Зверніть увагу, я не створюю повнофункціональну систему частинок, це лише специфічний ефект (невеликі вибухи, в основному для зворотного зв’язку з геймплеєм, що ви щось
ударите

Якщо ви просто хочете використовувати точки або лінії, то це добре. Я можу лише прокоментувати те, що більшість людей робить для частинок. Можливо, незаповнений трикутник зробив би приємну частинку.
Kylotan

4

З OpenGL ES 2.0, ES 1.X з розширенням та OpenGL => 2.1 ви можете використовувати GL_POINT_SPRITES. GL_POINT_SPRITES - це як квадроцикл завжди перед камерою.

У фрагментах шейдерів ви можете:

  • визначте розміри спрайт з gl_PointSize у вершинній шейдері
  • використовувати gl_PointCoord (uv координати) у фрагменті шейдера

Ви можете використовувати текстуру з альфаю для малювання кульових спрайтів ...

Підручник для точкових спрайтів


Я уникаю розширень, нерозумні, які двигун (який я не робив) вже використовуються, є достатньою для кількох людей, які скаржаться, що гра не працює ...
speeder

1

Більшість систем ефектів частинок, які я бачив, замість того, щоб малювати величезну кількість точок, малюють відносно меншу кількість текстур білборда, де кожна текстура виглядає трохи як вибух. Якщо ваш стиль мистецтва справді не заважає, ви, швидше за все, щасливіше підете цим шляхом. Це зведе до мінімуму кількість частинок, необхідних для індивідуального анімування та візуалізації, при цьому все ще даючи великий візуальний ефект.


1
Правда, але він націлений на стиль Vectrex, він би працював там менше.
Кай

1
Точно те, що сказав Кай ... було б безглуздо, І збільшив би розмір завантаження (я перемикаю найбільшу кількість графіки, яку я можу зі спрайту на справжні вектори, щоб я міг зменшити розмір файлів)
speeder

1

Для акуратного маленького способу впоратися з нерестом / видаленням / оновленням частинок, якщо припустити, що у вас є простий масив частинок - Частинки [MAX_PARTICLES]:

Слідкуйте за активними частинками (починаючи з NumActiveParticles = 0)

У кінці масиву завжди додаються нові частинки:

pNewParticle = &Particles[NumActiveParticles++];

Розумний біт - видаляючи «мертву» частинку - поміняйте її своєю останньою активною частинкою та зменшенням NumActiveParticles:

if ( DeadParticle < NumActiveParticles-1 )
{
  Particles[ DeadParticle ] = Particles[ NumActiveParticles-1 ];
}
NumActiveParticles--;

Це дозволяє уникнути будь-якого пошуку «невикористаних частинок» під час нересту і уникає сканування через масив MAX_PARTICLES, якщо жоден не використовується.

Зауважте, що це працює лише в тому випадку, якщо порядок оновлення / візуалізації є неважливим (як це стосується багатьох ефектів частинок, для яких використовується аддитивне змішування) - так як цей метод видалення частинки повторно замовляє масив


-1

Найшвидший спосіб, який я б припустив, - це знайти двигун з частинками і використовувати його для своїх ефектів. Ось декілька:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.