2012-03-28 14 views
3

現在、私のゲームのトレイルエフェクトとして、5フレームごとに、スプライトの半透明テクスチャコピーがトレールリスト<に追加されています。C#XNA 2Dトレイルエフェクトの最適化

これらの軌跡のアルファ値は、フレームごとにデクリメントされ、描画関数がリストを反復して各テクスチャを描画します。 0アルファをヒットしたら、リスト<>から削除されます。

結果は、移動するエンティティの後ろに小さなトレイル効果があります。問題は約100以上のエンティティで発生し、フレームレートが大幅に低下し始めます。

すべてのトレイルテクスチャは同じスプライトシートから来るので、バッチ処理の問題だとは思わない。私はコードをプロファイリングし、CPU強度はFPSドロップスパイクの間に低くなりますが、通常のFPSであるため、GPUの制限を意味すると仮定します。

この効果をより効率的に達成する方法はありますか?使用

相続人は、一般的なコードのイム:私は注意しなければならないと思います

// fade alpha 
m_alpha -= (int)(gameTime.ElapsedGameTime.TotalMilliseconds/10.0f); 

// draw 
if (m_alpha > 0) { 
    // p is used to alter RGB of the trails color (m_tint) depending on alpha value 
    float p = (float)m_alpha/255.0f; 
    Color blend = new Color((int)(m_tint.R*p), (int)(m_tint.G*p), (int)(m_tint.B*p), m_alpha);    
    // draw texture to sprite batch 
    Globals.spriteBatch.Draw(m_texture, getOrigin(), m_rectangle, blend, getAngle(), new Vector2(m_rectangle.Width/2, m_rectangle.Height/2), m_scale, SpriteEffects.None, 0.0f);     
} else { 
     // flag to remove from List<> 
     m_isDone = true;    
} 

、トレイルクラスに与えられたm_textureは、すべてのコースで共有グローバルテクスチャへの参照です。各トレイルのハードコピーを作成しています。

EDIT:SpriteBatch.Draw呼び出しをコメントアウトするだけで、何百ものオブジェクトに対して1つのフレームごとに新しいトレイルを割り当てても、フレームにはドロップがありません。もっと良い方法が必要ですこの。

+0

トレイルエフェクトを無効/ – MichaelHouse

+0

トレールエフェクトを削除すると、フレームレートドロップが完全に修正されます。私は、GPUが処理するスプライトをあまりにも多く追加しているだけであることを確信しています。 – kbirk

+2

いくつかのコードを投稿する必要があります。明らかにこのようなことが可能であり、パーティクルシステムは100粒子以上が容易に消えてしまいます。 – MichaelHouse

答えて

3

通常は、すべてのフレームで画面を消去するのではなく、現在のフレームを描画する前に透明な画面サイズの矩形を描画するだけです。したがって、新しいフレームが完全に「クリア」および「明るい」の間に、前のフレームは「淡色」または「色がぼやけている」。これが繰り返されると、以前のすべてのフレームからトレイルが生成されます。トレイルは決してクリアされず、むしろ「淡色」になります。

この手法は非常に効率的で、有名なFlurryスクリーンセーバー(www.youtube.com/watch?v=pKPEivA8x4g)で使用されています。

トレイルを長くするには、画面のクリアに使用する四角形の透明度を上げるだけです。さもなければ、あなたはそれをもっと不透明にして、トレイルを短くします。ただし、長方形をあまりにも透明にすると軌跡が長くなり過ぎると、アルファブレンディングのために長い軌跡を残す危険性があり、長い時間が経過しても完全に消去されない可能性があります。 Flurryのスクリーンセーバーには、この種のアーティファクトがありますが、それを補う方法があります。

状況によっては、この手法を適用する必要があります。たとえば、特定のオブジェクトが軌跡を残し、他のオブジェクトは軌跡を生成しないようにするいくつかの描画レイヤーが必要な場合があります。

この手法は、現在の手法としてスプライトを何千回も再描画しようとするよりも、長いトレールで効率的です。一方

、私はあなたのコード内のボトルネックは次の行だと思う:

Globals.spriteBatch.Draw(m_texture, getOrigin(), m_rectangle, blend, getAngle(), new Vector2(m_rectangle.Width/2, m_rectangle.Height/2), m_scale, SpriteEffects.None, 0.0f); 

ドローのようなGPUコール(数千人を持つことは非効率的です)。バッファ内にポリゴンのリストがあって、各ポリゴンが正しい位置にあり、そのポリゴンに格納されている透明度情報があれば、より効率的です。次に、Draw()を呼び出すと、正しいテクスチャと透明度を持つすべてのポリゴンをレンダリングできます。申し訳ありませんが、私はあなたのためのコードを提供することはできませんが、あなたのアプローチを続行したい場合、これはあなたが向いている方向かもしれません。要するに、あなたのGPUは確実に一度に何百万ものポリゴンを描画することができますが、何度もDraw()を呼び出すことはできません...

+0

ありがとう、ありがとう、これは私が望んでいた答えです。 – kbirk

+0

@Pondwater:聞いてよかった!どういたしまして! –

+0

これらのアーティファクトはアルファブレンディングによって残されていますが、それを防ぐ/回避するにはどうすればいいでしょうか? – kbirk