2015-12-14 38 views
4

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

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

每个顶点具有以下数据:

// 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上,但我也可以在英特尔HD 5000上重现它。这发生在所有的Chrome,Safari和Firefox上,所以我很确定它与WebGL无关实施本身。这可能是OSX中的驱动程序错误吗?我的场景是由一堆的UI组成的。大多数UI元素都是从一个UI精灵表中绘制的,并且文本是从位图字体精灵表中绘制的。该错误通常表现为使用UI精灵图纹理绘制文本。我已经通过着色器修改进行了验证,并且通过使用WebGL检查器,我可以在绘制调用时将正确的纹理绑定到正确的采样器。

我注意到这似乎是通过在一次绘制调用中将纹理A绑定到采样器1并将纹理B绑定到采样器2以及将它们颠倒的下一个绘制调用触发的,其中纹理A绑定到采样器2和纹理B绑定到sampler1。

这个问题目前可以在这个网址实况转载:https://tinytappers.bigvikinggames.com/

这是最容易看到通过打开两个底部菜单中的一个,虽然它的开放,轻按屏幕顶部的敌人。通常,攻丝本身或敌方死亡动画足以使下方菜单中的文本在纹理之间快速切换。再次,这只是在几个特定的​​OSX机器上。

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

+0

我无法在我的2014年15“mbp上进行回购,您应该尝试制作一个较小的样本,在您的游戏中保留最少的示例,然后发布该代码 – gman

回答

0

我想我能够解决这个问题。

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

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

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

无论如何,我的解决方法现在工作,所以我只会去那。

+0

如果您可以制作一个小样本,再现浏览器供应商将确保修复的bug – gman

相关问题