记录微信小游戏AR功能开发遇到的坑

参加了一个大创项目,要在小游戏上实现AR效果,奈何本人太菜,疯狂跳进坑里,在这里记录一下自己遇到的坑,希望能帮助到刚刚开始尝试的朋友,也希望能有路过的大佬救救还在坑里的我QAQ

1.小游戏调用wx.creatcamera()打开摄像头

let camera =wx.createCamera({
      x: 0,
      y: 0,
     width: 500,
      height: 500,
      flash: "off",
      size: "medium",
      //devicePosition:"front",
      success: function () {
          console.log("摄像头打开成功");
      },
      fail: function (res) {
          console.log(res);
          console.log("摄像头打开失败");
      }
  });

在模拟器上是打不开摄像头的,真机调试可以打开。

2.一定要先开始监听帧数据才能获得帧数据

 camera.listenFrameChange();//开始监听帧数据

var listener = camera.onCameraFrame((frame) => {
          if (count < 0) {
                        var data = new Uint8ClampedArray(frame.data)
                        var picurl = that.uinttourl(data, frame.width, frame.height);
                        this.bg.loadImage(picurl);
                        count = 10;//每十帧才渲染一次
                    }
                    count -= 1;
                });

3.因为微信的相机画面一定是在最顶层,而实现AR功能又必须使模型显示在相机上层,因此需要把相机组件的大小设为1*1并利用帧数据渲染相机画面。从相机拿到的帧数据frame.data是像素数组,我需要texture格式或者图片url格式才能把相机画面渲染到屏幕上,开始时我尝试把uint8array转base64,但是按照网上的方法(类似String.fromCharCode.apply(null, slice);这样的),都没有成功,苦恼了两天,最终尝试的网上一位大佬的方法得到下面这段代码,成功得到图片地址。

uinttourl(data, w, h) {
            let canvas = document.createElement('canvas');
            let ctx = canvas.getContext('2d');
            let width = canvas.width = w;
            let height = canvas.height = h;
            let rowBytes = width * 4;
            for (let row = 0; row < height; row++) {
                let imageData = ctx.createImageData(width, 1);
                let start = row * width * 4;
                for (let i = 0; i < rowBytes; i++) {
                    imageData.data[i] = data[start + i];
                }
                ctx.putImageData(imageData, 0, row);
            }
            let dataURL = canvas.toDataURL("image/jpeg",0.1);
            return dataURL;
        }

第一次渲染出来相机画面的时候我真的很激动,然而事实是我又跳进了一个大坑里,通过uinttourl(data, w, h)这个方法获得url确实能渲染出相机帧,但是出来的画面非!常!卡!如上面第二段代码,我需要设置每十帧渲染一次才能基本保证画面不黑屏(但还是会有闪屏),当我以更高的频率渲染时就会全程黑屏。经过排查,主要问题不是loadimage(),也不是因为图片的url是base64格式的。问题应该出在uinttourl(data, w, h)中,但是我现在也不确定到底是因为for循环太耗时还是canvas.toDataURL太耗时还是因为我不会处理内存。

今天调了一天毫无进度,绝望之余写下这篇记录,如果有好心的大佬路过,希望能够给点建议救救孩子~


2021年3月6日更新

看了网上很多人说webgl渲染比canvas染快很多,所以今天尝试了把微信官方提供的小程序AR示例代码移植到小游戏,主要是用到了他的webgl配置(真的不会自己写着色器之类的ORZ),成功把相机的帧数据通过webgl方式画到了canvas,然后还是通过canvas.toDataURL转成图片url,按照昨天的方法加载到spirit上,结果画面还是很卡,得出结论:昨天的画面卡并不是因为canvas渲染太耗时。

再又尝试了几种方法无效后,我试图从spirit下手,我用的引擎是laya,认真地读了官方文档后发现了spirit的cacheAs这个属性

虽然也不是很看得懂,但是看见了“渲染性能最高”几个字,决定一试,把cacheAs设为了“bitmap”后,奇迹出现了!渲染出来的画面没有闪屏了!虽然还是不能做到每帧都渲染,但是看起来基本上算是流畅了。

最后放一张效果图

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值