在Firefox中避免使用texImage2D进行CPU端转换

AHM*_*AHM 5 javascript firefox webgl

每当我在webgl Firefox中使用纹理(用于OSX的Firefox Developer Edition 50.0a2,要进行激励)时,在控制台中输出这些警告:

错误:WebGL:texSubImage2D:发生CPU端转换,这是非常慢的
错误:WebGL:texSubImage2D:发生的CPU像素转换,这是非常慢的
错误:WebGL:texSubImage2D:选择格式/类型导致昂贵的重新格式化:0x1908/0x1401

有什么办法可以避免吗?我已经尝试了所有允许的格式和类型的组合texImage2D,但无论我尝试什么,我都可以在CPU上进行转换.

这是一个显示我正在做的事情的最小例子:

var gl = document.querySelector('canvas').getContext('webgl');

var textureSize = 512;
var canvas = document.createElement('canvas');
canvas.width = textureSize;
canvas.height = textureSize;

var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgba(0, 1, 0, 0.0)';
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, 400, 400);

var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
Run Code Online (Sandbox Code Playgroud)
<canvas />
Run Code Online (Sandbox Code Playgroud)

gma*_*man 2

您的示例不会在 OSX 上的 firefox 48 中打印警告,所以我只能猜测,但是

2D 画布使用预乘 Alpha。默认情况下,WebGL 对纹理使用未预乘的 alpha。这意味着为了传输画布纹理的内容,必须将其转换为预乘 Alpha,这取决于实现方式可能会很慢。

如果您的纹理中不需要未预乘的 alpha,那么您可以在调用时告诉 WebGL 您需要预乘数据,texImage2DtexSubImage2D通过调用gl.pixelStorei并像这样告诉它

gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,浏览器可能可以按原样使用画布数据。这可能会使警告消失。请注意,如果您只上传一次,您可能不应该关心。如果您要上传每一帧,那么也许您应该这样做。

请注意,这gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);会影响所有纹理上传,包括原始数据。例如

gl.texImage2D(
    gl.TEXTURE_2D, 0, gl.RGBA, 
    1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, 
    new Uint8Array([128, 192, 255, 128]));
Run Code Online (Sandbox Code Playgroud)

如果UNPACK_PREMULTIPLY_ALPHA_WEBGL是,true浏览器将在上传纹理之前进行预乘,因此[128, 192, 255, 128]将变为[64, 96, 128, 128]

UNPACK_FLIP_Y_WEBGL还可能影响上传速度,具体取决于它在浏览器中的实现方式。

  • 我尝试了 UNPACK_PREMULTIPLY_ALPHA_WEBGL 和 UNPACK_FLIP_Y_WEBGL 的每种组合,但似乎没有任何区别。查看 Firefox 源代码(https://dxr.mozilla.org/mozilla-central/source/dom/canvas/WebGLTexelConversions.cpp#392 和 https://dxr.mozilla.org/mozilla-central/source/dom /canvas/TexUnpackBlob.cpp#307),我开始认为也许不可能走上快速道路。 (4认同)