我在某些OSX机器上看到一个非常奇怪的问题,其中我的WebGL程序似乎使用错误的纹理内容进行绘制。
我设置了一个sprite批处理,其中将一堆sprite quad缓冲在一起,形成一个绘制调用。我还使用多重纹理来进一步减少绘制调用的次数,在同一绘制调用中为多个纹理绘制精灵。
每个顶点具有以下数据:
// 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 Sprite表绘制的,而文本是从一个位图字体Sprite表绘制的。该错误通常表现为使用UI Sprite Sheet纹理绘制文本。我已经通过着色器修改和使用WebGL Inspector进行了验证,在进行绘制调用时,我具有绑定到正确采样器的正确纹理。
我确实注意到,这似乎是由于在一个绘制调用中将纹理A绑定到sampler1,将纹理B绑定到sampler2,然后在下一个绘制调用中将它们反转了而触发的,纹理A绑定到sampler2,纹理B绑定到sampler1。
当前可以在以下URL上实时复制此问题:https : //tinytappers.bigvikinggames.com/
通过打开两个底部菜单之一,最容易看到它,并且在打开菜单时,点击屏幕顶部的敌人。通常,敲击自身或敌人死亡动画足以使下部菜单中的文本在纹理之间快速切换。同样,这仅在少数特定的OSX计算机上。
有人可以复制吗?有人知道发生了什么吗?我很确定我传递给WebGL的数据是正确的。谁能找到数据的任何问题?
我想我可以解决这个问题。
我的代码试图变得聪明,并跟踪哪个纹理绑定到哪个纹理单元,然后仅在需要更改它们时才重新绑定它们。如果我始终在每次绘制调用之前始终将纹理显式绑定到相应的纹理单元,则问题就消失了。
在执行此变通办法之前,在某些情况下,我甚至已经使WebGL(在所有3个浏览器中)崩溃。在这种情况下,崩溃发生在Apple Intel 5000驱动程序中(在NVidia机器上没有崩溃)。
我仍然坚信这是某种驱动程序错误。我认为在苹果的OpenGL实现内部深处的绘制调用之间,纹理绑定被破坏了。除非不安全地认为绑定纹理将保持绑定状态?
无论如何,我的解决方法目前仍然有效,因此我将继续讨论。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句