最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • WebGL 中的图片解码优化

    正文概述 掘金(蚂蚁RichLab前端团队)   2021-04-24   547

    作者 - Oasis 团队-月木

    虽然 WebGL 支持 压缩纹理,上传 GPU 不存在解码耗时的问题,但日常应用中还是会用到 png/jpg/webp 等压缩过的图片格式。这些格式在 WebGL 中渲染需要转换成位图,即每个像素使用 RGB 或 RGBA 表示。这个过程称为图片解码。图片解码在渲染中是非常重要的一环,若直接使用 Image 对象上传(texImage2D)至 GPU,往往耗时较长,阻塞主线程,比如说会导致动画播放卡顿,影响用户体验。所以,在这里我们对浏览器中的一些 WebGL 中图片解码的方案做了一些研究和测试。 WebGL 中的图片解码优化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);
    })
    

    性能测试

    上面介绍完了两个异步解码 API 的基本使用,接下去我用 5 种方式对 100 张不同的 1024 * 1024 图(图片由脚本随机生成)进行解码测试,对比图片的解码时间和纹理上传时间。五种方式如下:

    1. 使用 Image 作为源用 createImageBitmap 方法。(示例)
    2. 使用 Blob 作为源使用 createImageBitmap 。(示例)
    3. 开启 5 个 worker 使用 createImageBitmap 方法。(示例)
    4. 使用 image.decode 进行解码。(示例)
    5. 使用 image 直接上传纹理。(示例)

    进过上面几项测试得出结果(上下浮动 100ms 左右):

    1. MacOS(2.6 GHz i7 chrome 87 降低 6 倍性能)

    使用方法解码时间(毫秒)纹理上传时间(毫秒)总时间备注
    createImageBitmap(Image)262529675592异步解码createImageBitmap(Blob)55921802739异步解码createImageBitmap(Blob) + worker21020002210异步 + 多线程解码image 直接上传30203020同步解码image.decode 后上传21049785188异步解码

    2. Android U4(Mi 10 Pro U4 3.21.0.172)

    使用方法解码时间(毫秒)纹理上传时间(毫秒)总时间备注
    createImageBitmap(Image)15408782418异步解码createImageBitmap(Blob)10961291225异步解码createImageBitmap(Blob) + worker715142857异步 + 多线程解码image 直接上传905905同步解码image.decode 后上传decode 报错,The source image cannot be decoded.异步解码

    3. Android Chrome(Mi 10 Pro Android Chrome 87)

    使用方法解码时间(毫秒)纹理上传时间(毫秒)总时间备注
    createImageBitmap(Image)5225041026异步解码createImageBitmap(Blob)310135445异步解码createImageBitmap(Blob) + worker249145394异步 + 多线程解码image 直接上传510510同步解码image.decode 后上传decode 报错,The source image cannot be decoded.异步解码

    4. iOS safari(iPhone7 iOS 14.2)

    使用方法解码时间(毫秒)纹理上传时间(毫秒)总时间备注
    createImageBitmap(Image)不支持createImageBitmap(Blob)不支持createImageBitmap(Blob) + worker不支持image 直接上传10761076同步解码image.decode 后上传20763002376异步解码

    结论

    通过以上测试,可以得出以下结论:

    1. Android 和 Mac Chrome 推荐用 createImageBitmap,数据源务必使用 Blob,解码可以提升 10% 左右的性能:
      1. 若数据源使用 Blob,无解码时间;若数据源使用 Image,有两次时间消耗,首先创建 bitmap 耗时很长,其次在 performance 里查看仍有解码时间(预期不该有解码时间,这是 Chrome 的 Bug,已经给 chromium 提了一个 issue,chrome 官方已经确认问题存在)。
      2. 在 worker 中调用 createImageBitmap 可以利用多线程能力,能进一步提升 15% 左右的性能。因为 worker 线程还不算特别稳定,是否开启 worker 解码交由用户配置决定,用户根据当前 cpu 负载及所需解码数量和业务场景去决定是否使用 worker 解码。
    2. iOS 不要用任何异步解码方案:
      1. 不支持 createImageBitmap
      2. 使用 Image.decode 的总时间是同步解码的两倍;

    根据上面测试的结果以及推导的结论,在 WebGL 中采取的图片请求最佳解码方案是: WebGL 中的图片解码优化

    以上方案即将应用到 oasis-engine 中,欢迎大家在 PR 中讨论。


    起源地下载网 » WebGL 中的图片解码优化

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元