XNA - проблема производительности выбраковки
Этот метод, который рисует мои плитки, кажется довольно медленным, я не уверен точно, что не так, он верит, что мой метод отбраковки не работает и рисует материал за кадром, но я не полностью уверен. Вот:
// 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 ответ
Попробуйте изменить SpriteBatch.Begin на защищенный и объединить все плитки в одну текстуру.
См. Этот вопрос GameDev для получения информации о том, почему deferred, скорее всего, самый быстрый вариант для вас.
Также поймите, что каждый раз, когда вы рисуете новую текстуру, вы должны вынимать старую из 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);
}
}