WebGL 中的图片解码优化
虽然 WebGL 支持 压缩纹理,上传 GPU 不存在解码耗时的问题,但日常应用中还是会用到 png/jpg/webp 等压缩过的图片格式。这些格式在 WebGL 中渲染需要转换成位图,即每个像素使用 RGB 或 RGBA 表示。这个过程称为图片解码。
图片解码在渲染中是非常重要的一环,若直接使用 Image 对象上传(texImage2D)至 GPU,往往耗时较长,阻塞主线程,比如说会导致动画播放卡顿,影响用户体验。所以,在这里对浏览器中的一些 WebGL 中图片解码的方案做了一些研究和测试。
本文重点是 Image.decode 方法和 createImageBitmap 方法。
Image.decode
Image.decode 可以异步对 Image 进行解码,异步的解码不会阻塞主线程动画和交互。使用方法如下:
const img = new Image();
img.src = '...';
img.decode().then(function() {
document.body.appendChild(img);
});
createImageBitmap
ImageBitmap 是专门为 Canvas 和 WebGL 渲染使用的一种数据格式。createImageBitmap 会异步返回一个含 ImageBitmap 对象的 Promise。createImageBitmap 可以在 worker 中使用,ImageBitmap 也可以在 worker 之间传输。createImageBitmap 接受多种数据源,本文重点测试 Blob 和 HTMLImageElement,这两种对象在渲染引擎中最常使用。
// 使用 image 作为源
createImageBitmap(image).then((imageBitmap)=>{
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageBitmap);
})
// 使用 blob 作为源
createImageBitmap(blob).then((imageBitmap)=>{
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageBitmap);
})
在 WebGL 中采取的图片请求最佳解码方案是: