Le moyen le plus rapide de créer un simple effet de particules


12

Je cherche le moyen le plus rapide de créer un effet de particules vraiment simple qui sera spammé comme un enfer sur le jeu ...

En gros, mon jeu ressemble à un jeu de vectrex, composé principalement de lignes ... Je veux faire quelques petites explosions qui seront vraiment courantes.

Il y a quelque chose de plus rapide que de se déplacer autour de certains points et de rendre avec GL_Point?


+1 juste pour la référence Vectrex. J'ai passé quelques heures amusantes sur Scramble and Tempest quand j'étais enfant au début des années 80. Sans cela, je ne serais probablement pas devenu développeur de jeux aujourd'hui.
Kylotan

Oui, Tempest est génial: D
speeder

Comment je dis qu'aucun n'est correct?
speeder

Réponses:


13

Il n'est vraiment pas nécessaire de stocker de la mémoire pour chaque particule et d'animer chaque particule séparément. Vous pouvez le faire de manière procédurale en reconstruisant la position des particules pendant le dessin en utilisant l'équation physique classique. s = ut + 1/2 à ^ 2

Un exemple simple (sans accélération constante des particules):


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

Ensuite, vous augmentez simplement la durée de vie à chaque itération de votre boucle de mise à jour.

Il est également tout à fait prêt à être implémenté sur le GPU, ce qui libère votre CPU de tout travail. Une implémentation gpu pourrait ressembler à ceci:

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

Le vertex shader du GPU reconstruirait alors la position des particules via l'équation physique et les uniformes / constantes qui lui sont passés - tout comme la version CPU.

Pour ajouter une certaine variance, vous pouvez utiliser plus d'explosions simultanées avec des paramètres légèrement différents, animant des couleurs / alpha, choisissant des positions de départ différentes. etc.


En outre, vous pouvez utiliser la prévisibilité des nombres pseudo-aléatoires pour générer tous les vecteurs initiaux des particules, créant des centaines de particules à partir de quelques données. L'utilisation du GPU pour créer les quads est une très bonne idée pour les particules simples.
Skizz

Pendant des années, j'ai fait des systèmes de particules de manière traditionnelle avec des tableaux de classes qui traitent les particules comme des entités semi-intelligentes et cela semblait toujours un peu inutile et gonflé. Cette méthode est bien meilleure pour les particules de base qui ne font rien de plus que de cracher sur l'écran.
Piku

7

J'ai fait plusieurs tests, et le moyen le plus RAPIDE (pas le plus rapide à coder) était des particules faites de GL_LINEs qui connaissaient leur position et leur vitesse, et qui les utilisaient comme points lors du rendu (donc, plus la particule va vite, plus il y a de "lignes") ça devient, le plus lent, ça devient un point).

L'effet est VRAIMENT cool (regardez n'importe quelle vidéo de guerres de géométrie pour le voir), et VRAIMENT rapide aussi. Coupez la merde des quads (surtout parce que les quads me obligeraient à calculer la double quantité de sommets)

En outre, c'est mieux que d'utiliser un système de particules déjà fait, car je voulais un effet spécifique et RAPIDE, les systèmes de particules prennent généralement en charge de nombreuses fonctionnalités, avec une quantité proportionnelle de surcharge.


2
+1 pour expliquer ce que vous avez fini par faire, même si je serais curieux d'entendre plus de détails sur vos tests. =)
leander

Btw: Tout cela était en mode immédiat (c'est la seule chose que je sais coder, et j'ai appris le nom hier ...)
speeder

6

Normalement, je pense que vous feriez des particules comme des quads à texture mappée. Traitez-les essentiellement comme des sprites 2D, et effacez-les au fil du temps, en les détruisant lorsqu'ils sont invisibles. Mieux encore, réutilisez les anciens lorsque vous en créez de nouveaux afin de ne pas vider la mémoire de ces choses.

Si vous utilisez l' alpha prémultiplié sur l'art, vous pouvez facilement supporter les lumières, le feu, la fumée et bien plus encore avec un seul type d'opération de mélange.


Hum ... les points ne sont pas PLUS RAPIDES que les textures?
speeder

2
Le matériel graphique est spécialement optimisé pour rastériser les textures du framebuffer. Si les points sont plus rapides, c'est probablement d'une quantité négligeable, et vous perdez toutes les possibilités que vous obtenez avec la texturation.
Kylotan

comme ça? Remarquez que je ne fais pas un système de particules complet, ce n'est qu'un effet spécifique (petites explosions, principalement pour les commentaires de gameplay que vous frappez quelque chose)
speeder

Si vous voulez simplement utiliser des points ou des lignes, c'est bien. Je ne peux que commenter ce que la plupart des gens font pour les particules. Peut-être qu'un triangle non rempli ferait une belle particule.
Kylotan

4

Avec OpenGL ES 2.0, ES 1.X avec une extension et OpenGL => 2.1, vous pouvez utiliser GL_POINT_SPRITES. GL_POINT_SPRITES sont comme un quad toujours devant la caméra.

Dans les shaders de fragments, vous pouvez:

  • définir les tailles de sprite avec gl_PointSize dans le vertex shader
  • utiliser gl_PointCoord (coordonnées uv) dans le fragment shader

Vous pouvez utiliser la texture avec alpha pour dessiner des sprites de balle ...

Un tutoriel pour Point Sprites


J'évite les extensions, les idiotes que le moteur (que je n'ai pas fait) utilisent déjà, sont déjà suffisantes pour que plusieurs personnes se plaignent que le jeu ne tourne pas ...
speeder

1

La plupart des systèmes d'effets de particules que j'ai vus, au lieu de dessiner un grand nombre de points, dessinent un nombre relativement plus petit de textures d'affichage où chaque texture ressemble un peu à une explosion. À moins que votre style artistique ne vous empêche vraiment de le faire, vous serez probablement plus heureux de suivre cette voie. Il minimisera la quantité de particules dont vous avez besoin pour animer et rendre individuellement tout en donnant un grand effet visuel.


1
Certes, mais il vise le style Vectrex, cela fonctionnerait moins bien là-bas.
Kaj

1
Exactement ce que Kaj a dit ... ce serait inutile ET augmenterait la taille du téléchargement (je passe le plus de graphiques possible du sprite aux vrais vecteurs, donc je peux réduire la taille du fichier)
speeder

1

Pour un petit moyen soigné de gérer la génération / suppression / mise à jour des particules, en supposant que vous avez un simple tableau de particules - Particules [MAX_PARTICLES]:

Gardez une trace des particules actives (en commençant par NumActiveParticles = 0)

De nouvelles particules sont toujours ajoutées à la fin du tableau:

pNewParticle = &Particles[NumActiveParticles++];

Le morceau intelligent - Lors de la suppression d'une particule «morte» - échangez-la avec la dernière particule active et décrémentez NumActiveParticles:

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

Cela évite toute recherche de «particules inutilisées» lors du frai et évite toute analyse à travers un tableau de MAX_PARTICLES si aucune n'est utilisée.

Notez que cela ne fonctionne que si l'ordre de mise à jour / rendu n'est pas important (comme c'est le cas pour de nombreux effets de particules, qui utilisent le mélange additif) - car cette méthode de suppression d'une particule réordonne le tableau


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.