【问题标题】:LibGDX optimize way to draw background with large resolutionLibGDX 优化绘制大分辨率背景的方式
【发布时间】:2018-01-06 12:21:46
【问题描述】:

我有一个问题困扰了我一个月,甚至更多。有一个大约9000x13000 像素的大背景。我正试图把这个背景带到屏幕上。由于我的显卡只支持分辨率不超过8192x8192 像素的纹理,所以显示的是黑色区域而不是纹理。我将图像压缩为5000x7000 像素。现在显示出来了,但是 FPS 已经下降到50(除了一张图像什么都没有)。此外,游戏还设计为在移动设备上运行,显卡的限制可以是2048x2048 纹理,也许更少。我试图将我的大纹理分成 117 块(每块不超过 1024x1024 像素),然后将它们一个接一个地拉出来。现在游戏的负载大约是一分钟,当纹理输出时,FPS 下降到5!我尝试使用过滤器

texture.setFilter(
    Texture.TextureFilter.MipMapNearestNearest,
    Texture.TextureFilter.Nearest
);

但 FPS 没有超过 10。它还在加载时将 useMipMap 标志设置为 true。目前我正在这样做:

Texture texture=new Texture(file, true);
texture.setFilter(
    Texture.TextureFilter.MipMapNearestNearest,
    Texture.TextureFilter.Nearest
);
public void render()
{
    batch.begin();
    batch.draw(texture,0,0,Gdx.graphics.getScreenWidth(),Gdx.graphics.getScreenHeight());
    batch.end();
}

告诉我,如何优化大纹理的输出? 此纹理是一张贴图,因此在接近大屏幕时应该清晰地显示细节。

如果有任何帮助,我将不胜感激

【问题讨论】:

  • 我猜不是所有 117 个部分都一直可见。只渲染那些怎么样?
  • 是的,我尝试只渲染那些在屏幕上可见的部分,FPS 大约是 30,但是随着地图的增加,FPS 再次下降到 5
  • 不幸的是,我认为没有任何优化可以完成。除非您用性能更高的语言编写渲染代码,否则没有什么可做的:/
  • 但是,您不能只使用平铺贴图或类似的平铺贴图来显示巨大的纹理。如果纹理的任何部分相同,则可以将它们存储并渲染为图块,这可能意味着性能提升。
  • 很遗憾,地图没有重复的元素——它只是艺术家创作的详细绘图

标签: android opengl-es libgdx render-to-texture


【解决方案1】:

我没有使用 libgdx 对其进行测试,但我认为除了拥有原始纹理之外,还值得尝试根据游戏中当前的缩放级别选择要显示的纹理的几种变体切成片。考虑在放大时在 Google 地图中加载图片。

想法

让我们将缩放级别定义为以下方式的数字:

  • 1 是最大缩放
  • 2 被缩小 2
  • 3 被缩小 4
  • 4 被缩小 8
  • ...

下面是纹理的定义方式:

  1. 将原始纹理切成 2048x2048 的块(~ 7x5 = 35 块,大多数移动设备都支持大小为 2048 的纹理)。将这些用于缩放级别 1。在这种情况下,您将最多同时加载 4 个纹理。
  2. 将原始纹理缩小 2 倍并再次切片。这将为您提供大约 9 个纹理。将它们用于 1 到 2 之间的缩放级别。
  3. 再缩小一倍 => 3 个纹理。将它们用于 2 到 3 之间的级别。
  4. 再来一次 => 3 级或更高级别。你可以在这里停下来。

现在,当用户缩小时,您使用纹理 #4。当用户放大到 3 级或更低时,您仍然会显示纹理 #4,同时正在加载缩放的纹理集。然后使用淡入/淡出进行平滑过渡以获得更好的视觉效果。

更多提示

  1. 为了更快地加载纹理,请考虑使用压缩纹理。压缩纹理的文件大小通常与 PNG 相当,但它可以更快地加载到视频内存中,并且使用与原始文件相同数量的 RAM。 (因为它不需要解压缩成原始位图)。特别考虑ASTC。旧设备不支持 ASTC,但我认为您的游戏运行要求很高。
  2. 仅当用户放大到适当的级别时才将纹理加载到内存中。用户缩小后卸载纹理。由于纹理压缩,这应该足够快。我会将纹理#4 始终保存在内存中,以获得更流畅的用户体验。出于同样的原因,可能保留中间级别是有意义的(例如,保留第 3 组的纹理,同时放大到第 2 级)。
  3. 为了更好地加载/卸载纹理,请多考虑用户行为(例如缩放的典型用法)。或者您可以使用某种 LRU 缓存并“自动”卸载纹理。

【讨论】:

  • 感谢您如此详细的回答!是的,我知道这项技术,它被称为 mipmap 纹理。 libgdx 文档说,如果在创建纹理时将第二个参数设置为 true,则框架会自动生成 mipmap。但这无济于事。我会尽量按照你说的去做。但是我担心游戏的大小会因此而增加很多,并且加载每个级别的细节会很长。非常感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
  • 2014-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多