Basit bir parçacık efekti oluşturmanın en hızlı yolu


12

Oyunda cehennem gibi spam olacak gerçekten basit parçacık efekti oluşturmanın en hızlı yolunu arıyorum ...

Temelde, oyunum çoğunlukla hatlardan yapılmış bir vectrex oyununa benziyor ... Gerçekten yaygın olacak bazı küçük patlamalar yapmak istiyorum.

Bazı noktalarda dolaşmak ve GL_Point ile render etmekten daha hızlı bir şey var mı?


+1 yalnızca Vectrex referansı için. 80'lerin başında bir çocuk olarak Scramble ve Tempest'te eğlenceli saatler geçirdim. Bu olmadan, muhtemelen bugün bir oyun geliştiricisi olarak bitiremezdim.
Kylotan

Evet, Fırtına harika: D
speeder

Hiçbirinin doğru olmadığını nasıl söyleyebilirim?
speeder

Yanıtlar:


13

Her parçacık için bellek depolamaya ve her parçacığı ayrı ayrı canlandırmaya gerçekten gerek yoktur. Klasik fizik denklemini kullanarak çizim sırasında parçacık pozisyonunu yeniden yapılandırarak prosedürel olarak yapabilirsiniz. s = ut + 1 / 2.at ^ 2

Basit bir örnek (parçacıkların sürekli hızlanması olmadan):


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

Daha sonra güncelleme döngünüzün her yinelemesinde s.timeElaed öğesini basitçe arttırırsınız.

Ayrıca GPU'ya uygulanmaya tamamen uygundur, böylece CPU'nuzu herhangi bir iş yapmak zorunda bırakmaz. Bir gpu uygulaması şöyle görünebilir:

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 tepe gölgeleyici daha sonra parçacık konumunu fizik denklemi aracılığıyla yeniden yapılandırır ve üniformalar / sabitler - tıpkı CPU sürümü gibi.

Biraz sapma eklemek için, farklı başlangıç ​​pozisyonları seçerek, renkleri / alfa animasyonunu canlandıran, biraz farklı parametrelerle daha eşzamanlı patlamalar kullanabilirsiniz. vb.


Ayrıca, tüm parçacıkların başlangıç ​​vektörlerini oluşturmak için sözde rasgele sayıların öngörülebilirliğini kullanarak, birkaç int değerindeki verilerden yüzlerce parçacık yaratabilirsiniz. Dörtlü oluşturmak için GPU'yu kullanmak basit parçacıklar için gerçekten iyi bir fikirdir.
Skizz

Yıllardır parçacık sistemlerini, parçacıkları yarı-akıllı varlıklar olarak ele alan sınıf dizileriyle geleneksel bir şekilde yapıyorum ve her zaman savurgan ve şişkin görünüyordu. Bu şekilde, ekran boyunca yayılmaktan başka bir şey yapmayan temel parçacıklar için çok daha iyidir.
Piku

7

Birkaç test yaptım ve HIZLI yol (kodlamanın en hızlısı değil), konumlarını ve hızlarını bilen GL_LINE'lardan yapılmış parçacıklardı ve bunu render yaparken puanlar olarak kullandı (bu yüzden parçacık ne kadar hızlı olursa, en "çizgi" yavaşlar, bir nokta olur).

Efekt GERÇEKTEN serin (görmek için herhangi bir geometri savaş videosuna bakın) ve GERÇEKTEN hızlı. Dörtlüleri berbat et (özellikle dörtlüler, çift köşe sayısını hesaplamamı gerektirdiğinden)

Ayrıca, zaten yapılmış bir parçacık sistemini kullanmaktan daha iyidir, çünkü belirli ve HIZLI bir etki istedim, parçacık sistemleri genellikle orantılı miktarda ek yük ile birçok özelliği destekler.


2
Testleriniz hakkında daha fazla ayrıntı duymak isterim, ancak ne yaptığınızı açıkladığınız için +1. =)
leander

Btw: Tüm bunlar anında moddaydı (kodlamayı bildiğim tek şey budur ve dün adı öğrendim ...)
hızlı

6

Normalde parçacıkları doku eşlemli dörtlü olarak yaparsınız. Onlara temel olarak 2D sprite olarak davranın ve görünmez olduğunda onları yok ederek zamanla kaybolun. Daha da iyisi, yenilerini yaptığınızda eskileri yeniden kullanın, böylece bu şeyler için hafızayı daraltmazsınız.

Sanatta önceden çarpılmış alfa kullanırsanız , ışıkları, ateşi, dumanı ve daha fazlasını tek bir karıştırma işlemiyle kolayca destekleyebilirsiniz.


Hum ... noktaları dokulardan daha hızlı değil mi?
hız

2
Grafik donanımı, dokuları çerçeve arabelleğine tarama için özel olarak optimize edilmiştir. Puanlar daha hızlıysa, ihmal edilebilir bir miktarda olması muhtemeldir ve tekstüre etme ile elde ettiğiniz tüm olasılıkları kaybedersiniz.
Kylotan

ne gibi? Tam özellikli bir parçacık sistemi yapmamaya dikkat edin, bu sadece belirli bir etki (çoğunlukla bir şeye çarptığınız oyun geri bildirimi için küçük patlamalar)
speed

Sadece noktalar veya çizgiler kullanmak istiyorsanız, sorun değil. Sadece çoğu insanın parçacıklar için ne yaptığı hakkında yorum yapabilirim. Belki doldurulmamış bir üçgen güzel bir parçacık yapar.
Kylotan

4

OpenGL ES 2.0, uzantılı ES 1.X ve OpenGL => 2.1 ile GL_POINT_SPRITES kullanabilirsiniz. GL_POINT_SPRITES her zaman kamera önünde dörtlü gibidir.

Parça gölgelendiricilerde şunları yapabilirsiniz:

  • köşe gölgelendiricisinde gl_PointSize ile hareketli grafik boyutlarını tanımlama
  • fragman gölgesinde gl_PointCoord (uv koordinatları) kullan

Top spriteları çizmek için alfa ile doku kullanabilirsiniz ...

Point Sprite'lar için bir eğitim


Uzantılardan kaçınıyorum, motorun (benim yapmadığım) aptal olanlar, birkaç kişi için oyunun çalışmadığından şikayet edecek kadar
alraedy

1

Gördüğüm çoğu parçacık efekt sistemi, çok sayıda nokta çizmek yerine, her bir dokunun bir patlamaya benzediği nispeten daha az sayıda billboard dokusu çiziyor. Sanat tarzınız gerçekten engellemedikçe, muhtemelen o rotadan daha mutlu olacaksınız. Yine de büyük bir görsel efekt verirken bireysel olarak canlandırmak ve işlemek için ihtiyacınız olan parçacık miktarını en aza indirir.


1
Doğru, ama Vectrex stilini hedefliyor, orada daha az işe yarayacaktı.
Kaj

1
Kaj tam olarak ne dedi ... anlamsız olurdu, ve indirme boyutunu artıracaktır (sprite'dan gerçek vektörlere yapabileceğim en fazla grafiği değiştiriyorum, bu yüzden dosya boyutunu azaltabilirim)
hız

1

Basit bir parçacık dizisine sahip olduğunuzu varsayarak parçacıkların yumurtlama / silme / güncellemesini işlemenin küçük bir yolu için - Parçacıklar [MAX_PARTICLES]:

Aktif partikülleri takip edin (NumActiveParticles = 0 ile başlayan)

Dizinin sonuna her zaman yeni parçacıklar eklenir:

pNewParticle = &Particles[NumActiveParticles++];

Akıllı bit - 'Ölü' bir parçacığı çıkarırken - son aktif parçacıkla değiştirin ve NumActiveParticles'ı azaltın:

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

Bu, yumurtlama sırasında 'kullanılmayan parçacıklar' aramasını önler ve hiçbiri kullanılmıyorsa MAX_PARTICLES dizisi üzerinden herhangi bir tarama yapılmasını önler.

Bunun yalnızca güncelleme / oluşturma sırası önemsiz olduğunda (ek harmanlama kullanan birçok parçacık efektinde olduğu gibi) işe yaradığını unutmayın - bir parçacığı silme yöntemi diziyi yeniden sipariş ettiğinden


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.