ゲームで地獄のようにスパムされる本当にシンプルなパーティクル効果を作成する最速の方法を探しています...
基本的に、私のゲームはほとんどが線でできているvectrexゲームのように見えます。
いくつかのポイントを移動してGL_Pointでレンダリングするよりも高速なものがありますか?
ゲームで地獄のようにスパムされる本当にシンプルなパーティクル効果を作成する最速の方法を探しています...
基本的に、私のゲームはほとんどが線でできているvectrexゲームのように見えます。
いくつかのポイントを移動してGL_Pointでレンダリングするよりも高速なものがありますか?
回答:
実際には、すべてのパーティクルのメモリを保存し、各パーティクルを個別にアニメーション化する必要はありません。古典的な物理方程式を使用して、描画中に粒子の位置を再構築することにより、手続き的に行うことができます。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バージョンと同様です。
多少の差異を追加するには、わずかに異なるパラメーターでより多くの同時爆発を使用し、色/アルファをアニメートし、異なる開始位置を選択します。等
私はいくつかのテストを行いましたが、最速の方法(コードの最速ではない)は、位置と速度を知っているGL_LINEで作られたパーティクルであり、それをレンダリングのポイントとして使用しました(したがって、パーティクルが速く、最も「ライン」遅くなり、ポイントになります)。
効果は本当にクールで(ジオメトリ戦争のビデオを見てそれを見てください)、本当に速いです。クアッドからクラップを追い出します(特に、クアッドを使用すると頂点の2倍の量を計算する必要があるため)
また、特定のFASTエフェクトが必要だったため、既に完成したパーティクルシステムを使用するよりも優れています。パーティクルシステムは通常、多くの機能を比例したオーバーヘッドでサポートします。
通常、パーティクルはテクスチャマッピングされたクワッドとして実行すると思います。基本的に2Dスプライトとして扱い、時間の経過とともにフェードアウトし、見えないときにそれらを破壊します。さらに良いのは、新しいものを作成するときに古いものを再利用して、これらのことのためにメモリをスラッシングしないようにすることです。
アートで事前乗算されたアルファを使用すると、1種類のブレンド操作ですべてに加えてライト、火、煙などを簡単にサポートできます。
OpenGL ES 2.0、拡張機能付きES 1.X、およびOpenGL => 2.1では、GL_POINT_SPRITESを使用できます。GL_POINT_SPRITESは、常にカメラの前にあるクワッドのようなものです。
フラグメントシェーダーでは、次のことができます。
テクスチャをアルファで使用して、ボールスプライトを描画できます...
私が見たほとんどのパーティクルエフェクトシステムは、膨大な数のポイントを描画する代わりに、各テクスチャが爆発のように見える比較的少数のビルボードテクスチャを描画します。あなたのアートスタイルが本当に妨げない限り、あなたはおそらくそのルートを下るのが幸せになるでしょう。大きな視覚効果を与えながら、個別にアニメーション化してレンダリングするために必要なパーティクルの量を最小限に抑えます。
パーティクルの単純な配列-Particles [MAX_PARTICLES]があると仮定して、パーティクルのスポーン/削除/更新を適切に処理するために:
アクティブなパーティクルを追跡する(NumActiveParticles = 0から開始)
新しいパーティクルは常に配列の最後に追加されます:
pNewParticle = &Particles[NumActiveParticles++];
巧妙なビット-「デッド」パーティクルを削除するとき-最後のアクティブパーティクルと交換し、NumActiveParticlesを減らします。
if ( DeadParticle < NumActiveParticles-1 )
{
Particles[ DeadParticle ] = Particles[ NumActiveParticles-1 ];
}
NumActiveParticles--;
これにより、スポーン時の「未使用のパーティクル」の検索が回避され、使用されていない場合はMAX_PARTICLESの配列全体のスキャンが回避されます。
これは、更新/レンダリングの順序が重要でない場合にのみ機能することに注意してください(多くのパーティクルエフェクトの場合と同様に、加算ブレンドを使用します)-このパーティクルを削除する方法は配列を並べ替えるので