【问题标题】:XNA - Culling Performance IssueXNA - 剔除性能问题
【发布时间】:2012-03-26 17:52:02
【问题描述】:

这种绘制瓷砖的方法似乎很慢,我不确定到底出了什么问题,它相信我的剔除方法不起作用并且在屏幕外绘制东西,但我不完全确定。这里是:

        // Calculate the visible range of tiles.
        int left = (int)Math.Floor(cameraPosition.X / 16);
        int right = left + spriteBatch.GraphicsDevice.Viewport.Width / 16;
        right = Math.Min(right, Width) + 1; // Width -1 originally - didn't look good as tiles drawn on screen
        if (right > tiles.GetUpperBound(0))
            right = tiles.GetUpperBound(0) + 1; // adding 1 to get the last right tile drawn

        int top = (int)Math.Floor(cameraPosition.Y / 16);
        int bottom = left + spriteBatch.GraphicsDevice.Viewport.Height/ 16;
        bottom = Math.Min(bottom, Height) + 1; // Height -1 originally - didn't look good as tiles drawn on screen
        if (bottom > tiles.GetUpperBound(1))
            bottom = tiles.GetUpperBound(1) + 1; // adding 1 to get the last bottom tile drawn

        // For each tile position
        for (int y = top; y < bottom; ++y)
        {
            for (int x = left; x < right; ++x)
            {
                // If there is a visible tile in that position, draw it
                if (tiles[x, y].BlockType.Name != "Blank")
                {
                    Texture2D texture = tileContent["DirtBlock_" + getTileSetType(tiles,x,y)];
                    spriteBatch.Draw(texture, new Vector2(x * 16, y * 16), Color.White);
                    if (isMinimap)
                    spriteBatch.Draw(pixel, new Vector2(30+x, 30+y), Color.White);
                }

            }
        }

GetTileSetTypes 是一个函数,用于获取它周围的瓦片,用于不同的纹理,如 DirtBlock_North、DirtBlock_Center 等。

平铺内容只是我的块纹理的一个类。

【问题讨论】:

  • 您如何确定这是运行缓慢的代码?通常每帧绘制多少个图块?你在哪里调用 SpriteBatch.Begin 和 .End?
  • 这无疑是一个 SpriteBatch 问题,当我只跳过瓷砖的绘制,但加载碰撞等时,我获得了 30 fps。这让我觉得顶部的剔除方法仍然是在屏幕外绘制东西,切换图形是个问题。
  • 您可能应该使用分析器,以便准确找出导致其变慢的原因。例如:SlimTune; code.google.com/p/slimtune

标签: c# performance xna culling spritebatch


【解决方案1】:

尝试将 SpriteBatch.Begin 更改为延迟并将所有图块组合到一个纹理上。

请参阅thisGameDev 问题,了解为什么延迟最有可能是您最快的选择。

还要意识到,每次绘制新纹理时,都必须将旧纹理从 GPU 中取出并放入新纹理。此过程称为纹理交换,通常不是问题,但您要交换纹理两次每个磁贴可能会显着影响性能。

这可以通过将多个精灵组合到一个纹理上并使用源矩形参数来解决。这允许您在没有纹理交换的情况下绘制多个精灵。为此有一些 OSS 库。 Sprite Sheet Packer 是我个人的最爱。

不幸的是,没有项目和分析器,我只是在猜测;然而,这是我所知道的渲染瓷砖地图的两个最大问题。从这里我真的看不出有什么问题。下面是我用来绘制瓦片地图的代码,您可以看到它与您的非常相似。

如果一切都失败了,我建议使用分析器来确定哪些位运行缓慢。

        //Init the holder
        _holder = new Rectangle(0, 0, TileWidth, TileHeight);

        //Figure out the min and max tile indices to draw
        var minX = Math.Max((int)Math.Floor((float)worldArea.Left / TileWidth), 0);
        var maxX = Math.Min((int)Math.Ceiling((float)worldArea.Right / TileWidth), Width);

        var minY = Math.Max((int)Math.Floor((float)worldArea.Top / TileHeight), 0);
        var maxY = Math.Min((int)Math.Ceiling((float)worldArea.Bottom / TileHeight), Height);

        for (var y = minY; y < maxY; y++) {
            for (var x = minX; x < maxX; x++) {

                _holder.X = x * TileWidth;
                _holder.Y = y * TileHeight;

                var t = tileLayer[y * Width + x];
                spriteBatch.Draw(
                    t.Texture,
                     _holder, 
                    t.SourceRectangle,
                    Color.White, 
                    0,
                    Vector2.Zero,
                    t.SpriteEffects, 
                    0);
            }
        }

【讨论】:

  • 虽然精灵表很可能是要走的路,但 OP 可以尝试SpriteSortMode.Texture 而不仅仅是延迟。这将按纹理对所有内容进行排序,从而最大限度地减少纹理切换。 msdn.microsoft.com/en-us/library/…
  • 我很快就会实现 SpriteSheets,但我只尝试了一种纹理而不是不同的纹理,而且它只有几帧,所以我知道这不是主要原因。
  • 谢谢你,这是一个很好的观点,我没有建议 SpriteSortMode.Texture 因为如果他有物体或风景,“这可以提高绘制均匀深度的非重叠精灵时的性能”不成立.它迫使他使用单独的 spritebatch 来渲染瓷砖,这确实有助于瓷砖地图的渲染时间,但在考虑到 NPC 和风景后会损害整体 fps。
  • 我有一个单独的 spritbatch 用于绘制背景。另外,我在做 GetUpperBound 对吗?对于数组[,]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多