【问题标题】:Texture cache overflow for WebGL HTML5 gameWebGL HTML5 游戏的纹理缓存溢出
【发布时间】:2019-08-28 13:58:57
【问题描述】:

我正在创建一个 HTML5 网络冒险游戏并使用 Tiled 制作瓷砖地图。

即使使用Texture Packer,我似乎也超过了纹理单元的最大缓存,因为我遇到了错误

纹理缓存溢出:16 个纹理单元可用

WebGL Stats 显示限制为 16,大约 70% 的设备。我的浏览器,如图here,支持16个纹理单元:

在游戏中,我打开 Chrome 控制台查看 WebGL 规范:

  • WebGL2RenderingContext.MAX_TEXTURE_IMAGE_UNITS = 34930
  • WebGL2RenderingContext.MAX_VERTEX_TEXTURE_IMAGE_UNITS = 35660
  • WebGL2RenderingContext.MAX_COMBINED_TEXTURE_IMAGE_UNITS = 35661

这有点令人困惑,因为 this article 显示输出应该更多在 0-10 范围内,而不是 30,000 范围内:

maxTextureUnits = 8
maxVertexShaderTextureUnits = 4
maxFragmentShaderTextureUnits = 8

我的问题

  • 如何确定我打包的纹理图集中的哪些图像导致了问题?即,如何检查总纹理?
  • 是否可以强制更高的缓存限制?

【问题讨论】:

    标签: javascript html webgl textures


    【解决方案1】:

    检查这些值的方法是

    const maxFragmentShaderTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    const maxVertexShaderTextureUnits = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
    const maxTextureUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
    

    此外,这些值与您可以在单个着色器中访问多少纹理有关,而不是您总共可以拥有多少纹理。

    它们也与“缓存”无关

    在您的情况下,您可能希望将纹理组合成一个纹理图集(一个包含所有图块的纹理)。

    Here's some code that does that。 它加载一个平铺的 json 文件,然后加载所有引用的图像,然后创建一个 2D 画布并将每个图像中的图块复制到画布中,重新映射地图中的图块以匹配。完成后,它使用画布作为平铺纹理的来源。通常我会离线执行此操作,但很高兴能够点击“重新加载”以查看我在运行时留下的新地图。

    在同一个库中是a shader that draws tilemaps,包括翻转和旋转的瓷砖。换句话说,要绘制平铺地图,每层需要一个绘制调用,并且只使用 2 个纹理。一个纹理保存平铺图像(上面创建的纹理)。另一个纹理包含一层平铺地图。着色器读取平铺地图纹理并使用它从平铺图像纹理中绘制正确的平铺。你可以看到这个技术的解释in this article

    顺便说一句:带有平铺加载器的库也有a shader that can selectively adjust the hue of a sprite。该库用于一些游戏,例如this game

    • 如何确定我打包的纹理图集中的哪些图像导致了问题?即,如何检查总纹理?

    您管理纹理,而不是 WebGL,因此如果您想知道您使用了多少纹理,请添加一些代码来计算它们。

    • 是否可以强制更高的缓存限制?

    不,但就像我上面所说的,这与任何缓存无关。

    我的猜测是您正在使用某个库或者您自己的代码正在生成一个着色器,并且您正在向它添加越来越多的纹理,并且着色器生成器因此生成了一个使用太多纹理的着色器。问题是你为什么在同一张图中使用这么多纹理。据我所知,没有 2D 游戏在一次绘制调用中使用超过 2 到 6 个纹理。游戏可能会使用 10000 个纹理,但要绘制单个精灵或图层地图,它只需要 1 或 2 个纹理。

    换一种说法。一个典型的游戏就可以了

    for each layer of tilemap
      bind texture atlas for layer (assming it's different than other layers)
      draw layer
    
    for each sprite
      bind texture for sprite
      draw sprite
    

    在上面的示例中,即使您有 10000 个纹理,一次也只有 1 个纹理在使用,因此您没有达到任何限制。

    【讨论】:

      猜你喜欢
      • 2014-08-26
      • 2011-11-23
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      • 2014-12-05
      • 2011-05-28
      • 2019-03-12
      • 2013-09-20
      相关资源
      最近更新 更多