我使用.NET Framework 4在C#中编程,目的是使用XNA制作基于磁贴的游戏。我有一个大的纹理(256像素乘4096像素)。请记住,这是一个基于图块的游戏,因此这个纹理非常庞大,因为它包含许多图块,每个图块都是32像素×32像素。我认为专家肯定会知道基于磁贴的游戏是什么样的。方向是正交的(如棋盘),而不是等距的。
在Game.Draw()方法中,我有两个选择,其中一个选项比另一个选择效率高得多。
选择/方法#1:
半伪代码:
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
}
}
}
标题:因此,有效地,第一种方法是多次引用一个大纹理,每次使用这个大纹理的小矩形来绘制适当的平铺图像。
选择/方法#2 :
半伪代码:
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
}
}
}
标题:所以,实际上,第二种方法是多次绘制许多小纹理。
问题:哪种方法和原因?我个人认为使用第一种方法效率会高得多。如果你考虑一下这对地图中的tile数组意味着什么(想想一个有2000 x 2000个tile的大地图,让我们说),每个Tile对象只需要包含2个整数,对于源的X和Y位置一个大纹理中的矩形 - 8个字节。但是,如果使用方法#2,则地图的tile数组中的每个Tile对象都必须存储32by32纹理 - 一个图像 - 必须为RGBA像素32分配32次内存 - 每个tile为4096字节然后?那么,哪种方法和原因?首要任务是速度,然后是内存负载,然后是效率或专家认为的任何内容。
答案 0 :(得分:9)
第一种方法将更快 !它与CPU端数据结构也没有任何关系。在任何一种情况下你都可能得到几个字节 - 所以没关系。
第一种方法会更快的原因是因为GPU的工作方式。简单地说,你发送带有顶点/三角形列表的GPU绘图命令。这些顶点具有各种数据(位置,颜色,纹理坐标等)。至关重要的是,它们无法指定纹理 - 绘制三角形的纹理必须在绘制之前在图形设备上指定,用于整个三角形列表。
SpriteBatch所做的是自动将精灵一起批处理,尽可能减少纹理交换,从而绘制发送的命令。这就是为什么它有一个按纹理排序的选项。这也是源矩形参数存在的原因 - 允许使用精灵表 - 因此可以绘制更多的精灵而无需更改纹理。
(事实上,你发送给GPU的绘制命令 - 即使你没有使用SpritBatch - 被称为“批量”。当你发送太多时你会变成“批量限制”。很容易变成批处理有限的 - 几百个批次是对限制的非常粗略的估计。)
答案 1 :(得分:2)
同意。从更快的速度拉出的纹理越少,因为它最大限度地减少了GPU上的状态变化。
为了使速度更快,请注意大多数图块不会在帧之间发生变化。因此,将它们全部绘制到一个屏幕大小的渲染目标,然后在后续帧上绘制,只需重新绘制一个绘制调用的单个纹理。添加顶部更改的图块。