0

私はXNAで「落下砂」ゲームに取り組んでいます。もちろん、それはたくさんのピクセルを描かなければならないことを意味します!アルゴリズムをテストするためだけに、ピクセルごとに透明な青色を使用して、問題なく開始されました。フレームレート(安定した60 FPS)を失う前に、画面に約100,000ピクセルを描画することができました。これは、必要以上でした。しかし、最終的に別の色のピクセル(青と赤)を追加し、他の変更を加えなかった場合、FPSは指数関数的に低下し、FPSが約10に低下する前に、約10,000ピクセルしか画面に描画できませんでした。スプライトバッチが自動的にピクセルを並べ替えてブレンドするため、私は完全に間違っている可能性があります。何か別のことを考えている場合はお知らせください。2つの色を混ぜ合わせるという行為は私がスピードを失っているところだと思います。では、どうすればスプライトバッチのメソッドを回避できますか?それとも私は完全にベースから外れていますか?

SpriteSortModeとBlendModeをいじってみましたが、スプライトのバッチ呼び出しごとに色付きのピクセルのように描画するだけでしたが、今のところ運がありません。

また、画面に描画しているピクセルは、そもそも同じ座標になることはないので、ブレンドなどは必要ありません。

    //Game Draw Method
    protected override void Draw(GameTime gameTime)
    {                      
        stopWatch.Start();          

        GraphicsDevice.Clear(Color.Black);

        spriteBatch.Begin();

        //backgroundSprite.Draw(spriteBatch);

        terrainSprite.Draw(spriteBatch);

        resourceMap.Draw(spriteBatch, spriteFont);            

        frameCounter++;

        string fps = string.Format("fps: {0}", frameRate);

        int totalint = 0;

        for (int i = 0; i < resourceMap.activeCoordinates.Count; i++)
        {
            totalint += resourceMap.activeCoordinates[i].Count;
        }

        string total = string.Format("resource count: {0}", totalint);

        spriteBatch.DrawString(spriteFont, fps, new Vector2(33, 33), Color.White);
        spriteBatch.DrawString(spriteFont, total, new Vector2(33, 45), Color.White);
        spriteBatch.DrawString(spriteFont, totalTime, new Vector2(33, 17),    Color.White);            
        spriteBatch.DrawString(spriteFont, totalTime, new Vector2(33, 17),  Color.White); 


        spriteBatch.End();
        stopWatch.Stop();
        totalTime = "Draw Time:     " + stopWatch.Elapsed;
        stopWatch = new Stopwatch();


        base.Draw(gameTime);
    }

    //resourceMap.Draw(SpriteBatch spriteBatch, SpriteFont font) from Game Draw
    public void Draw(SpriteBatch spriteBatch, SpriteFont font)
    {
        //spriteBatch.End();
        //this was originally one for loop to draw all pixels, but was separated to draw each different color pixel after discovering performance issue
        for (int c = 0; c < activeCoordinates.Count(); c++)
        {
            //spriteBatch.Begin();
            for (int i = 0; i < activeCoordinates[c].Count; i++)
            {
                mapArray[(int)activeCoordinates[c][i].X][(int)activeCoordinates[c][i].Y].Draw(spriteBatch);
            }
            //spriteBatch.End();
        }
        //spriteBatch.Begin();
        spriteBatch.DrawString(font, timeInMilli, new Vector2(33, 0), Color.White);
    }

繰り返しになりますが、コードに加えられた唯一の変更は、描画されるピクセルのリストに異なる色を追加することでした。そのため、追加の色を追加するまで、ここのコードはうまく機能していました(約60fpsで100,000ピクセルが描画されました)。

助けてくれてありがとう!

4

1 に答える 1

1

わかりました。できる限り最善の回答を提供しますが、投稿したコードの量によって制限されます。まず、パフォーマンスに影響を与えるさまざまな要因の概要について、この回答を紹介します。

発生する可能性のある問題はSpriteBatch、開始するバッチが多すぎることです。テクスチャを変更するたびにバッチを開始する必要があります。ピクセルごとに異なるテクスチャを使用していて、ランダムな順序で描画しているように見えます。

SpriteBatch(with )内のテクスチャによる並べ替えは、SpriteSortMode.Textureそれ自体がコストのかかる操作になる可能性があります。似たようなテクスチャのスプライトをグループ化するための独自のコードは、遅いか正しくない可能性がありますが、指定したコードではわかりません。

多くのテクスチャを使用するのではなく、単一の白いテクスチャを使用してから、tintパラメータを使用して、各スプライトを目的の色に動的に色付けする方が適切です。その後、すべてのスプライトを1つのバッチで送信できます。

ただし、非常に多くのスプライトの頂点を設定するための多くの処理と同様に、実際にGPUに送信されているデータの量を考慮する必要があります。各スプライトには4つの頂点があり、それぞれに位置、色、テクスチャ座標があります。これは、 1ピクセルあたりなんと96バイトです。そして、すべてをフレームごとにGPUに送信する必要があります。

一方、テクスチャは1ピクセルあたりわずか4バイトです。ですから、もっと速くすべきだというのは当然のことです。

それを遅くする可能性のある2つのことがあります:

まず第一に、あなたがTexture2D.SetData必要以上に電話をかけている場合。を呼び出すたびにSetData、かなりの量のオーバーヘッドが必要になります。ピクセルごとに1回呼び出すと、非常に遅くなります。代わりに、画像全体に対して1回呼び出します。これにより、使用できるほど高速になるはずです。ただし、これを自分で広範囲にテストしたことはありません。

もう1つの可能性は、GPUに深いパイプライン(ハードウェアに依存)があり、フレームN + 1用に更新しようとしているときに、テクスチャを使用してフレームNをレンダリングしていることです。これにより、GPUは新しい変更を受け入れる前にフレームNのレンダリングを終了します。他の非常にGPUを多用することをしている場合、またはグラフィックスドライバーが愚かなことをしている場合を除いて、これが問題になる可能性は低いようですが。

于 2013-02-26T06:53:11.647 に答える