2009-02-26 17 views
2

私はいくつかのパーティクルシステムの目のキャンディをスピードアップする必要があります。目のキャンディーには、添加剤の配合、蓄積、および粒子上の尾跡および輝きが含まれる。現時点では、手作業で浮動小数点イメージバッファにレンダリングしています。最後の分にunsigned charに変換してから、OpenGLテクスチャにアップロードします。グローをシミュレートするために、異なる解像度と異なるオフセットで同じテクスチャを複数回レンダリングしています。これは遅すぎることが証明されているので、私は何かを変えようとしています。問題は、私の開発ハードウェアはインテルGMA950ですが、ターゲットマシンにはNvidia GeForce 8800が搭載されているため、この段階でOpenGLをプロファイリングするのは難しいです。グラフィックス:浮動小数点累積画像で最高の性能

非常に科学的ではないプロファイリングを行いましたが、スローダウンの大部分は浮動小数点画像を扱うことから来ていることが判明しました:すべてのピクセルを定数でスケーリングしてフェードアウトし、浮動小数点画像を符号なしの文字に変換してアップロードするグラフィックハードウェアだから、私は最適化のため、以下のオプションで探しています:

  • 定点で16.16の構成をUINT32さんとの山車を交換し
  • SSE2アセンブリを使用して最適化フロート操作(画像バッファは、山車の1024 * 768 * 3の配列であります)
  • 使用のOpenGL蓄積バッファの代わりにfloat配列
  • 利用のOpenGLの浮動小数点FBOの代わりにfloat配列の
  • 使用OpenGLのピクセル/バーテックスシェーダ

あなたを持っていますこれらの可能性のある経験はありますか?どんな考え、助言?私が考えなかった何か他に?

+0

私たちはスクリーンショットを見ることができますか? – Peter

答えて

4

問題は単純に処理しなければならないデータの量です。

フロートバッファのサイズは9メガバイトで、データを複数回タッチします。ほとんどの場合、あなたのレンダリングループはやや次のようになります。

  • クリアバッファ
  • がそれに何かをレンダリング(用途は読み取りおよび書き込み)
  • 符号なしバイトに変換OpenGLの
をアップロード

これはあなたが移動するデータが非常に多く、キャッシュがあなたのキャッシュよりもはるかに大きいため、キャッシュはあなたを助けません。すべてのピクセルを5回タッチしたとします。もしそうなら、ゆっくりとしたメインメモリに45MBのデータを出し入れします。多くのデータのようには聞こえませんが、ほとんどのメモリアクセスがキャッシュミスになると考えてください。 CPUは、データが到着するのを待つのにほとんどの時間を費やします。

レンダリングを行うためにCPUを使いたい場合はあまりできません。いくつかのアイデア:非一時的なロードとストアため

SSEを使用して
  • 役立つかもしれないが、彼らは(あなたがあなたの読み取りおよび書き込みを揃えることがあります)あなたのタスクかなり複雑になります。

  • レンダリングをタイルに分割してみてください。例えば。小さな四角形(256 * 256程度)ですべてを行います。この背後にあるアイデアは、キャッシュから実際に利益を得ることです。長方形をクリアした後、例えばビットマップ全体がキャッシュに保存されます。比較的遅いメインメモリからデータを取得する必要がないため、レンダリングとバイトへの変換がより高速になります。

  • 最後の手段:パーティクルエフェクトの解像度を下げます。これは、あなたにビジュアル品質を犠牲にして恩恵を受けるでしょう。

最高の解決策は、グラフィックカードにレンダリングを移動することです。テクスチャ機能へのレンダリングは、最近の標準です。使用する拡張子を決定する必要があるため、OpenGLで動作させるのはちょっと難しいですが、一度それを動作させるともうパフォーマンスに問題はありません。

Btw - 本当にには浮動小数点レンダリングターゲットが必要ですか? 1ピクセルあたり3バイトがあれば、パフォーマンスが向上します。

+0

あなたの答えに感謝します!私は元の質問でこれを明確にしていませんでしたが、私は実際に長い間スムーズにそれらをフェードアウトできるようにフロートイメージを必要とする素敵なトレイルを残すことに興味があります... – damian

+0

ハーフフロートまたは16ビットチャンネルあたりの整数 –

1

手動コードをスプライトで置き換えてみてください。たとえば、アルファベットが10%のOpenGLテクスチャです。その後、画面上にたくさんのものを描きます(そのうち10個は同じ場所にあります)。

+0

ありがとうございますが、スプライトレンダリングでパフォーマンスの問題が起きていません(なぜなら、とにかく1つのピクセルしか描画していないからです)。 – damian

+0

私が言ったように:これをやめて、各粒子をいくつかの半透明なスプライトで置き換えます。あなたが1つの場所で描画するスプライトが多くなればなるほど、より多くの "輝き"が得られるはずです。 –

+0

私は元の質問でこれを明確にしていませんでしたが、私は本当に素敵なコースを残すことに興味があり、グローはセカンダリです。素敵なトレイルはフロートイメージを必要とするので、長い間スムーズにフェードアウトできます。 – damian

1

"手動"とは、ピクセルをポックするためにCPUを使用していることを意味しますが、OpenGLを使用してテクスチャポリゴンを描く場所は、かなり高速です。

+0

hanks;私は、グラフィックスハードウェア上でピクセルを突き刺すのではなく、浮動小数点配列での加算ブレンドを使用して、それをテクスチャとして描画します。テクスチャ付きポリゴンを使用することによる最大の問題は、FBOへのアクセスやFBOの変更を直接取得することです。時間の経過とともにフェードアウトすることができます。 – damian

2

このような大規模なパーティクルシステムのレンダリング計算をGPUに移動することが最善です。これは、できるだけ早くこのジョブを正確に行うようにハードウェアが最適化されています。

Aaron is right:各パーティクルをスプライトで表します。あなたはSSE2を使ってCPU上で空間上のスプライトの動きを計算することができます(例えば、フレームごとの位置を累積します)。しかし、OpenGLを介してGPU上のすべての加算ブレンドと積算を行います。 (スプライトの追加は十分に簡単です)シェーダ(「プロ」の方法)で行うか、累積バッファにレンダリングして戻すか、単にCPUにスプライトの束を生成するだけで、トレイルをラスタライザに投げてください。

関連する問題