评论

小程序下WebGL截图

小程序下WebGL截图

最近做了关于小程序下WebGL截图的项目,遇到一些坑,记录下。

  1. 安卓切换页面后返回,再一次获取像素为空
  2. IOS偶尔获取到的为空白图像
  3. 获取到的数据绘制出来后上下颠倒

翻THREE.JS的代码,发现正确的截图方法

https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L1903

if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {

    // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)

    if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {

        _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );

    }

} else {

    console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );

}

所以解决方法

// 在渲染循环里检测checkFramebufferStatus状态,完成后再读取像素
const render = () => {
  if (this.disposing) return
  requestAnimationFrame(render);
  demo.update()
  renderer.render(scene, camera);

  if (this.screenshotResolve) {
    // @ts-ignore 参考 Threejs WebGLRenderer.readRenderTargetPixels
    if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
      // @ts-ignore
      gl.readPixels(0, 0, frameBuffer.x, frameBuffer.y, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
      // 翻转Y轴
      flip(pixelData, frameBuffer.x, frameBuffer.y, 4);
      // 确保有像素,微信小程序安卓在进入子页面返回本页面后,再一次readPixels稳定无像素
      if (pixelData.some(i => i !== 0)) {
        this.screenshotResolve([pixelData, frameBuffer.x, frameBuffer.y])
        this.screenshotResolve = null as unknown as Function;
      }
    }
  }
}

具体可阅读代码片段 https://developers.weixin.qq.com/s/syS4xzmw7AnO

点赞 6
收藏
评论

6 个评论

  • 恸
    2023-01-05

    您好,请教一下,用上面的方法iOS会报小程序运行内存不足,微信会闪退。但是Android都是正常的,可以保存图片

    2023-01-05
    赞同
    回复
  • 神经蛙
    神经蛙
    2022-11-03

    请问如何将Unit8Array的数据保存为图片文件?

    2022-11-03
    赞同
    回复
  •         
            
    2021-12-14

    想请教一下,如何threejs生成图片进行保存(楼主的方法太长了,不知道有没有简单的),看html是用toDataURL方法,小程序好像不行。

    2021-12-14
    赞同
    回复
  • 小伟
    小伟
    2021-11-10

    你好,请问下你那边这个代码片段在 iOS 上还是可以截图吗?我测试了在安卓上可以,iOS 不行,pixelData.some(i => i !== 0) 这个判断为 false

    2021-11-10
    赞同
    回复 2
    • 小伟
      小伟
      2021-11-10
      antialias 设为 false 后就可以
      2021-11-10
      1
      回复
    • shmily
      shmily
      2021-12-22回复小伟
      试了一下,可以了,但是抗锯齿跟为什么会影响到这个呢
      2021-12-22
      回复
  • 你若盛开,
    你若盛开,
    2021-05-12

    厉害,我也是截了webGL画布的像素数据后发现截的图是倒的,原来是需要翻转一下Y轴,谢谢大神!

    2021-05-12
    赞同
    回复
  • DeepKolos
    DeepKolos
    2021-02-02

    小程序下可用的three 可更新、降级three、使用自定义three

    https://github.com/deepkolos/three-platformize

    2021-02-02
    赞同
    回复
登录 后发表内容