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

时间:2016-08-31 13:39:12

标签: javascript firefox webgl

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

  

错误: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);

<canvas />
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

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

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

如果你不需要在纹理中使用非预乘alpha,那么你可以通过调用texImage2D告诉WebGL你想要预乘数据texSubImage2Dgl.pixelStorei并告诉它像这样

gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

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

请注意,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]));

如果UNPACK_PREMULTIPLY_ALPHA_WEBGLtrue,浏览器会在上传纹理之前进行预乘,以便[255, 255, 255, 128]成为[64, 96, 128, 128]

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