A maneira mais rápida de criar um efeito de partícula simples

12

Estou procurando a maneira mais rápida de criar um efeito de partícula realmente simples que será spam como o inferno no jogo ...

Basicamente, meu jogo parece um jogo vectrex, feito principalmente de linhas ... Quero fazer algumas pequenas explosões que serão realmente comuns.

Há algo mais rápido do que apenas mover alguns pontos e renderizar com o GL_Point?

speeder
fonte
+1 apenas para a referência Vectrex. Passei algumas horas divertidas em Scramble e Tempest quando criança no início dos anos 80. Sem isso, eu provavelmente não teria acabado como desenvolvedor de jogos hoje.
Kylotan
Sim, Tempest é incrível: D
speeder
Como digo que ninguém está correto?
speeder

Respostas:

13

Realmente não há necessidade de armazenar memória para cada partícula e animar cada partícula separadamente. Você pode fazer isso proceduralmente reconstruindo a posição das partículas durante o desenho usando a equação física clássica. s = ut + 1 / 2.at ^ 2

Um exemplo simples (sem aceleração 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();
}

Então você simplesmente aumenta s.timeElapsed em todas as iterações do seu loop de atualização.

Também é totalmente passível de ser implementado na GPU, liberando assim sua CPU de fazer qualquer trabalho. Uma implementação de gpu pode ser assim:

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

O shader de vértice da GPU reconstruiria a posição das partículas através da equação da física e os uniformes / constantes passados ​​para ela - exatamente como a versão da CPU.

Para adicionar alguma variação, você pode usar mais explosões simultâneas com parâmetros ligeiramente diferentes, animando cores / alfa, escolhendo diferentes posições iniciais. etc.

jpaver
fonte
Além disso, você pode usar a previsibilidade de números pseudo-aleatórios para gerar todos os vetores iniciais das partículas, criando centenas de partículas a partir de alguns dados de int. Usar a GPU para criar quads é uma boa ideia para partículas simples.
Skizz
Por anos, venho criando sistemas de partículas da maneira tradicional, com matrizes de classes que tratam as partículas como entidades semi-inteligentes e sempre pareceu meio desperdício e inchado. Dessa forma, é muito melhor para partículas básicas que não fazem nada além de vomitar na tela.
Piku
7

Fiz vários testes e a maneira MAIS RÁPIDA (não a mais rápida de codificar) era de partículas feitas de GL_LINEs que conheciam sua posição e velocidade, e usei isso como pontos ao renderizar (então, quanto mais rápida a partícula for, mais "linha" torna-se, mais lento, torna-se um ponto).

O efeito é REALMENTE legal (veja qualquer vídeo de guerra geométrica para vê-lo) e REALMENTE rápido também. Chute a porcaria dos quadríceps (especialmente porque os quads me obrigariam a calcular a quantidade dupla de vértices)

Além disso, é melhor do que usar um sistema de partículas já pronto, porque eu queria um efeito específico e RÁPIDO, os sistemas de partículas geralmente suportam muitos recursos, com uma quantidade proporcional de sobrecarga.

speeder
fonte
2
+1 por explicar o que você acabou fazendo, embora eu esteja curioso para saber mais detalhes sobre seus testes. =)
leander 14/08
Btw: Tudo isso estava no modo imediato (que é a única coisa que eu sei como código, e eu aprendi o nome ontem ...)
speeder
6

Normalmente eu acho que você faria partículas como quads mapeados em textura. Trate-os como sprites 2D basicamente e desbote-os com o tempo, destruindo-os quando invisíveis. Melhor ainda, reutilize os antigos quando criar novos, para não perder a memória dessas coisas.

Se você usar alfa pré-multiplicado na arte, poderá facilmente suportar luzes, fogo, fumaça e muito mais, além de tudo com um tipo de operação de mistura.

Kylotan
fonte
Hum ... pontos não são mais RÁPIDOS do que texturas?
speeder
2
O hardware gráfico é otimizado especificamente para rasterizar texturas no buffer de quadros. Se os pontos são mais rápidos, é provável que seja por uma quantia insignificante e você perde todas as possibilidades que obtém com a texturização.
Kylotan
como o quê? Mente-lhe que eu não estou fazendo um sistema de partículas cheio de recursos, é apenas um efeito específico (pequenas explosões, principalmente para o gabarito de jogo que você bater em alguma coisa)
speeder
Se você só quer usar pontos ou linhas, tudo bem. Só posso comentar o que a maioria das pessoas faz por partículas. Talvez um triângulo não preenchido forme uma partícula agradável.
Kylotan
4

Com o OpenGL ES 2.0, ES 1.X com uma extensão e OpenGL => 2.1, você pode usar GL_POINT_SPRITES. GL_POINT_SPRITES são como um quad sempre na frente da câmera.

Nos shaders de fragmentos, você pode:

  • definir tamanhos de sprite com gl_PointSize no vertex shader
  • use gl_PointCoord (coordenadas uv) no sombreador de fragmentos

Você pode usar textura com alfa para desenhar sprites de bola ...

Um tutorial para Sprites de ponto

Ellis
fonte
Estou evitando extensões, os tolos que o motor (que não fez) já utilizam, são alraedy suficiente para várias pessoas se queixam de que o jogo não correr ...
speeder
1

A maioria dos sistemas de efeito de partículas que eu já vi, em vez de desenhar um grande número de pontos, desenha um número relativamente menor de texturas de outdoors, onde cada textura se parece um pouco com uma explosão. A menos que seu estilo artístico realmente impeça, você provavelmente ficará mais feliz seguindo esse caminho. Isso minimizará a quantidade de partículas que você precisa para animar e renderizar individualmente, enquanto ainda gera um grande efeito visual.

maravilhoso
fonte
1
É verdade, mas ele está mirando no estilo Vectrex, funcionaria menos bem lá.
Kaj 27/07
1
Exatamente o que Kaj disse ... seria inútil, e que aumentar o tamanho do download (eu estou passando o maior número de gráficos que eu posso de sprite para vetores verdadeiros, para que eu possa reduzir o tamanho do arquivo)
speeder
1

Para uma maneira simples de lidar com a desova / exclusão / atualização de partículas, supondo que você tenha uma matriz simples de partículas - Partículas [MAX_PARTICLES]:

Acompanhe as partículas ativas (começando com NumActiveParticles = 0)

Novas partículas são sempre adicionadas no final da matriz:

pNewParticle = &Particles[NumActiveParticles++];

A parte inteligente - Ao remover uma partícula 'morta' - troque-a pela última partícula ativa e diminua NumActiveParticles:

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

Isso evita qualquer pesquisa por 'partículas não usadas' durante a geração e evita qualquer varredura por uma matriz de MAX_PARTICLES se nenhuma estiver em uso.

Observe que isso só funciona se a ordem de atualização / renderização não for importante (como é o caso de muitos efeitos de partículas, que usam mistura aditiva) - pois esse método de excluir uma partição reordena a matriz

bluescrn
fonte
-1

A maneira mais rápida que eu assumiria é encontrar um mecanismo de partículas e usá-lo para seus efeitos. Aqui estão alguns:

RCIX
fonte