0

我不知道我在哪里犯错。我在 youtube 上看到了一些演示,它们实时渲染了大约 100 万个粒子(令人惊叹)。但是,当我只想渲染 2500 个小正方形(Texture2D)时,系统就会崩溃——一切都变得缓慢而生涩。在这里,我按原样呈现循环 - 简单的平铺到平铺渲染。网格为 50 x 50,Texture2D Tile 只有 5x5 大 png 图像和 GridNode 3x3。我是 XNA 的新手,所以请不要打我太多... :-)

谁能告诉我,我做错了什么?

非常感谢

for (x = FromCol; x <= ToCol; x++)
            {
                for (y = FromRow; y <= ToRow; y++)
                {
                    Color aColor = new Color((byte)(x * 20), (byte)(y * 15), (byte)(60 + x));

                    CoordX = DisplayArea.Left + (int)Math.Round((x - FromCol) * zoomWidth - (restCol * ZoomingX) - indent_x);//
                    CoordY = DisplayArea.Top + (int)Math.Round((y - FromRow) * zoomHeight - (restRow * ZoomingY) - indent_y);//

                    dodraw = ((CoordX) > DisplayArea.Left) & (CoordX < (DisplayArea.Right - indent_x)) & ((CoordY) > DisplayArea.Top) & (CoordY < (DisplayArea.Bottom-indent_y));


                    l = CoordX + indent_x;
                    t = CoordY + indent_y; 
                    r = l + (int)Math.Round(ColWidth * ZoomingX);
                    b = t + (int)Math.Round(RowHeight * ZoomingY);

                    if (l < DisplayArea.Left) l = DisplayArea.Left;
                    if (t < DisplayArea.Top)  t = DisplayArea.Top;
                    if (r > (DisplayArea.Left + DisplayArea.Width)) r = DisplayArea.Left + DisplayArea.Width;
                    if (b > DisplayArea.Top + DisplayArea.Height) b = DisplayArea.Top + DisplayArea.Height;

                    SpriteBatch.Draw(Tile, new Rectangle(l, t, r - l, b - t), aColor);

                    if (dodraw) SpriteBatch.Draw(GridNode, new Vector2(CoordX, CoordY), Color.White);
                }
4

2 回答 2

4

赛斯的回答几乎是正确的。当你向 GPU 发送一个批次时——当你绘制一些东西时——它会占用相对大量的 CPU 时间。实际上,您仅限于每帧发送几百个批次 - 您的“批次限制”。

SpriteBatch通过将尽可能多的精灵打包到一个批次中来解决这个问题。它实际上只在End()[1]中绘制东西。但是,如果它们共享一个纹理,它只能将精灵批处理在一起。

您在这里几乎遇到了最坏的情况:看起来您正在交错纹理,强制SpriteBatch为每个精灵启动一个新批次。

所以首先要做的是检查这是否真的是你的问题的原因。一个快速的方法是设置SpriteSortMode.Texture(in SpriteBatch.Begin) 并查看性能是否有所提高。这将完全符合听起来的样子——在绘制顺序中按纹理对精灵进行分组,从而减少纹理更改的数量,从而减少批次。

然后你就可以开始着手解决这个问题了。如果您可以继续使用SpriteSortMode.Texture,那很好。您还可以将循环转换为两个单独的循环。SpriteBatch或者您可以在一个循环中填充两个单独的对象 -SpriteBatch基本上充当缓冲区[1]

或者,如果您真的需要交错的这些纹理,则使用sprite sheet

最后,我在 GameDev 网站上写了这个相当流行的答案,其中更详细地介绍了这个主题。


[1] 使用时除外SpriteSortMode.Immediate

于 2012-09-01T08:34:58.900 回答
1

您正在对 Draw 方法进行 2500 次调用。每次告诉 CPU 向 GPU 发出指令时,都会产生巨大的处理开销。这就是为什么你的表现比在一次绘制调用中绘制一百万个粒子的游戏更差的原因。

一次绘制 1000 个三角形比绘制 1 个三角形 1000 次要快得多。

于 2012-09-01T03:40:33.453 回答