La forma más rápida de crear un efecto de partícula simple

12

Estoy buscando la forma más rápida de crear un efecto de partículas realmente simple que se enviará como spam en el juego ...

Básicamente, mi juego se ve como un juego vectrex, hecho principalmente de líneas ... Quiero hacer algunas pequeñas explosiones que serán realmente comunes.

¿Hay algo más rápido que simplemente moverse por algunos puntos y renderizar con GL_Point?

Speeder
fuente
+1 solo para la referencia de Vectrex. Pasé algunas horas divertidas en Scramble and Tempest cuando era niño a principios de los 80. Sin eso, probablemente no habría terminado hoy como desarrollador de juegos.
Kylotan
Sí, la tempestad es increíble: D
speeder
¿Cómo digo que ninguno es correcto?
Speeder

Respuestas:

13

Realmente no hay necesidad de almacenar memoria para cada partícula y animar cada partícula por separado. Puede hacerlo procedimentalmente al reconstruir la posición de la partícula durante el dibujo utilizando la ecuación de física clásica. s = ut + 1 / 2.at ^ 2

Un ejemplo simple (sin aceleración constante de partículas):


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

Luego, simplemente aumenta s.timeElapsed en cada iteración de su ciclo de actualización.

También es completamente susceptible de implementarse en la GPU, liberando así a su CPU de tener que hacer cualquier trabajo. Una implementación de gpu podría verse así:

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

El sombreador de vértices de la GPU luego reconstruiría la posición de la partícula a través de la ecuación física y los uniformes / constantes pasaron a ella, tal como lo hizo la versión de la CPU.

Para agregar alguna variación, puede usar más explosiones simultáneas con parámetros ligeramente diferentes, animando colores / alfa, eligiendo diferentes posiciones de inicio. etc.

jpaver
fuente
Además, puede usar la previsibilidad de números pseudoaleatorios para generar todos los vectores iniciales de las partículas, creando cientos de partículas a partir de unos pocos datos de int. Usar la GPU para crear los quads es una muy buena idea para partículas simples.
Skizz
Durante años, he estado haciendo sistemas de partículas de la manera tradicional con conjuntos de clases que tratan a las partículas como entidades semiinteligentes y siempre me pareció un poco derrochador e hinchado. De esta manera es mucho mejor para las partículas básicas que no hacen más que arrojar a través de la pantalla.
Piku
7

Hice varias pruebas, y la forma MÁS RÁPIDA (no la más rápida de codificar) fue partículas hechas de GL_LINE que conocían su posición y velocidad, y las usé como puntos al renderizar (por lo tanto, cuanto más rápido va la partícula, más "línea" se vuelve, más lento, se convierte en un punto).

El efecto es REALMENTE genial (mira cualquier video de geometry wars para verlo), y REALMENTE rápido también. Expulsar a los quads (especialmente porque los quads me harían necesitar calcular la cantidad doble de vértices)

Además, es mejor que usar un sistema de partículas ya hecho, porque quería un efecto específico y RÁPIDO, los sistemas de partículas generalmente admiten muchas características, con una cantidad proporcional de sobrecarga.

Speeder
fuente
2
+1 por explicar lo que terminaste haciendo, aunque me gustaría saber más sobre tus pruebas. =)
leander
Por cierto: todo eso estaba en modo inmediato (eso es lo único que sé codificar, y aprendí el nombre ayer ...)
Speeder
6

Normalmente creo que harías partículas como quads mapeados con textura. Trátelos básicamente como sprites 2D y desvanezca con el tiempo, destruyéndolos cuando sean invisibles. Mejor aún, reutilice los viejos cuando haga otros nuevos para no estar agotando la memoria de estas cosas.

Si usa alfa premultiplicado en el arte, puede soportar fácilmente luces, fuego, humo y más, además de todo con un solo tipo de operación de mezcla.

Kylotan
fuente
Hum ... ¿los puntos no son MÁS RÁPIDOS que las texturas?
Speeder
2
El hardware de gráficos está específicamente optimizado para rasterizar texturas al framebuffer. Si los puntos son más rápidos, es probable que sea por una cantidad insignificante, y pierdes todas las posibilidades que obtienes con la textura.
Kylotan
¿como que? Que no estoy haciendo un sistema completo de partículas ofrecido importa, es sólo un efecto específico (pequeñas explosiones, sobre todo para la retroalimentación de juego que se golpea algo)
reductor de velocidad
Si solo quieres usar puntos o líneas, entonces está bien. Solo puedo comentar lo que la mayoría de la gente hace por las partículas. Tal vez un triángulo sin relleno sería una buena partícula.
Kylotan
4

Con OpenGL ES 2.0, ES 1.X con una extensión y OpenGL => 2.1, puede usar GL_POINT_SPRITES. GL_POINT_SPRITES son como un quad siempre delante de la cámara.

En fragment shaders, puedes:

  • definir tamaños de sprite con gl_PointSize en vertex shader
  • use gl_PointCoord (coordenadas uv) en fragment shader

Puedes usar textura con alfa para dibujar sprites de bola ...

Un tutorial para Point Sprites

Ellis
fuente
Estoy evitando las extensiones, las tontas que el motor (que no hice) ya usan, son lo suficientemente alocadas como para que varias personas se quejen de que el juego no se ejecuta ... ''
dijo el
1

La mayoría de los sistemas de efectos de partículas que he visto, en lugar de dibujar una gran cantidad de puntos, dibujan una cantidad relativamente menor de texturas de vallas publicitarias donde cada textura se parece un poco a una explosión. A menos que su estilo artístico realmente lo impida, es probable que sea más feliz siguiendo ese camino. Minimizará la cantidad de partículas que necesita para animar y renderizar individualmente, a la vez que le dará un gran efecto visual.

munificente
fuente
1
Es cierto, pero apunta al estilo Vectrex, funcionaría menos bien allí.
Kaj
1
Exactamente lo que dijo Kaj ... no tendría sentido, y aumentaría el tamaño de descarga (estoy cambiando las mayoría de los gráficos que puedo de sprite para vectores verdaderos, por lo que puede reducir el tamaño del archivo)
reductor de velocidad
1

Para una pequeña forma ordenada de manejar el desove / eliminación / actualización de partículas, suponiendo que tenga una matriz simple de partículas - Partículas [MAX_PARTICLES]:

Mantenga un registro de las partículas activas (comenzando con NumActiveParticles = 0)

Siempre se agregan nuevas partículas al final de la matriz:

pNewParticle = &Particles[NumActiveParticles++];

El bit inteligente: al eliminar una partícula 'muerta', cámbiela por la última partícula activa y disminuya NumActiveParticles:

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

Esto evita cualquier búsqueda de 'partículas no utilizadas' durante el desove, y evita cualquier exploración a través de una matriz de MAX_PARTICLES si no hay ninguna en uso.

Tenga en cuenta que esto solo funciona si el orden de actualización / renderización no es importante (como es el caso de muchos efectos de partículas, que usan una combinación de aditivos), ya que este método de eliminar una partícula reordena la matriz

bluescrn
fuente