代码之家  ›  专栏  ›  技术社区  ›  user3871

WebGL HTML5游戏的纹理缓存溢出

  •  0
  • user3871  · 技术社区  · 5 年前

    我正在创建一个HTML5网络冒险游戏,并使TileMaps Tiled .

    即使有 Texture Packer ,当我得到错误时,我似乎超过了纹理单位的最大缓存

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

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

    enter image description here

    在游戏中,我打开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范围内,而不是30000范围内:

    maxTextureUnits = 8
    maxVertexShaderTextureUnits = 4
    maxFragmentShaderTextureUnits = 8
    

    我的问题 :

    • 如何确定我的压缩纹理图集中的哪些图像导致了问题?也就是说,我怎样才能检查所有的纹理?
    • 是否可以强制提高缓存限制?
    0 回复  |  直到 5 年前
        1
  •  1
  •   gman    5 年前

    检查这些值的方法是

    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 包括翻转和旋转的瓷砖。换句话说,要绘制平铺贴图,每层调用一次绘制,只使用两个纹理。一个纹理保存平铺图像(上面创建的纹理)。另一个纹理包含平铺贴图的层。着色器读取平铺贴图纹理,并使用该纹理从平铺图像纹理绘制正确的平铺。你可以看到这种技术的解释 in this article

    顺便说一句:带平铺加载程序的库也有 a shader that can selectively adjust the hue of a sprite 。例如,图书馆曾与一些游戏一起使用 this game

    • 如何确定我的压缩纹理图集中的哪些图像导致了问题?也就是说,我怎样才能检查所有的纹理?

    你管理的是纹理,而不是webgl,所以如果你想知道你用了多少,就添加一些代码来计算它们。

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

    不,但就像我上面说的,这和任何缓存都没有关系。

    我的猜测是你正在使用一些库或者你自己的代码正在生成一个材质球,你正在添加越来越多的纹理到它和材质球生成器,因此生成一个材质球,使用太多的纹理。问题是你为什么在同一张图中使用这么多纹理。据我所知,没有一款2D游戏在一次抽签中使用超过2到6个纹理。游戏可能使用10000个纹理,但要绘制一个精灵或一个tilemap层,只需要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个纹理,一次也只有一个纹理在使用,因此没有达到任何限制。