【问题标题】:Avoid CPU side conversion with texImage2D in Firefox避免在 Firefox 中使用 texImage2D 进行 CPU 端转换
【发布时间】:2016-09-01 12:25:11
【问题描述】:

每当我在 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);
<canvas />

【问题讨论】:

  • 尝试使用gl.texImage2D(target, level, internalformat, width, height, border, format, type, ArrayBufferView? pixels); texImage2D 的版本并将 widthheight 参数设置为您的 textureSize

标签: javascript firefox webgl


【解决方案1】:

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

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

如果您的纹理中不需要未预乘的 Alpha,那么您可以在调用 texImage2DtexSubImage2D 时告诉 WebGL 您需要预乘数据,方法是调用 gl.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 也可能会影响上传速度,具体取决于它在浏览器中的实现方式。

【讨论】:

猜你喜欢
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 2013-06-28
相关资源
最近更新 更多