【发布时间】: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。你应该尝试制作一个更小的样本。继续从你的游戏中删除一些东西,直到你有最小的例子来解决问题。然后发布代码。