[C#][XNA] Draw() 20,000 32 by 32 Textures or 1 Large Texture 20,000 Times
- by Rudi
The title may be confusing - sorry about that, it's a poor summary.
Here's my dilemma.
I'm programming in C# using the .NET Framework 4, and aiming to make a tile-based game with XNA. I have one large texture (256 pixels by 4096 pixels). Remember this is a tile-based game, so this texture is so massive only because it contains many tiles, which are each 32 pixels by 32 pixels. I think the experts will definitely know what a tile-based game is like. The orientation is orthogonal (like a chess board), not isometric.
In the Game.Draw() method, I have two choices, one of which will be incredibly more efficient than the other.
Choice/Method #1:
Semi-Pseudocode:
public void Draw()
{
// map tiles are drawn left-to-right, top-to-bottom
for (int x = 0; x < mapWidth; x++)
{
for (int y = 0; y < mapHeight; y++)
{
SpriteBatch.Draw(
MyLargeTexture, // One large 256 x 4096 texture
new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok
new Rectangle(x, y, 32, 32), // Notice the source rectangle 'cuts out' 32 by 32 squares from the texture corresponding to the loop
Color.White); // No tint - ignore this, its ok
}
}
}
Caption: So, effectively, the first method is referencing one large texture many many times, each time using a small rectangle of this large texture to draw the appropriate tile image.
Choice/Method #2:
Semi-Pseudocode:
public void Draw()
{
// map tiles are drawn left-to-right, top-to-bottom
for (int x = 0; x < mapWidth; x++)
{
for (int y = 0; y < mapHeight; y++)
{
Texture2D tileTexture = map.GetTileTexture(x, y); // Getting a small 32 by 32 texture (different each iteration of the loop)
SpriteBatch.Draw(
tileTexture,
new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok
new Rectangle(0, 0, tileTexture.Width, tileTexture.Height), // Notice the source rectangle uses the entire texture, because the entire texture IS 32 by 32
Color.White); // No tint - ignore this, its ok
}
}
}
Caption: So, effectively, the second method is drawing many small textures many times.
The Question: Which method and why? Personally, I would think it would be incredibly more efficient to use the first method. If you think about what that means for the tile array in a map (think of a large map with 2000 by 2000 tiles, let's say), each Tile object would only have to contain 2 integers, for the X and Y positions of the source rectangle in the one large texture - 8 bytes. If you use method #2, however, each Tile object in the tile array of the map would have to store a 32by32 Texture - an image - which has to allocate memory for the R G B A pixels 32 by 32 times - is that 4096 bytes per tile then? So, which method and why? First priority is speed, then memory-load, then efficiency or whatever you experts believe.