Cara tercepat untuk membuat efek partikel sederhana

12

Saya mencari cara tercepat untuk membuat efek partikel yang sangat sederhana yang akan di-spammed di game ...

Pada dasarnya, gim saya terlihat seperti gim vectrex, sebagian besar terdiri dari baris ... Saya ingin membuat beberapa ledakan kecil yang akan sangat umum.

Ada sesuatu yang lebih cepat daripada hanya bergerak di beberapa titik dan merender dengan GL_Point?

lebih cepat
sumber
+1 hanya untuk referensi Vectrex. Saya menghabiskan beberapa jam yang menyenangkan di Scramble and Tempest sebagai seorang anak di awal 80-an. Tanpa itu saya mungkin tidak akan berakhir sebagai pengembang game hari ini.
Kylotan
Yap, Tempest is awesome: D
speeder
Bagaimana saya mengatakan bahwa tidak ada yang benar?
speeder

Jawaban:

13

Benar-benar tidak perlu menyimpan memori untuk setiap partikel dan menghidupkan setiap partikel secara terpisah. Anda dapat melakukannya secara prosedural dengan merekonstruksi posisi partikel selama menggambar dengan menggunakan persamaan fisika klasik. s = ut + 1 / 2.at ^ 2

Contoh sederhana (tanpa percepatan partikel konstan):


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

Maka Anda cukup meningkatkan s.timeElapsed pada setiap iterasi dari loop pembaruan Anda.

Hal ini juga sepenuhnya dapat diterapkan pada GPU sehingga membebaskan CPU Anda dari keharusan melakukan pekerjaan apa pun. Implementasi GPU mungkin terlihat seperti ini:

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

Vertikal shader GPU kemudian akan merekonstruksi posisi partikel melalui persamaan fisika dan seragam / konstanta diteruskan ke sana - sama seperti versi CPU.

Untuk menambahkan beberapa variasi, Anda dapat menggunakan ledakan lebih simultan dengan parameter yang sedikit berbeda, menganimasikan warna / alfa, memilih posisi awal yang berbeda. dll.

jpaver
sumber
Juga, Anda dapat menggunakan prediktabilitas angka acak semu untuk menghasilkan vektor awal semua partikel, menciptakan ratusan partikel dari beberapa data int. Menggunakan GPU untuk membuat paha depan adalah ide yang sangat bagus untuk partikel sederhana.
Mendesing
Selama bertahun-tahun saya telah membuat sistem partikel dengan cara tradisional dengan array kelas yang memperlakukan partikel sebagai entitas semi-cerdas dan selalu tampak agak boros dan kembung. Cara ini jauh lebih baik untuk partikel dasar yang melakukan tidak lebih dari memuntahkan layar.
Piku
7

Saya membuat beberapa tes, dan cara TERCEPAT (bukan yang tercepat untuk kode) adalah partikel yang terbuat dari GL_LINEs yang tahu posisi dan kecepatan mereka, dan menggunakannya sebagai titik saat merender (jadi, semakin cepat partikelnya berjalan, paling "garis") itu menjadi, semakin lambat, itu menjadi sebuah poin).

Efeknya BENAR-BENAR keren (lihat video perang geometri untuk melihatnya), dan BENAR-BENAR cepat juga. Hentikan omong kosong dari paha depan (khususnya karena paha depan akan membuat saya perlu menghitung jumlah ganda dari vertex)

Juga, ini lebih baik daripada menggunakan sistem partikel yang sudah dilakukan, karena saya ingin efek spesifik dan CEPAT, sistem partikel biasanya mendukung banyak fitur, dengan jumlah overhead yang proporsional.

lebih cepat
sumber
2
+1 untuk menjelaskan apa yang akhirnya Anda lakukan, meskipun saya ingin tahu untuk mendengar lebih detail tentang tes Anda. =)
leander
Btw: Semua itu dalam mode langsung (itu adalah satu-satunya hal yang saya tahu bagaimana kode, dan saya belajar namanya kemarin ...)
speeder
6

Biasanya saya pikir Anda akan melakukan partikel sebagai paha tekstur-dipetakan. Perlakukan mereka sebagai sprite 2D pada dasarnya, dan pudar seiring waktu, menghancurkannya ketika tidak terlihat. Lebih baik lagi, gunakan kembali yang lama ketika Anda membuat yang baru sehingga Anda tidak meronta-ronta memori untuk hal-hal ini.

Jika Anda menggunakan alfa yang telah ditiru sebelumnya pada bidangnya maka Anda dapat dengan mudah mendukung lampu, api, asap, dan banyak lagi selain semua itu dengan satu jenis operasi pencampuran.

Kylotan
sumber
Poin ... bukan lebih cepat dari tekstur?
speeder
2
Perangkat keras grafis secara khusus dioptimalkan untuk rasterisasi tekstur ke framebuffer. Jika poin lebih cepat, itu mungkin dengan jumlah yang dapat diabaikan, dan Anda kehilangan semua kemungkinan yang Anda dapatkan dengan tekstur.
Kylotan
seperti apa? Pikiran Anda saya tidak membuat sistem partikel berfitur lengkap, itu hanya efek tertentu (ledakan kecil, sebagian besar untuk umpan balik gameplay yang Anda memukul sesuatu)
speeder
Jika Anda hanya ingin menggunakan titik atau garis, maka itu tidak masalah. Saya hanya bisa mengomentari apa yang dilakukan kebanyakan orang untuk partikel. Mungkin segitiga yang tidak terisi akan membuat partikel yang bagus.
Kylotan
4

Dengan OpenGL ES 2.0, ES 1.X dengan ekstensi dan OpenGL => 2.1, Anda dapat menggunakan GL_POINT_SPRITES. GL_POINT_SPRITES seperti quad selalu di depan kamera.

Di fragmen shader, Anda dapat:

  • tentukan ukuran sprite dengan gl_PointSize di vertex shader
  • gunakan gl_PointCoord (koordinat uv) di shader fragmen

Anda dapat menggunakan tekstur dengan alpha untuk menggambar sprite bola ...

Tutorial untuk Point Sprite

Ellis
sumber
Saya menghindari ekstensi, yang konyol bahwa mesin (yang saya tidak membuat) sudah menggunakan, yang alraedy cukup untuk beberapa orang mengeluh bahwa permainan tidak berjalan ...
speeder
1

Sebagian besar sistem efek partikel yang saya lihat, alih-alih menggambar sejumlah besar titik, menggambar sejumlah kecil tekstur papan iklan di mana masing-masing teksturnya terlihat agak seperti ledakan. Kecuali jika gaya seni Anda benar-benar menghalangi, Anda mungkin akan lebih senang melewati rute itu. Ini akan meminimalkan jumlah partikel yang Anda butuhkan untuk menghidupkan dan membuat secara individual sambil tetap memberikan efek visual yang besar.

banyak sekali
sumber
1
Benar, tapi dia mengincar gaya Vectrex, itu akan bekerja kurang baik di sana.
Kaj
1
Persis apa yang Kaj katakan ... itu akan sia-sia, DAN akan meningkatkan ukuran unduhan (Saya mengganti grafik paling banyak dari sprite ke vektor benar, jadi saya bisa mengurangi ukuran file)
speeder
1

Untuk cara kecil yang rapi untuk menangani pemijahan / penghapusan / pembaruan partikel, dengan asumsi Anda memiliki susunan partikel sederhana - Partikel [MAX_PARTICLES]:

Melacak partikel aktif (dimulai dengan NumActiveParticles = 0)

Partikel baru selalu ditambahkan di akhir array:

pNewParticle = &Particles[NumActiveParticles++];

Bit pintar - Ketika menghapus partikel 'mati' - bertukar dengan partikel aktif terakhir, dan decrement NumActiveParticles:

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

Ini menghindari setiap pencarian 'partikel yang tidak digunakan' saat pemijahan, dan menghindari pemindaian melalui array MAX_PARTICLES jika tidak ada yang digunakan.

Perhatikan bahwa ini hanya berfungsi jika urutan pembaruan / render tidak penting (seperti halnya untuk banyak efek partikel, yang menggunakan campuran aditif) - karena metode penghapusan partikel ini memerintahkan ulang susunan array

bluescrn
sumber
-1

Cara tercepat yang saya anggap adalah menemukan mesin partikel dan menggunakannya untuk efek Anda. Berikut ini beberapa di antaranya:

RCIX
sumber