シンプルなパーティクルエフェクトを作成する最速の方法


12

ゲームで地獄のようにスパムされる本当にシンプルなパーティクル効果を作成する最速の方法を探しています...

基本的に、私のゲームはほとんどが線でできているvectrexゲームのように見えます。

いくつかのポイントを移動してGL_Pointでレンダリングするよりも高速なものがありますか?


Vectrex参照のためだけに+1。80年代前半の子供の頃、スクランブルとテンペストで楽しい時間を過ごしました。それがなければ、おそらく今日のゲーム開発者として終わらないでしょう。
カイロタン

うん、テンペストは素晴らしいです:D-
スピーダー

どれも正しくないと言うにはどうすればいいですか?
スピーダー

回答:


13

実際には、すべてのパーティクルのメモリを保存し、各パーティクルを個別にアニメーション化する必要はありません。古典的な物理方程式を使用して、描画中に粒子の位置を再構築することにより、手続き的に行うことができます。s = ut + 1 / 2.at ^ 2

単純な例(粒子の一定の加速なし):


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

次に、更新ループの反復ごとにs.timeElapsedを増やすだけです。

また、GPUに実装することも完全に受け入れられるため、CPUを解放して作業を行う必要がなくなります。GPU実装は次のようになります。

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頂点シェーダーは、物理方程式とそれに渡されるユニフォーム/定数を介してパーティクルの位置を再構築します-CPUバージョンと同様です。

多少の差異を追加するには、わずかに異なるパラメーターでより多くの同時爆発を使用し、色/アルファをアニメートし、異なる開始位置を選択します。等


また、疑似乱数の予測可能性を使用して、すべてのパーティクルの初期ベクトルを生成し、少数のintのデータから数百のパーティクルを作成できます。GPUを使用してクワッドを作成することは、単純なパーティクルには本当に良いアイデアです。
スキズ

何年もの間、パーティクルを半インテリジェントなエンティティとして扱うクラスの配列を使用して、パーティクルシステムを伝統的な方法で作成してきました。この方法は、画面全体に噴出するだけの基本的なパーティクルには非常に適しています。
ピク

7

私はいくつかのテストを行いましたが、最速の方法(コードの最速ではない)は、位置と速度を知っているGL_LINEで作られたパーティクルであり、それをレンダリングのポイントとして使用しました(したがって、パーティクルが速く、最も「ライン」遅くなり、ポイントになります)。

効果は本当にクールで(ジオメトリ戦争のビデオを見てそれを見てください)、本当に速いです。クアッドからクラップを追い出します(特に、クアッドを使用すると頂点の2倍の量を計算する必要があるため)

また、特定のFASTエフェクトが必要だったため、既に完成したパーティクルシステムを使用するよりも優れています。パーティクルシステムは通常、多くの機能を比例したオーバーヘッドでサポートします。


2
あなたがやったことを説明するために+1。=)
スリム

Btw:それはすべて即時モードでした(コード化の方法を知っているのはそれだけで、昨日名前を覚えました...)
スピーダー

6

通常、パーティクルはテクスチャマッピングされたクワッドとして実行すると思います。基本的に2Dスプライトとして扱い、時間の経過とともにフェードアウトし、見えないときにそれらを破壊します。さらに良いのは、新しいものを作成するときに古いものを再利用して、これらのことのためにメモリをスラッシングしないようにすることです。

アートで事前乗算されたアルファを使用すると、1種類のブレンド操作ですべてに加えてライト、火、煙などを簡単にサポートできます。


ええと...ポイントはテクスチャよりも速くありませんか?
スピーダー

2
グラフィックスハードウェアは、テクスチャをフレームバッファにラスタライズするために特に最適化されています。ポイントがより速い場合、それはごくわずかな量である可能性が高く、テクスチャリングで得られる可能性をすべて失います。
カイロタン

どのような?私は、それが唯一の特定の効果(あなたが何かを打つことを主にゲームプレイのフィードバックのための小さな爆発、)でフル機能のパーティクルシステムを作っていないです断っておくが
スピーダー

ポイントまたはラインのみを使用する場合は、問題ありません。私がコメントできるのは、ほとんどの人がパーティクルに対して行っていることだけです。たぶん、塗りつぶされていない三角形が素敵な粒子になるでしょう。
カイロタン

4

OpenGL ES 2.0、拡張機能付きES 1.X、およびOpenGL => 2.1では、GL_POINT_SPRITESを使用できます。GL_POINT_SPRITESは、常にカメラの前にあるクワッドのようなものです。

フラグメントシェーダーでは、次のことができます。

  • 頂点シェーダーでgl_PointSizeを使用してスプライトのサイズを定義します
  • フラグメントシェーダーでgl_PointCoord(uv座標)を使用する

テクスチャをアルファで使用して、ボールスプライトを描画できます...

ポイントスプライトのチュートリアル


私は拡張子を避けています、(私が作っていないこと)エンジンがすでに使用することを愚かなものは、いくつかの人々に十分なalraedyは、ゲームが実行されないことを不平を言うが...
スピーダー

1

私が見たほとんどのパーティクルエフェクトシステムは、膨大な数のポイントを描画する代わりに、各テクスチャが爆発のように見える比較的少数のビルボードテクスチャを描画します。あなたのアートスタイルが本当に妨げない限り、あなたはおそらくそのルートを下るのが幸せになるでしょう。大きな視覚効果を与えながら、個別にアニメーション化してレンダリングするために必要なパーティクルの量を最小限に抑えます。


1
確かに、彼はVectrexスタイルを目指していますが、そこではあまりうまくいきません。
カイ

1
まさにカイが言ったこと...それは無意味であり、ダウンロードサイズを増やします(私はスプライトから本当のベクトルにできる限り多くのグラフィックを切り替えているので、ファイルサイズを減らすことができます)
スピーダー

1

パーティクルの単純な配列-Particles [MAX_PARTICLES]があると仮定して、パーティクルのスポーン/削除/更新を適切に処理するために:

アクティブなパーティクルを追跡する(NumActiveParticles = 0から開始)

新しいパーティクルは常に配列の最後に追加されます:

pNewParticle = &Particles[NumActiveParticles++];

巧妙なビット-「デッド」パーティクルを削除するとき-最後のアクティブパーティクルと交換し、NumActiveParticlesを減らします。

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

これにより、スポーン時の「未使用のパーティクル」の検索が回避され、使用されていない場合はMAX_PARTICLESの配列全体のスキャンが回避されます。

これは、更新/レンダリングの順序が重要でない場合にのみ機能することに注意してください(多くのパーティクルエフェクトの場合と同様に、加算ブレンドを使用します)-このパーティクルを削除する方法は配列を並べ替えるので


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.