OSX上的WebGL在所有浏览器中使用错误的纹理

时间:2015-12-14 21:43:44

标签: macos textures webgl

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

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

每个顶点都有以下数据:

 // 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绑定到sampler1。

此问题目前可以通过以下网址重播:https://tinytappers.bigvikinggames.com/

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

其他人可以重现这个吗?有谁知道发生了什么?我很确定我传递给WebGL的数据是正确的。任何人都可以发现数据有任何问题吗?

1 个答案:

答案 0 :(得分:0)

我想我能解决这个问题。

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

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

我仍然相信这是某种驱动程序错误。我想某种程度上,纹理绑定在Apple OpenGL实现中的绘制调用之间以某种方式被破坏了。除非假设绑定纹理仍然保持绑定是不安全的吗?

无论如何,我的解决方法现在适用,所以我将继续使用它。