【问题标题】:WebGL on OSX using wrong texture in all browsersOSX 上的 WebGL 在所有浏览器中使用错误的纹理
【发布时间】:2015-12-14 21:43:44
【问题描述】:

我在某些 OSX 机器上看到一个非常奇怪的问题,我的 WebGL 程序似乎使用了错误的纹理内容进行绘图。

我设置了一个精灵批处理,我将一堆精灵四边形缓冲在一起,形成一个绘制调用。我还使用多重纹理来进一步减少绘制调用的数量,在同一个绘制调用中为多个纹理绘制精灵。

每个顶点都有以下数据:

 // 16 bytes
 float x;
 float y;
 float u;
 float v;

 // 16 bytes
 float texture_offset_x;
 float texture_offset_y;
 float texture_scale_width;
 float texture_scale_height;

 // 24 bytes
 float t0;
 float t1;
 float t2;
 float t3;
 float t4;
 float t5;

 // 8 bytes
 float width_scale;
 float height_scale;

 // 4 bytes
 unsigned byte r;
 unsigned byte g;
 unsigned byte b;
 unsigned byte a;

 // Texture sampler index
 float texture_index;

片段着色器像这样组合绘制调用:

  "#version 100",
  "",
  "uniform lowp sampler2D sampler0;",
  "uniform lowp sampler2D sampler1;",
  "uniform lowp sampler2D sampler2;",
  "uniform lowp sampler2D sampler3;",
  "uniform lowp sampler2D sampler4;",
  "uniform lowp sampler2D sampler5;",
  "uniform lowp sampler2D sampler6;",
  "uniform lowp sampler2D sampler7;",
  "",
  "varying mediump vec2 vTextureCoord;",
  "varying lowp vec4 vTintColor;",
  "varying lowp float vTextureIndex;",
  "",
  "void main(void) {",
  "   lowp vec4 fragColors[8];",
  "   fragColors[0] = texture2D(sampler0, vTextureCoord);",
  "   fragColors[1] = texture2D(sampler1, vTextureCoord);",
  "   fragColors[2] = texture2D(sampler2, vTextureCoord);",
  "   fragColors[3] = texture2D(sampler3, vTextureCoord);",
  "   fragColors[4] = texture2D(sampler4, vTextureCoord);",
  "   fragColors[5] = texture2D(sampler5, vTextureCoord);",
  "   fragColors[6] = texture2D(sampler6, vTextureCoord);",
  "   fragColors[7] = texture2D(sampler7, vTextureCoord);",
  "",
  "   lowp float fragIncluded[8];",
  "",
  "   fragIncluded[0] = float(vTextureIndex <= 0.5);",
  "   fragIncluded[1] = float(vTextureIndex >= 0.5 && vTextureIndex < 1.5);",
  "   fragIncluded[2] = float(vTextureIndex >= 1.5 && vTextureIndex < 2.5);",
  "   fragIncluded[3] = float(vTextureIndex >= 2.5 && vTextureIndex < 3.5);",
  "   fragIncluded[4] = float(vTextureIndex >= 3.5 && vTextureIndex < 4.5);",
  "   fragIncluded[5] = float(vTextureIndex >= 4.5 && vTextureIndex < 5.5);",
  "   fragIncluded[6] = float(vTextureIndex >= 5.5 && vTextureIndex < 6.5);",
  "   fragIncluded[7] = float(vTextureIndex >= 6.5 && vTextureIndex < 7.5);",
  "",
  "   lowp vec4 fragColor = fragColors[0] * fragIncluded[0] + ",
  "                         fragColors[1] * fragIncluded[1] + ",
  "                         fragColors[2] * fragIncluded[2] + ",
  "                         fragColors[3] * fragIncluded[3] + ",
  "                         fragColors[4] * fragIncluded[4] + ",
  "                         fragColors[5] * fragIncluded[5] + ",
  "                         fragColors[6] * fragIncluded[6] + ",
  "                         fragColors[7] * fragIncluded[7];",
  "",
  "   gl_FragColor = fragColor * vTintColor;",
  "}"

在大多数情况下一切正常。但是在某些 OSX 机器上,被采样的纹理有时会出现错误。具体来说,这似乎最常发生在基于 NVidia 的 MacBook 上,但我也能够在 Intel HD 5000 上重现它。这发生在所有 Chrome、Safari 和 Firefox 上,所以我很确定它与 WebGL 无关实施本身。这可能是 OSX 中的驱动程序错误吗?

我的场景由一堆 UI 组成。大多数 UI 元素是从一个 UI 精灵表中绘制的,而文本是从位图字体精灵表中绘制的。该错误通常表现为使用 UI 精灵表纹理绘制文本。我已经通过着色器修改和使用 WebGL Inspector 验证了我在绘制调用时将正确的纹理绑定到正确的采样器。

我确实注意到这似乎是通过在一次绘制调用中将纹理 A 绑定到 sampler1,将纹理 B 绑定到 sampler2 触发的,而下一次绘制调用将它们反转,纹理 A 绑定到 sampler2,纹理 B 绑定到采样器1。

目前可以在此 URL 上实时复制此问题:https://tinytappers.bigvikinggames.com/

通过打开两个底部菜单之一最容易看到它,并在它打开时点击屏幕顶部的敌人。通常无论是敲击本身,还是敌人的死亡动画都足以让下方菜单中的文本在纹理之间快速切换。同样,这仅适用于少数特定的 OSX 机器。

其他人可以复制吗?有谁知道发生了什么?我很确定我传递给 WebGL 的数据是正确的。谁能发现数据有问题?

【问题讨论】:

  • 我无法在我的 2014 15" mbp 上 repo。你应该尝试制作一个更小的样本。继续从你的游戏中删除一些东西,直到你有最小的例子来解决问题。然后发布代码。

标签: macos textures webgl


【解决方案1】:

我想我可以解决这个问题。

我的代码试图变得聪明,并跟踪哪个纹理绑定到哪个纹理单元,然后只在需要更改时重新绑定它们。如果我总是在每次绘制调用之前将纹理显式绑定到相应的纹理单元,问题就会消失。

在我做这个解决方法之前,在某些情况下,我什至能够使 WebGL(在所有 3 个浏览器中)崩溃。在这种情况下,崩溃发生在 Apple Intel 5000 驱动程序中(在 NVidia 机器上没有崩溃)。

我仍然确信这是某种驱动程序错误。我认为纹理绑定在 Apple 的 OpenGL 实现深处的绘制调用之间以某种方式被破坏了。除非假设绑定的纹理将保持绑定不安全?

无论如何,我的解决方法目前有效,所以我就照着做吧。

【讨论】:

  • 如果您可以制作一个小样本来重现该错误,浏览器供应商将确保它得到修复
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2016-07-05
  • 1970-01-01
相关资源
最近更新 更多