由于或尽管有大量图像,我是否应该使用Spritesheets?


13

我正在开发2D游戏,并且我有很多精灵。我使用3D动画和模型将其渲染为2D,从而使它们看起来像“ Fallout”或“ Diablo”。比手工绘制还容易,哈哈。

我已经不得不将帧速率降低到15fps,这是我可以降低的最低帧速率,而又不会使它们看上去不连贯。但是,由于24帧的平滑度令人难以置信,这令人感到悲伤。

我这样做的原因有两个:

1)减少硬盘空间。图片越少,我的整体游戏就越小。

2)减少RAM消耗。加载的图像越少,我越有可能避免导致RAM限制过大的问题。

但是,如果有一种方法可以压缩HDD空间和RAM中的图像,我会这样做。我之前已经对其进行过测试,从RGBA8888到RGBA5555的赠品在质量上几乎没有任何变化,而在TexturePacker程序中转换为RGBA4444时仅受到了一点打击。我目前不这样做,因为SFML似乎使用相同数量的内存,而不管它是哪种类型的.PNG图像。我研究了如何以不同的方式加载它,但是未能找到关于该主题的任何内容。

我已经阅读了很多有关如何处理2D视频游戏的内容。共识是压倒性的:将您的Sprite打包成更大的纹理以获得出色的性能!因此,我使用TexturePacker将微小的Sprite打包到更大的Spritesheet中。

但是,我计划每个角色有10-15个动画,移动5个方向,每个动画15-40帧(平均24个)。具有15个动画,5个方向,每个动画平均24帧;即每个字符1800个单独的帧。如果装在一张精灵纸中,则只能显示75张图像。(每个动画每个方向一个精灵表。15* 5)

对于游戏中一个巨大的老板角色,我不能使用Spritesheet,而必须编程一种仅一次加载一张图像的方法。我不知道我是否可以这样做以提高性能。

对于角色,我已经将它们打包在一张spritesheet中。对于单个角色来说,这似乎在大多数时间都有效,尽管有时会停顿。但是,我将其归因于我构思错误的代码,该代码交换了纹理,而不是预加载该角色的所有纹理。

如果我要预加载纹理,则对于精灵表来说是有意义的。我只能想象为每个角色预加载1800个小图像是一个坏主意。

但是,我想一次将它们流式传输到内存中是非常快的,所以我只需要一次在内存中有一个图像。这是否意味着在任何给定时刻我只会让每个字符消耗几个KB而不是45 + MB?

我想这会破坏我的性能,因为流传输必须非常快(每秒15张图像进出内存和渲染,每秒),尽管这些图像非常小-加载字符Spritesheets可能是一个更好的主意进入内存。但是无论如何,我将不得不为我的大老板角色编写一个类似于单图像流的渲染系统。

我一直在尝试,但这不是一个简单的过程。特别是考虑到我正在研究游戏引擎的其他部分,而这些部分现在还不处理图形。


1.您未指定RAM或HDD约束。快速访问需要几个字符?2.课文中有几个问题,也许您可​​以将其加粗,甚至将问题分成几部分?
Kromster

哦,对不起。不多。我可以想象在任何一次屏幕上最多可以显示40个单独的字符。如果人们提出要破坏其客户的提示,那么... 130是绝对最大值。通常,典型最大值仅需要为10,并且绝对最大值不超过<40。超过40的值将是极其极端的稀有,用户有意地尝试添加字符,除了屏幕截图或填塞字符的乐趣外,没有其他原因。高于10的情况很少见,而超过40的情况则非常罕见。
Carter81 2013年

该游戏是仅适用于PC(无移动设备)的2D角色扮演游戏,但是我不希望排除移动平台,除非它根本不可行。我想我拥有的RAM空间仅限于用户PC和用户VRAM上的任何RAM。我严重怀疑这将是非常大的HDD明智的选择。只是对于HDD消耗始终是正确的,它越小越好。
Carter81 2013年

您需要在屏幕上显示多少个UNIQUE字符?
Kromster 2013年

不超过20。除非他们作弊,否则以上所有内容将几乎是不可能的。通常为5-10。
Carter81 2013年

Answers:


16

我们的RTS Remake也有类似情况。所有单位和房屋都是精灵。我们为单位,房屋和地形提供了18 000个精灵,另外为团队颜色提供了约6000个(用作蒙版)。经过长时间拉伸,我们在字体中还使用了约3万个字符。

因此,图集背后的主要原因是:

  • 减少浪费的内存(在较早的日子中,当您将NPOT上传到GPU时,它会拉伸/填充到POT,我读到它在iOS和某些框架上仍然相同。您最好检查一下目标硬件的范围)
  • 较少的纹理切换
  • 以更少的大块更快地加载所有内容

什么对我们没有用:

  • 调色板的纹理。该功能仅存在于OpenGL 1.x 2.x中,即使在那时,GPU制造商也大多放弃了该功能。但是,如果您针对OpenGL + Shaders,则可以在着色器中自己编写代码!
  • NPOT纹理,我们会遇到边界错误和精灵模糊的问题,这在像素艺术中是无法接受的。RAM使用率也高得多。

现在,我们将所有内容打包成数十个1024x1024地图集(现代GPU支持更大的尺寸),并且仅消耗约300mb的内存就可以很好地工作,这对于PC游戏来说是相当不错的。我们进行了一些优化:

  • 添加用户选项以使用RGB5_A1而不是RGBA8(棋盘格阴影)
  • 尽可能避免使用8位Alpha,并使用RGB5_A1格式
  • 将精灵紧密地打包到地图集中(请参阅Bin Packing算法)
  • 存储和加载HDD中的所有内容(资源文件应离线生成)
  • 您也可以尝试使用硬件压缩格式(DXT,S3TC等)

当您认真考虑迁移到移动设备时,您会担心约束。现在就开始使游戏运转并吸引玩家!;)


到目前为止,这是最好的解决方案!我的精灵在RGB5_A1或RGBA4444中看起来都没有什么不同,但是可以节省内存。您在聊天中建议将我的所有资产预加载到RAM和VRAM中是完美的。更进一步,您建议使用可选的图形级别,例如为拥有RAM的用户提供高清客户端,或者将帧速率降低一半的选项等。全方位的出色建议,正是我所需要的!
Carter81 2013年

5

我在这里有一个与切线相关的答案,但是一般的想法是,如果您在不同的时间加载和绘制纹理(渲染时没有加载其他纹理),那么有两个地方可以这样做会影响您的表现:

载入时间:

这是将纹理上传到内存的时刻。您要发送到VRAM 的全部数据主要决定了加载时间。使您的纹理具有较小的格式(例如RGBA4444)将使其更快。但是,除非您将数百兆字节的纹理上传到VRAM,否则您可能不会在这里遇到瓶颈。如果这样做,一个不错的加载屏幕可以减轻等待的时间。

将纹理连接到地图集几乎没有效果,因为要发送到VRAM的全部信息量是相同的。实际上,如果要对纹理进行地图集处理,并且必须在地图集中留出空白空间,那么实际上您将向VRAM 发送更多数据,因此这部分速度会变慢!

渲染性能:

一旦所有纹理都位于VRAM中,您拥有的纹理数量将不会影响渲染性能。有四个因素会影响渲染性能:

  1. 渲染状态更改:每次更改要从中渲染的图像时,都会严重增加渲染时间。通常,您希望最大程度地减少状态更改的数量,并且可以通过将要连续绘制的多个图像分组到纹理图集中来减少状态更改的数量。

    仅地图集是不够的。您必须以减少状态变化的方式进行图集设置,以便获得性能提升。例如,您可能会认为将主角放置在Sprite表中会提高性能,但是如果仅从每帧Sprite表中绘制一个Sprite,则与在Sprite表中绘制一个Sprite相比,不会获得任何性能提升。每个精灵在一个单独的文件中。

    适当的地图集并非易事,但通常您可以安全地将同一图层中的精灵进行分组。例如,将所有GUI项目都放在一个精灵表中是一个非常有前途的想法,而按字母顺序对怪物进行分组可能不会。

  2. 绘图调用:通常,您可能希望将绘图调用保持在最低限度。一条很好的经验法则是,如果两个绘制调用之间的渲染状态没有变化,则可以将它们加入单个绘制调用中。为了获得更高的性能,您可以使用8个纹理采样器,并且每8个纹理进行一次组绘制调用,因此您仅需每8个纹理更改一次纹理。

  3. 三角形数:实际上,绘制的三角形越多,绘制它们所花费的时间就越长。但是,在现代计算机中,对于大多数2D游戏,您将无法最大限度地发挥这一作用。您可以安全地每帧绘制成千上万的精灵,并且仍然获得疯狂的良好帧速率。如果在GPU出现问题之前绘制大量Sprite,可能会占用更多CPU资源。

  4. API设置:如果您做的一切正确,并且帧速率仍然很低,请检查用于绘制子画面的设置。我不知道SFML,但是例如,在Direct3D 9中,使用D3DUSAGE_DYNAMIC或创建顶点缓冲区D3DPOOL_MANAGED可以轻松地将渲染时间增加十倍。当然,使用vSync可以将帧速率限制为显示器的刷新速率。此外,使用不对齐的FVF可能会降低某些GPU的性能。这也适用于Direct3D 9。

    根据您的情况,请查看所用API的文档。

如果您的纹理数量很少(不到1GB),并且绘制的精灵数量很少(每帧少于一百万),那么我要看的第一件事就是更改API设置,并且然后减少渲染状态和绘制调用的数量。


如果我不在乎加载时间,我是否可以假设除非我用完了RAM或VRAM,否则应该将所有内容预先加载到内存中吗?
Carter81 2013年

我只关心所有事情,因为我担心RAM / VRAM不足。我不知道为什么,但是令我惊讶的是,玩我的游戏的用户每次尝试加载到具有太多独特精灵的区域时都将崩溃,或者当有太多角色进入其屏幕时就会崩溃。如果我没有记错,每个单独的精灵占用96KB,那么如果每个唯一角色具有15个动画,5个方向以及每个动画平均24帧-完全加载的每个单独角色为173MB。一次在屏幕上可能有10个,甚至更多的唯一字符。
Carter81 2013年

@KromStern:如果是图集,并且必须保留空白(填充),那么数据将更大,因此加载时间将更长。显然,导致加载时间较长的原因是空白空间,总加载时间与数据总量而不是纹理量有关。我看不到任何误导之处,而且我认为,如果纹理和图集分别是PoT和nPoT,则有足够知识的人可以理解所有问题,并能得出结论并得出自己的结论。
2013年

1
@ Carter81:您需要选择目标硬件配置,例如“ i5、1GB RAM,NVidia GT260、400mb硬盘”,然后从中进行工作。总是会有PC的性能更弱,RAM更少。
Kromster 2013年

显然,他们在任何给定时间都不需要全部15个动画。但是,如果所有10个唯一的角色同时进入“战斗模式”,从而需要将5组动画(行走,奔跑,闲置,非战斗等)与另外5组动画(战斗行走,战斗怠速,战斗等)?我害怕交换纹理,因为当我尝试使用SFML进行纹理交换时,它会在切换纹理地图集时引起客户端的明显冻结暂停。我不知道处理这么多精灵的各种策略会遇到什么瓶颈。
Carter81 2013年
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.