2D图形-为什么使用Spritesheets?


62

我已经看到了许多有关如何从Spritesheet渲染Sprite的示例,但我还没有理解为什么它是2D游戏中处理Sprite的最常见方法。

我在一些演示应用程序中以2d精灵渲染开始,通过将任何给定的精灵类型的每个动画帧作为其自己的纹理进行处理,并将纹理集合存储在字典中。这似乎很适合我,并且非常适合我的工作流程,因为我倾向于将动画制作为gif / mng文件,然后将帧提取到各个png中。

从单张纸而不是从单独的纹理进行渲染是否具有明显的性能优势?借助能够每秒在屏幕上将数百万个多边形绘制到屏幕上的现代硬件,这对于我的仅处理几十个50x100px矩形的2d游戏来说,是否也很重要?

将纹理加载到图形内存中并在XNA中显示的实现细节似乎很抽象。我所知道的是,纹理在加载时已绑定到图形设备,然后在游戏循环中,纹理将成批渲染。因此,我不清楚我的选择是否会影响性能。

我怀疑大多数2d游戏开发人员似乎有一些很好的理由在使用它们,我只是不明白为什么。


不,对于您的50个奇怪的Sprite来说,其实并不重要。但是要失去什么呢?
共产党鸭子

Answers:


69

使用Spritesheets的一个有力论据是可以限制图形卡上可用纹理的数量。因此,您的图形库将不得不不断删除纹理并在GPU上重新分配纹理。一次分配一个大纹理效率更高。

还要考虑纹理大小通常是2的幂。因此,如果您有50x100px的Sprite,则将分配大小为64x128px或更糟的128x128px的纹理。那只是浪费图形内存。最好将所有子画面打包为1024x1024px纹理,这将允许20x10子画面,并且您只会在水平和垂直方向损失24个像素。有时甚至将大小不同的精灵组合成一个巨大的精灵表,以尽可能高效地使用纹理。

附录:使用Sprite-sheets的一个非常重要的原因是减少GPU上的绘图调用次数,这可能会对性能产生显着影响。在其他答案中对此进行了说明,为了完整起见,我添加了此内容,以便获得更多可见性。


1
谢谢,我没有考虑这些要点-您大致知道可用纹理数量的限制吗?我从未见过图形规范中提到的此统计信息-限制是否基本上等于图形RAM的数量?
哥伦布

通常限制是GPU内存,是的。我以为旧卡的纹理数量受到一些限制,但我似乎找不到能证明这一点的参考。
bummzack 2011年

12
即使没有数量限制,用于移动许多小图像的公交车的效率也不如一个(或几个)大车票的效率高。
Mordachai 2011年

5
好点了,但最重要的方面是通过减少绘图调用的次数来最大程度地减少管道停顿。GPU更喜欢少量的大型工作,而不是大量的小型工作。将您所有的精灵放置在少量的大张纸上,这意味着您可以一次设置文本阶段,并一次批绘制许多精灵。Spritebatch为此为您完成。如果您有多个Spritesheet,请确保告诉SpriteBatch按纹理排序
Cubed2D 2011年

添加纹理压缩将使所有的松弛空间变成很小的开销,最重要的是
Joe Plante

36

我想说的是,可以使用在一次绘制调用中渲染多件东西的能力。以字体渲染为例,如果没有Spritesheet,则需要使用单独的纹理交换和绘画调用来渲染每个字符。将它们放入Spritesheet中,您可以通过一次绘制调用来渲染整个句子(只需为角指定不同的UV即可挑选出字体中的差异字符)。当在很多平台上渲染东西的实际开销是进行过多的API调用时,这是一种更有效的渲染方式。

它也可以帮助节省空间,但是首先要取决于您在Spritesheet中打包的内容。


2
+1触及抽奖电话。(有些东西我没有在接受的答案中看到)
Michael Coleman

11

每个抽奖电话都有一定的开销。通过使用精灵表,您可以批处理未使用动画同一帧的事物的绘图(或更笼统地说,使用相同材质的所有事物)可以大大提高性能。对于现代PC而言,这可能并不太重要,具体取决于您的游戏,但对于iPhone来说绝对重要。


2
绝对仍然重要。图形硬件已针对少数详细模型(例如角色)推入大量多边形进行了优化,因为大多数游戏都朝那个方向发展。结果是您需要在几十个绘制调用中的每一个中推入尽可能多的多边形。渲染大型场景(例如城市)的游戏引擎通常会在运行中将多种纹理组合在一起,以减少抽奖次数。
2011年

我肯定想知道许多3D硬件中的纹理u,v映射以及点划线操作是否受益于Sprite表。
乔普兰特

7

除了性能方面的考虑外,在制作艺术品时,子画面还可以派上用场。每个字符都可以在自己的工作表中,并且只需滚动即可看到所有帧。它可以帮助我在所有框架上保持一致的外观。

另外,我用AS3编写代码,每个图像文件都需要单独的嵌入指令。我宁愿只使用一个整个Spritesheet的嵌入,而不是使用所有框架的24个嵌入,即使我使用的是单独的资源类。


1
+1。尽管OP没有使用Flash,但是嵌入或加载也是支持Spritesheets的重点。当从Web服务器加载资产时,这也很重要,在Web服务器中,相对于几百个请求(对于每个“框架”)而言,首选1个请求。
bummzack 2011年

绝对要减少服务器对在线游戏的请求。我们考虑了将图像放入.swf还是spritesheet是更好的方法,因为它们都可以实现此主要目标(我们最终决定,spritesheets对于我们的艺术家而言,劳动强度较小)。
jhocking 2012年

7

在XNA上使用Spritesheets的另一个原因是,在Xbox360开发中,存在一个已知的问题,即与项目中文件的数量有关,部署/加载时间较慢。因此,将许多小的图像文件合并为一个图像文件将有助于解决该问题。


5

我不会在这里提到内存/ GPU,因为有足够的答案。

相反,它可以在您进行艺术创作时及之后清除您的艺术作品。您无需浏览10张图像即可查看步行周期,而可以一次查看所有帧。如果要分发此文件,则只处理1个文件而不是10个文件。

然后,从characterwalk01到characterwalk10,再从characterattack01到characterattack05,将character.png和敌人.png覆盖起来(从组织的角度来看)也比较干净。


4

图形内存没有像磁盘上的文件系统那样繁琐的内存管理。相反的情况是:它保持简单快速

这样一种简单而快速的内存管理方式可能就像只有一个单一的4096x4096巨型精灵,将其宽度和/或高度减半而切成多个较小的精灵。(存在类似的一维内存管理技术,但我忘记了这个名称。)最终,必须执行碎片整理。

为了在运行时跳过这种内存管理,开发人员会在编译时甚至在图形的设计过程中自动用多个较小的精灵填充单个较大的精灵。


3

同样不要忘记I / O操作,它可能在初始化期间为您节省。如果从CD驱动器加载,则每个文件都是一个额外的I / O调用,并且可能需要一些时间来查找(现代HDD每个文件大约15毫秒,CD可能是50-100毫秒?)。由于只需要提取一个文件,因此可以节省大量的初始化时间。如果您的应用程序正在做其他事情(例如等待GPU),它还允许您的操作系统缓存这些I / O操作。


1
另一方面,如果您想解决文件查找问题,则可以使用自定义格式将所有精灵打包在单个文件中。大多数游戏都这样做。
tigrou 2012年

0

除了提高性能效率外,我发现它更加简单。创建艺术品时需要做一些额外的工作以确保您的图像始终在其范围内,但是能够轻松地查看当前正在处理的所有图像要容易得多。

我认为编码也更容易。我只是有一个对象数组,如:

sheet = {
    img: (the actual image),
    rects: [
        {x:0, y:0, w:32, h:32},
        {x:32, y:0, w:32, h:32},
        {x:64, y:0, w:32, h:32}
    ]
};

sheets.push(sheet);

然后为每个项目给它两个值,sheet和rect。工作表将是对象数组中的索引,而rect将是该工作表的rects数组中的索引。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.