2012-12-11 20 views
13

XNA 3.1で何かを作っているので、ピクセルシェーダを介して適用される別々のエフェクトがたくさんあります。これらは、特殊攻撃、環境などのあらゆる種類のソースから来ています。私が抱えている問題は、フレームレートが大幅に低下していることに気付いていることです。複数のピクセルシェーダを効率的に組み合わせる

現時点では、シーン全体をRenderTarget2Dに描画しています。次に、すべてのエフェクトを適用します。私は(IDが実行時にパラメータを変更するために使用されている)の影響とそのIDを含むSortedDictionaryを格納し、私はそれを反復し、他の後、各エフェクト1を適用しています:

foreach(KeyValuePair<Ref<int>,Effect> p in renderEffects) 
{ 
    Effect r = p.Value; 
    g.SetRenderTarget(0, MainGame.MainRenderTarget); 
    //Change RenderTarget to allow code to grab existing texture in the same draw area. 
    levelDraw = MainGame.LevelRenderTarget.GetTexture(); 
    //Change back to draw back to this texture, allowing render effects to be layered. 
    g.SetRenderTarget(0, MainGame.LevelRenderTarget); 

    MainGame.StartDraw(MainGame.GameBatch); 
    //Starts the sprite batch and sets some parameters 
    r.Begin(); 
    r.CurrentTechnique.Passes[0].Begin(); 
    MainGame.GameBatch.Draw(levelDraw, new Rectangle(0, 0, levelDraw.Width, levelDraw.Height), Color.White); 
    r.CurrentTechnique.Passes[0].End(); 
    r.End(); 
    MainGame.GameBatch.End(); 
} 

は今、これが顕著生成

フレームは3つのエフェクトだけ重ねるとドロップし、10を適用すると60FPSから16FPSに落ちますが、これは当然受け入れられません。私はこれを行うより効率的な方法があるのだろうかと思います。私は1つのテクスチャしか持たないことを考慮して、エフェクトを1つのファイルに結合し、テクスチャを取り込まずに複数のパスを実行できると考えました。しかし、これが可能かどうかはわかりません。

私はそれをやっているよりも良い方法がなければならないと思うが、これを行うにはどうすればよいのか正確にはわからない。

+3

で見たいと思うかもしれません。 「[質問には「タイトル内に「タグ」を含める必要がありますか」(http://meta.stackexchange.com/questions/19190/)」を参照してください。コンセンサスは「いいえ、そうすべきではありません」です。 –

+0

ありがとう。私はタグを見なければならないのではなく、彼らが一目で助けてくれるかどうかを知ることができるようにそれらを含める傾向があります。 – Hoeloe

+2

タグには、文字化けしたタイトルよりも優れた仕組みが含まれています。 「お気に入りのタグ」を設定すると、それらのタグを含むメッセージが強調表示されます。これらのタグを含むメッセージを非表示にする「無視されたタグ」があります。 –

答えて

1

描画時にすべてを陰影付けしていますか?シェーダが計算量が多い場合、まずZバッファをztesting/writeするだけです(カラーバッファの書き込みはオフです)。また、スクリーンを「深く塗りつぶす」ために、簡単にシンプルなシェーダを使用します。

つまり、すべての不透明なオブジェクトを、最初のパスで深度バッファのみを更新してレンダリングします。

2回目のパスでは、シェーダーをオンにします(深度の書き込みをオフにします。既にそこにある値と同じ値を書き戻すために帯域幅を使用する必要はありません)。これにより、過剰描画されたピクセルの不要な作業はすべてマスクされます。これらのピクセルは深度テストに直ちに失敗するためです。

編集:今私はOPがフルスクリーン効果をしていることを実感します。シーンはレンダリングしません。

+0

シェーダを1つのテクスチャに適用するだけなので、各ピクセルが各パスで一度だけ描画され、深度バッファでピクセルがオーバードローされることはないため、デプスバッファに問題はありません。 – Hoeloe

+0

私はあなたが何を意味するのかを見ると、一連のフルスクリーン効果を適用するために巨大な四角形を「掲示板」に貼っているだけで、パフォーマンスがボトルネックになっています。 – doug65536

+0

状態の変化を最小限に抑えるためにエフェクトループをソートすることはできますか?一般に、コストの削減:シェーダプログラム、テクスチャバインディング、バッファバインディング、その他。おそらく、パスの順序を変更して状態の変化を最小限に抑えることで、状態の変化を避けることができます。頂点バッファとテクスチャは、より大きなテクスチャ/より大きな頂点バッファにタイル張りすることができ、いくつかの状態が常に変化するのを防ぐことができます。 – doug65536

2

スニペット内のメソッドは、エフェクトごとにテクスチャグラブとフルスクリーン描画を実行しているため、CPUとGPU間のメモリ帯域幅に何が起きているのかを強調しているため、非常に遅い可能性がありますシェーダーの内部あなたの記事で提案したように、読み書きループを何度も繰り返し実行するのではなく、複数の操作を含むシェーダのセットを作成する必要があります。高価なシェーダは通常、複数のread-write-repeatsシンプルなシェーダの

あなたは私があなたのタイトルを編集したShawn Hargreaves article on shader fragments in HLSLTim Jones's code for doing this in XNA

+0

Tim Jonesのコードは、XNA 4と同じように、私にとって役に立たないのですが、私は3.1を使っています。しかし、これらの記事をリンクしていただきありがとうございます。 – Hoeloe

+0

あなたの問題のサイズでは、あなたは手動でコンビネーションを行う方が良いかもしれません - おそらく、効果を積み重ねることによって視覚的に解読が難しくなります。つまり、複雑なマルチエフェクトバージョンは、見た目を損なう。 – theodox

+0

これは考えています。パーサーとコンパイラを作成して、HLSLシェーダのリストを特定のパラメータとともに取得し、すべてを1つのファイルにプッシュすることを検討しています。コードを文字列として読み込み、コードを文字列形式からバイト配列に変換し、新しいエフェクトファイルに書き込むことができます。私はこれがうまくいくかどうか、それが良いものになるかどうかはわかりませんが、試してみる価値があるかもしれません。私はファイルから元のコードを文字列として取得する方法がわかりません... – Hoeloe

関連する問題