XNA - проблема производительности выбраковки - PullRequest
1 голос
/ 26 марта 2012

Этот метод, который рисует мои плитки, кажется довольно медленным, я не уверен точно, что не так, он верит, что мой метод отбраковки не работает и рисует материал за кадром, но я не уверен в этом.Вот оно:

        // 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 и т. Д.

Содержимое плитки - это просто класс с моимблок текстур.

1 Ответ

1 голос
/ 26 марта 2012

Попробуйте изменить SpriteBatch.Begin на защищенный и объединить все плитки в одну текстуру.

См. этот вопрос GameDev для получения информации о том, почему deferred, скорее всего, самый быстрый вариант для вас.

Также поймите, что каждый раз, когда вы рисуете новую текстуру, вы должны вынимать старую из GPU и вставлять новую. Этот процесс называется свопинг текстур и обычно не является проблемой, но вы меняете текстуру дважды за плитку, что может заметно повлиять на производительность.

Это можно исправить, объединив несколько спрайтов в одну текстуру и используя аргумент исходного прямоугольника. Это позволяет вам рисовать несколько спрайтов без замены текстуры. Для этого есть несколько библиотек OSS. Упаковщик листов спрайта - мой личный фаворит.

К сожалению, без проекта и профилировщика, я просто догадываюсь; Тем не менее, это две самые большие ошибки для рендеринга тайловых карт, которые я знаю. Я действительно не вижу ничего плохого отсюда. Ниже приведен код, который я использую для рисования своих карт тайлов, и, как вы видите, он очень похож на ваш.

Если ничего не помогает, я бы предложил использовать профилировщик, чтобы выяснить, какие биты работают медленно.

        //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);
            }
        }
...