XNA 4.0 用のグラフィック エンジンの作業を行っていますが、解決策が見つからない問題に遭遇しました。現在、シェーダーを使用して光の効果を実装しようとしています。グラフィック エンジンもパーティクル エンジンで構成されているため、少なくともパフォーマンスを考慮することは非常に重要です。これら2つの組み合わせが問題を引き起こします。
まず第一に、私は多くの読書と調査を行ってきましたが、私が理解していることから、ドローコールが少ないほどパフォーマンスが向上します。ドロー コールとは、スプライト バッチが実際のジオメトリとテクスチャを GPU に送信するタイミングを意味します。したがって、私は1 つのバッチ内でできるだけ多くを描画しようとしています。
そして今、問題が発生します。エンジンの描画メソッドには 2 つのオーバーロードがあります。
public static void Draw(Texture texture)
{
// Call spriteBatch.Draw(...);
}
public static void Draw(Light light)
{
// Call spriteBatch.Draw(...);
}
最初のオーバーロードは、デフォルト シェーダーを使用して通常のテクスチャを描画するだけです。2 番目のオーバーロードは、別のシェーダーを使用するライトを描画します。私がやりたいことは次のとおりです。
public static void Draw(Texture texture)
{
// Use default shader
// Call spriteBatch.Draw(...);
}
public static void Draw(Light light)
{
// Use light shader
// Call spriteBatch.Draw(...);
}
ただし、SpriteBatch は一度に複数のシェーダーをサポートしていないため、代わりにエフェクト パスを使用してこれを実行しようとしました。
public static void Draw(Texture texture)
{
effect.CurrentTechnique.Passes[0].Apply();
// Call spriteBatch.Draw(...);
}
public static void Draw(Light light)
{
effect.CurrentTechnique.Passes[1].Apply();
// Call spriteBatch.Draw(...);
}
spriteBatch.Draw() が呼び出されたときにシェーダーが使用されず、代わりに spriteBatch.End() が呼び出されたときに、これも機能しませんでした。したがって、上記のコードは、最後に適用したパスですべてをレンダリングしました。
私の 3 番目の試みは、2 つの SpriteBatches を使用することでした。
public static void Begin()
{
spriteBatchColor.Begin([...], null); // Default shader.
spriteBatchLight.Begin([...], effect); // Light shader.
}
public static void Draw(Texture texture)
{
// Call spriteBatchColor.Draw(...);
}
public static void Draw(Light light)
{
// Call spriteBatchLight.Draw(...);
}
public static void End()
{
spriteBatchColor.End();
spriteBatchLight.End();
}
これは実際には機能しましたが、レイヤーの深さが完全に台無しになりました。これは、spriteBatchLight.End() が最後に呼び出されるため、それほど奇妙ではなく、spriteBatchColor が描画したすべてのものの上に常に描画されます。
SpriteSortMode を SpriteSortMode.Immediate に設定できることはわかっていますが、このモードではすべてが直接描画されるため、パフォーマンスが大幅に低下します。この場合、パフォーマンスが非常に重要であるため、GPU への描画呼び出しをできるだけ少なくして最適化したいため、SpriteSortMode.Immediate はオプションではありません。
だから、私の質問は:
1 つのバッチ内で2 つの異なるエフェクト/テクニック/パスを使用する方法はありますか? または、2 つの異なる SpriteBatches を使用して、最終的な描画を行うときにそれらを組み合わせて、レイヤーの深さが台無しにならないようにする方法はありますか?