11

私は独自のパーティクルシステムエンジンを設計しています。これは学習目的であり、既存のエンジンを実際には使用したくありません。

今は美しいパーティクルを生成しましたが、操作しやすいようにエンジンをレイアウトしたいと思います。

私はクラス「パーティクルシステム」について考えていましたが、

そのクラスには、次の参照が含まれます。

粒子リスト:システムを構成する粒子のリスト。

systemEmitter:パーティクルのシステムエミッタであるEmitterクラスは、たとえば、線、点からの放出、ポリゴンからのランダムな放出など、いくつかの粒子放出技術を実行できる必要があります。また、このクラスは、放出する方向と時間で、点に向かって、点から離れて放出するように、放出制御を行う必要があります。

particleController:たとえば、ポイントの周りの回転、可変の粒子サイズ、可変の粒子の色、粒子がさまざまな方法で反応するシステムの周囲の領域、衝突検出(他のオブジェクトとの衝突、または必要に応じて粒子内)を管理します。

パーティクルレンダラー:このシステムの描画を担当し、可変ブレンディングタイプ、パーティクルテクスチャ、三角形、円、カスタムなどのパーティクルタイプ...

この4つのアイテムは、パーティクルシステムクラスを構成します。一部のFXでは、複数のパーティクルシステムが必要になる場合があります。たとえば、Fire FXでは、火に1つのシステム、煙に1つのシステム、火花に1つのシステムを使用できます。

これは私が心に抱いていることですが、この設計アプローチが優れているかどうか、または何かが足りないか、何か別のことをすることができる/すべきであるかどうかを知りたいと思います。FXを「保存」する簡単な方法については考えていません。たとえば、エンジンに「火を引く」、「爆発を引く」、「噴水を引く」など、FX情報を保存するのに最適な方法は何でしょうか。 xmlファイルでの使用などをお勧めします。

意見は大歓迎です。前に述べたように、学習上の理由から、別のエンジンを使用するのではなく、これを作成したいと思います。

4

4 に答える 4

5

この設定は問題ないはずです。あなたが考えていることを願っているのは、どのデータがパーティクルクラスに含まれるパーティクルを構成するかということです。システムの実行時に可能な限り少ないメモリの読み取り/書き込みのみを行う必要があるため、必要不可欠なものだけを用意する必要があります。

それをデータ駆動型にする限り、それはかなり簡単なはずです。ロードにはxmlとバイナリ形式のオプションをお勧めします。そのため、開発中に(ツールがなくても)簡単に調整できます。ツールを入手するか、調整が完了したら、すばやく読み込むためにxmlをバイナリに変換します。

これらのパーティクルシステムの作成と更新を処理するマネージャクラスが必要になる場合もあります。これにより、すべてのシステムに関係する他の機能を処理する場所も可能になります。この例としては、パフォーマンス上の理由で管理できるパーティクルシステムやパーティクルの量を制限したり、すべてのシステムで考慮すべき衝突面を設定したりすることが挙げられます。

あなたはこれが教育目的であり、その点でこれらのことはかなり厄介だと言います(しかし、粒子が重いゲームでこれを使用する場合は重要です)。

これは、DirectXやOpenGLなどのAPIを使用してレンダリングしていると思います。その点で、パーティクルエフェクトはすべて、頂点情報用に同じメモリプールを共有します。これにより、レンダリング速度が大幅に向上します。また、錐台カリング(AABBまたはCircle)で使用するために、パーティクルシステムの影響を受ける領域の境界を追跡します。

パーティクルシステムの更新の大きな部分は、属性がある値から別の値にどのように移動するかです。値の補間をより動的にすることができれば、効果の見栄えが良くなります。単純に線形補間するだけで十分ですが、値を補間するために使用される動的グラフがある方がよい場合があります。たとえば、1秒で0から255の青になる代わりに、0.2秒で0から128になり、0.8秒で128-255になるのはクールかもしれません。これを追加すると、エフェクトの外観に関するオプションが大幅に増えます。

それに加えて、あなたはあなたが何をしたいのかについてかなり良い考えを持っていると思います。さまざまなタイプのパーティクルのレンダリングについてのあなたの言及は、あなたがこれについて正しい方法で考えていることを私に教えてくれます。ビルボードクワッドのレンダリングだけに焦点を当ててパーティクルエンジンを作成する人を見てきました。3Dジオメトリを放出するオプションがあると、見栄えが良くなります。また、システムがモデル情報を取得し、それを個別のパーティクルに動的に分割して放出する機能を備えていることを検討することもできます(まだ行っていない場合)。実際にモデルを爆発させると、爆発パーティクルを表示してオブジェクトをフェードアウトするか、損傷した状態に切り替えるよりもはるかに見栄えが良くなります。

于 2009-09-23T16:16:06.527 に答える
1

単純な2Dスプライト粒子を最適化するためのいくつかのアイデア。

頂点配列/VBO内のすべてのパーティクルを送信し、頂点シェーダーを使用して時間の経過とともにそれらの位置を更新することをお勧めします。これは、数式を使用して簡単に記述できる単純なモーションがある場合に最適です。ここでx(t)、およびy(t)(つまり、時間のみに依存します)。

もう1つの優れたアイデアは、三角形や四角形の代わりにポイントスプライトを使用することです。これにより、パイプラインに必要な帯域幅が4分の1に削減されます。


私のスペースシムでは、最も簡単なアプローチを実装しました。パーティクルは、glBegin()/を使用してテクスチャクワッドとして送信されglEnd()ます。それらは、個々のオブジェクトとして現在の「セクター」にダンプされ、ダンプ以降の時間から完全に独立しています。これは最も原始的で愚かでばかげた行動であり、パフォーマンスの大幅な低下の原因となります。特に、STLベクトルのイテレータを介してオブジェクトを反復処理し、オブジェクトを1つずつ順番に送信するためです。

必要なパーティクルの数と、それらに何をさせたいかを考慮する必要があります。*周囲に反応して衝突させたいですか?次に、CPUで処理される更新と、何度も送信されるデータが必要です。*彼らは可能な限り最も愚かな方法で飛び回っていますか?そうすれば、すべてのパーティクルをVBOおよびTBOとして送信し、シェーダーで更新できる場合があります。

楽しむ!


askerからのコメント#1に関連するように更新されました:-)

私がすることは、KISSの原則を使用することです。ParticleEmitterこれは、頂点配列、速度の配列、およびvector平面、球、三角形などの単純なコライダーのインスタンスを含むSTLを含むと呼ばれるクラスを意味します。vectorさらに、コライダーを備えた「グローバル」*STLを用意します。次に、コライダーに応じて速度を更新します。

同様のことがアファクター(重力、風など)でも実行できます。アフェクターを使用した別のSTLベクトルとParticleEmitter、アフェクターを使用した別の「グローバル」STLvectorです。

アフェクターとコライダーは、を実装するクラスになりますaffectParticle(particle_t*)。ここでstruct particle_t { float x,y,z; float vx,vy,vz; }。私はそれをPOD構造のままにし、で更新を実行しParticleEmitter::update()ます。

ただし、これをiPhoneで実行している場合は、複雑すぎる可能性がありますか?おそらく、あなたはすでに実装したもので逃げることができますか?自分のデザインがベンチマークの結果にどのように影響するかはわかりませんが、パーティクル、コライダー、アフェクターのカウントダウンを維持すると、およそ。でスケーリングするように聞こえるので、十分に合理的に聞こえますn*c+n*a

これらは私のアドホックな考えであり、私が個人的にそれをどのように実装するかです。あなたのデザイン、または他の人のデザインは、おそらくより良いでしょう:-)

*引用符で囲まれた「グローバル」は、使用中のスペース分割を利用するのがおそらく理にかなっているためです。

于 2009-09-29T20:43:15.020 に答える
1

私はC++で自分のエンジンに同じ優れた設計を実装しました。代わりに、参照とテンプレートポリシー(戦略-Alexandreskuの「ModernC ++ Desing」を読んでください)を使用しませんでした。静的ポリモーフィズムにより、パフォーマンスが向上します。

于 2010-03-14T20:28:03.347 に答える
0

私の経験に応じて、いくつかコメントしたいと思います。

  1. 従来、ほとんどのパーティクルはAOS(Array of Struct)を使用してパーティクル属性を格納していました。しかし、これは最善の決定ではないかもしれません。SOA(Struct of Array)表現を使用すると、各パーティクルシステムの属性を追加するための多くの柔軟性が得られます。また、SOAを使用したSIMDを使用すると、パフォーマンスを大幅に向上させることができます。たとえば、SSE命令を使用して4つのパーティクルを一緒に実行します。
  2. パーティクルが放出される位置は、1つのパーティクル属性の初期化のみです。パーティクルを放出するときは、ライフタイム、ベロシティなどの他の属性を初期化する必要があります。これらすべての機能を初期化子として抽象化できます。位置については、ディスク初期化子、ボックス初期化子などがあります。
  3. いくつかの現代のパーティクルシステムは、イベントの概念を採用しています。パーティクルシステムはイベントを生成する可能性があり(たとえば、雨が地形と衝突する)、他のパーティクルシステムはリッスンして何らかのアクションを実行する可能性があります(たとえば、スプラッシュを放出する)。

ちなみに、既存のアプリケーション/ミドルウェアの設計を研究し、実験するのが最善の方法だと思います。

于 2012-11-14T09:51:12.053 に答える