Der schnellste Weg, um einen einfachen Partikeleffekt zu erzeugen

12

Ich bin auf der Suche nach dem schnellsten Weg, um einen wirklich einfachen Partikeleffekt zu erzeugen, der im Spiel höllisch verbreitet wird ...

Grundsätzlich sieht mein Spiel aus wie ein Vectrex-Spiel, das hauptsächlich aus Linien besteht. Ich möchte ein paar kleine Explosionen machen, die sehr häufig vorkommen.

Gibt es etwas, das schneller ist, als sich nur um einige Punkte zu bewegen und mit GL_Point zu rendern?

Speeder
quelle
+1 nur für die Vectrex-Referenz. Ich habe als Kind in den frühen 80ern ein paar lustige Stunden mit Scramble und Tempest verbracht. Ohne das wäre ich heute wahrscheinlich nicht als Spieleentwickler gelandet.
Kylotan
Ja, Tempest ist großartig: D
speeder
Wie sage ich, dass keiner richtig ist?
Speeder

Antworten:

13

Es ist wirklich nicht notwendig, Speicher für jedes Partikel zu speichern und jedes Partikel separat zu animieren. Sie können dies prozedural durchführen, indem Sie die Partikelposition während des Zeichnens mithilfe der klassischen physikalischen Gleichung rekonstruieren. s = ut + 1 / 2.at ^ 2

Ein einfaches Beispiel (ohne konstante Teilchenbeschleunigung):


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

Dann erhöhst du einfach bei jeder Iteration deiner Update-Schleife an timeElapsed.

Die Implementierung auf der GPU ist ebenfalls problemlos möglich, sodass Ihre CPU nicht mehr arbeiten muss. Eine GPU-Implementierung könnte folgendermaßen aussehen:

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

Der GPU Vertex Shader rekonstruierte dann die Partikelposition über die Physikgleichung und die an ihn übergebenen Uniformen / Konstanten - genau wie die CPU-Version.

Um eine gewisse Varianz hinzuzufügen, können Sie mehrere Explosionen gleichzeitig mit leicht abweichenden Parametern verwenden, Farben / Alpha animieren und unterschiedliche Startpositionen auswählen. etc.

jpaver
quelle
Sie können auch die Vorhersagbarkeit von Pseudozufallszahlen verwenden, um alle Anfangsvektoren der Partikel zu generieren. Dabei werden Hunderte von Partikeln aus den Daten einiger int erstellt. Die Verwendung der GPU zum Erstellen der Quads ist eine wirklich gute Idee für einfache Partikel.
Skizz 30.07.10
Seit Jahren mache ich Partikelsysteme auf traditionelle Weise mit Arrays von Klassen, die Partikel als halbintelligente Entitäten behandeln, und es schien immer irgendwie verschwenderisch und aufgebläht. Diese Methode ist viel besser für Basisteilchen, die nichts anderes tun, als über den Bildschirm zu fliegen.
Piku
7

Ich habe mehrere Tests durchgeführt, und der SCHNELLSTE Weg (der nicht am schnellsten zu codieren ist) waren Partikel aus GL_LINEs, die ihre Position und Geschwindigkeit kannten, und die als Punkte beim Rendern verwendet wurden (je schneller das Partikel ist, desto "Linie"). es wird, desto langsamer wird es ein Punkt).

Der Effekt ist WIRKLICH cool (sehen Sie sich jedes Geometrie-Krieg-Video an, um es zu sehen) und WIRKLICH schnell. Kick the crap aus Quads (vor allem, weil ich mit Quads die doppelte Anzahl von Vertices berechnen müsste)

Außerdem ist es besser als die Verwendung eines bereits erstellten Partikelsystems, da ich einen spezifischen und SCHNELLEN Effekt wollte. Partikelsysteme unterstützen normalerweise viele Funktionen mit proportionalem Overhead.

Speeder
quelle
2
+1 für die Erklärung, was Sie getan haben, obwohl ich neugierig auf weitere Details zu Ihren Tests wäre. =)
Leander
Übrigens: All das war im Sofortmodus (das ist das einzige, was ich codieren kann, und ich habe den Namen gestern erfahren ...)
Speeder
6

Normalerweise würde man Partikel als texturierte Quads verwenden. Behandeln Sie sie im Grunde genommen als 2D-Sprites und blenden Sie sie mit der Zeit aus und zerstören Sie sie, wenn sie unsichtbar sind. Besser noch, verwende die alten wieder, wenn du neue machst, damit du nicht die Erinnerung für diese Dinge verschwendest.

Wenn Sie vormultipliziertes Alpha für die Grafik verwenden, können Sie mit nur einer Mischoperation problemlos Licht, Feuer, Rauch und mehr unterstützen.

Kylotan
quelle
Hum ... Punkte sind nicht SCHNELLER als Texturen?
Speeder
2
Die Grafikhardware ist speziell für das Rastern von Texturen im Framebuffer optimiert. Wenn die Punkte schneller sind, ist die Wahrscheinlichkeit vernachlässigbar hoch und Sie verlieren alle Möglichkeiten, die Sie mit der Texturierung haben.
Kylotan,
wie ... was? Wohlgemerkt, ich mache kein Partikelsystem mit vollem Funktionsumfang, es ist nur ein bestimmter Effekt (kleine Explosionen, hauptsächlich für Gameplay-Feedback, wenn Sie etwas treffen)
Speeder
Wenn Sie nur Punkte oder Linien verwenden möchten, ist das in Ordnung. Ich kann nur kommentieren, was die meisten Leute für Partikel tun. Vielleicht würde ein ungefülltes Dreieck ein schönes Teilchen ergeben.
Kylotan,
4

Mit OpenGL ES 2.0, ES 1.X mit einer Erweiterung und OpenGL => 2.1 können Sie GL_POINT_SPRITES verwenden. GL_POINT_SPRITES sind wie ein Quad immer vor der Kamera.

In Fragment-Shadern können Sie:

  • Definieren Sie die Größe des Sprites mit gl_PointSize im Vertex-Shader
  • Verwenden Sie gl_PointCoord (UV-Koordinaten) im Fragment-Shader

Sie können Texturen mit Alpha verwenden, um Kugel-Sprites zu zeichnen ...

Ein Tutorial für Point Sprites

Ellis
quelle
Ich vermeide Erweiterungen, die dummen, die die Engine (die ich nicht gemacht habe) bereits benutzt, und die schon ausreichen, um mehrere Leute darüber zu beklagen, dass das Spiel nicht läuft ...
speeder
1

Die meisten Partikeleffektsysteme, die ich gesehen habe, zeichnen statt einer großen Anzahl von Punkten eine relativ kleine Anzahl von Billboard-Texturen, wobei jede Textur ein bisschen wie eine Explosion aussieht. Wenn Ihr Kunststil nicht wirklich verhindert, werden Sie wahrscheinlich glücklicher sein, diesen Weg zu gehen. Dies minimiert die Menge an Partikeln, die Sie einzeln animieren und rendern müssen, während Sie dennoch einen großen visuellen Effekt erzielen.

herrlich
quelle
1
Stimmt, aber er strebt den Vectrex-Stil an, da würde es weniger gut funktionieren.
Kaj
1
Genau das, was Kaj sagte ... es sinnlos wäre, und würde Download - Größe erhöhen (ich die meisten Grafik wechsle ich von Sprite zu wahren Vektoren können, so dass ich Dateigröße reduzieren)
Speeder
1

Für eine übersichtliche Art und Weise, mit dem Laichen / Löschen / Aktualisieren von Partikeln umzugehen, vorausgesetzt, Sie haben ein einfaches Array von Partikeln - Partikel [MAX_PARTICLES]:

Verfolgen Sie die aktiven Partikel (beginnend mit NumActiveParticles = 0)

Neue Partikel werden immer am Ende des Arrays hinzugefügt:

pNewParticle = &Particles[NumActiveParticles++];

Das Schlaue - Wenn Sie ein 'totes' Partikel entfernen, tauschen Sie es mit dem letzten aktiven Partikel aus und verringern Sie NumActiveParticles:

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

Dadurch wird vermieden, dass beim Laichen nach "nicht verwendeten Partikeln" gesucht wird, und dass ein Array von MAX_PARTICLES durchsucht wird, wenn keine verwendet werden.

Beachten Sie, dass dies nur funktioniert, wenn die Aktualisierungs- / Renderreihenfolge unwichtig ist (wie dies bei vielen Partikeleffekten der Fall ist, bei denen eine additive Mischung verwendet wird), da diese Methode zum Löschen eines Partikels das Array neu anordnet

Bluescrn
quelle
-1

Der schnellste Weg, den ich annehmen würde, ist, eine Partikelmaschine zu finden und diese für Ihre Effekte zu verwenden. Hier sind ein paar:

RCIX
quelle