最近做了关于小程序下WebGL截图的项目,遇到一些坑,记录下。
- 安卓切换页面后返回,再一次获取像素为空
- IOS偶尔获取到的为空白图像
- 获取到的数据绘制出来后上下颠倒
翻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;
}
}
}
}
您好,请教一下,用上面的方法iOS会报小程序运行内存不足,微信会闪退。但是Android都是正常的,可以保存图片
请问如何将Unit8Array的数据保存为图片文件?
想请教一下,如何threejs生成图片进行保存(楼主的方法太长了,不知道有没有简单的),看html是用toDataURL方法,小程序好像不行。
你好,请问下你那边这个代码片段在 iOS 上还是可以截图吗?我测试了在安卓上可以,iOS 不行,pixelData.some(i => i !== 0) 这个判断为 false
厉害,我也是截了webGL画布的像素数据后发现截的图是倒的,原来是需要翻转一下Y轴,谢谢大神!
小程序下可用的three 可更新、降级three、使用自定义three
https://github.com/deepkolos/three-platformize