gpt4 book ai didi

c# - Draw() 20,000 32 x 32 纹理或 1 个大纹理 20,000 次

转载 作者:太空狗 更新时间:2023-10-29 22:24:31 27 4
gpt4 key购买 nike

我正在使用 .NET Framework 4 使用 C# 进行编程,目标是使用 XNA 制作基于图 block 的游戏。我有一个大纹理(256 像素 x 4096 像素)。请记住,这是一个基于图 block 的游戏,所以这个纹理如此巨大只是因为它包含许多图 block ,每个图 block 为 32 x 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
}
}
}

说明:因此,实际上,第一种方法是多次引用一个大纹理,每次都使用这个大纹理的一个小矩形来绘制适当的图 block 图像。

选择/方法#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
}
}
}

说明:所以,实际上,第二种方法是多次绘制许多小纹理。

问题:哪种方法以及为什么?就我个人而言,我认为使用第一种方法会更加高效。如果您考虑这对 map 中的图 block 数组意味着什么(假设有 2000 x 2000 个图 block 的大 map ),每个 Tile 对象只需要包含 2 个整数,用于源的 X 和 Y 位置一个大纹理中的矩形 - 8 字节。但是,如果您使用方法 #2,则 map 的 tile 数组中的每个 Tile 对象都必须存储一个 32by32 的纹理 - 图像 - 必须为 R G B A 像素分配内存 32 x 32 倍 - 每个图 block 4096 字节然后?那么,哪种方法以及为什么?首要任务是速度,然后是内存负载,然后是效率或您专家认为的任何东西。

最佳答案

第一种方法会很多更快!它也与您的 CPU 端数据结构没有任何关系。在任何一种情况下,您都可能减少到几个字节 - 所以这无关紧要。

第一种方法会更快的原因是 GPU 的工作方式。简而言之,您发送带有顶点/三角形列表的 GPU 绘制命令。这些顶点有各种数据(位置、颜色、纹理坐标等)。至关重要的是,它们无法指定纹理 - 绘制三角形所用的纹理必须在绘制之前在图形设备上指定,对于整个三角形列表。

SpriteBatch 所做的是在可能的情况下自动将 Sprite 批处理在一起,从而最大限度地减少纹理交换,从而减少发送的绘制命令。这就是为什么它有一个按纹理排序的选项。这也是存在 source-rectangle 参数的原因 - 允许使用 sprite 表 - 因此可以绘制更多的 sprite 而无需更改纹理。

(事实上,您发送到 GPU 的绘制命令 - 即使您没有使用 SpritBatch - 也被称为“批处理”。当您发送太多时,您会变成“批处理受限”。成为批处理非常容易有限 - 几百批是对限制的非常粗略的估计。)

关于c# - Draw() 20,000 32 x 32 纹理或 1 个大纹理 20,000 次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4543152/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com