小程序AR踩坑记录

这篇具有很好参考价值的文章主要介绍了小程序AR踩坑记录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用微信自带的 VisionKit API提供 AR 能力。官方手册地址: VisionKit 基础

虽然官方提供了 demo 代码,但是埋藏的暗坑还是不少。特此总结一下。

DEMO案例

待添加

逻辑流程

大致流程如下: 用户访问 AR 页面,程序进行初始化,通过 VKSession 获取到摄像头数据,并将图片传到后端进行识别,获得目标物体坐标信息,随后在目标位置放置 3D 模型。

流程细节如下:

  1. 初始化 canvas 尺寸,设置对应设备像素密度下的宽高信息。
  2. 初始化 threejs 。
    1. 初始化 scene、 camera、 light。threejs 库需要使用微信官方提供的 threejs-miniprogram 。使用了 three-platformize 发现摄像头数据无法上屏。
    2. 初始化 GLTFLoader。 GLTFLoader 加载有贴图模型会有问题,因为微信小程序环境不支持 Blob 相关 API,若要支持需要自己实现。
    3. 初始化 WebGL。 initGL ,这一步设置好片元着色器和顶点着色器,让摄像头的数据渲染到webgl 画布上。(官方提供的着色器代码在我们场景有bug)
  3. 初始化 VKSession。在 requestAnimationFrame 中获取帧数据,进行动态渲染画面。执行 render(frame)。
  4. 在 render 函数中:
    1. 同步摄像头位置信息,需要对 VKSession 的矩阵进行逆矩阵求导。并把位置信息同步给 threejs 的摄像头,来保证 3D 模型的方向跟踪手机移动的方向。
  5. 获取当前帧图片,上传到后台进行识别
    1. 读取 webgl 像素信息,提供 canvasPutImageData 绘制到一个不可见的 canvas。
    2. 使用 canvasToTempFilePath 和 getFileSystemManager 将 canvas 上的图像转化成base64。
    3. 调用识别接口
      1. 识别成功,载入3D模型
      2. 识别不成功,等待一段时间后继续尝试。

主要问题

  1. webgl 图片获取
    1. 图片像素信息获取
    2. 图片翻转问题
  2. 图片转化成base64
  3. VKSession 模型穿模问题
  4. VKSession 摄像头数据渲染问题
  5. threejs-miniprogram gltf 贴图模型加载问题
  6. 模型动画导出异常问题

解决方案

webgl 图片获取

主要问题:

  • 获取到的数据绘制出来后上下颠倒需要对像素信息进行翻转
  • iOS 设备开启抗锯齿后获取数据是100%是纯黑色

由于使用 VKSession 后,手机摄像头的数据在 VKFrame 中,而且无法再次创建 camera 组件。所以我们必须利用 VKFrame 中的数据来获取摄像头的图像。 摄像头的上屏逻辑在 renderGL 方法中。此时,图像已经被渲染到页面的 webgl 组件上,我们需要把 webgl 的渲染帧读取下来。

threejs 中截图源码为 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.' );

}

核心代码如下


// 这里是核心步骤,获取 webgl 的像素信息 
const gl = this.gl;
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const pixels = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
// 翻转Y轴
flip(pixels, width, height, 4);

图片转化成base64

获取到需要的像素数据后, 就可以绘制到 canvas 上( canvasPutImageData 方法),然后将 canvas 导出成 base64 图片( canvasToTempFilePath + getFileSystemManager )了。

const frame = this.canvas;
const gl = this.gl;
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const pixels = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
flip(pixels, width, height, 4);
wx.canvasPutImageData(
  {
    canvasId: "myCanvas",
    data: new Uint8ClampedArray(typedArrayToBuffer(pixels)),
    x: 0,
    y: 0,
    width: frame.width,
    height: frame.height,
    success: (res) => {
      // 图片保存到 canvas
      this.save(frame).then((base64) => {
        reslove(base64);
      });
    },
    fail(res) {
      console.log(res);
    }
  }
);

save(frame) {
      return wx
        .canvasToTempFilePath({
          x: 0,
          y: 0,
          width: frame.width,
          height: frame.height,
          canvasId: "myCanvas",
          fileType: "jpg",
          destWidth: frame.width,
          destHeight: frame.height,
          // 精度修改
          quality: 0.6
        })
        .then(
          (res) => {
            // 临时文件转base64
            return new Promise((reslove, reject) => {
              wx.getFileSystemManager().readFile({
                filePath: res.tempFilePath, //选择图片返回的相对路径
                encoding: "base64", //编码格式
                success: (res) => {
                  // 保存base64
                  reslove(res.data);
                },
                fail: (error) => {
                  reject(error);
                }
              });
            });
          },
          (tempError) => {
            console.log(tempError);
            wx.showToast({
              title: "图片生成失败,重新检测",
              icon: "none",
              duration: 1000
            });
          }
        );
    }

穿模问题

官方提供的 renderGL 默认关闭了深度检测,会导致 3D 模型穿模 ,所以需要注释 gl.disable(gl.DEPTH_TEST);

renderGL(frame) {
  const gl = this.renderer.getContext();
  // gl.disable(gl.DEPTH_TEST);
  const { yTexture, uvTexture } = frame.getCameraTexture(gl, "yuv");
  const displayTransform = frame.getDisplayTransform();
  ...
}

摄像头数据渲染问题

由于开启了深度检测,导致着色器代码有bug,会在机型上展示黑条或者雪花。解决方案如下。修改着色器代码如下

		const vs = `
			attribute vec2 a_position;
			attribute vec2 a_texCoord;
			uniform mat3 displayTransform;
			varying vec2 v_texCoord;
			void main() {
			  vec3 p = displayTransform * vec3(a_position, 0);
			  gl_Position = vec4(p.x, p.y, -1, 1);
			  v_texCoord = a_texCoord;
			}
		`;

以下方案未尝试,也可以试试看。

VKSession官方demo兼容性,在华为p30 pro或者小米11 会出现左上角花瓶区域?

gltf 贴图模型加载问题

由于小程序环境不支持Blob 和 URL 对象,所以参考 three-platformize 项目的 loader,实现对应的api即可。文章来源地址https://www.toymoban.com/news/detail-433118.html

到了这里,关于小程序AR踩坑记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序请求不到接口解决(踩坑记录)

    域名是否配置了ssl证书 小程序后台-开发-开发设置-服务器域名 中是否配置了域名 配置完后可以在开发者工具中查看 如果还是不能请求到接口,请检查 ssl证书链是否有问题 myssl检测工具 我的是因为支持了 TLS1.0协议被判定为不合规,关闭后正常

    2024年02月12日
    浏览(44)
  • uniapp运行到微信小程序踩坑记录

    提示TypeError: Property value expected type of string but got undefined 打包时提示以下报错 因为标签绑定绑定一个函数的参数中传入一个函数时,不能直接加入括号传承,不支持方法中套方法的操作, 错误: 正确 应该把参数传入函数中以回调的形式去调用,不能直接在标签上嵌套 Error

    2024年02月16日
    浏览(67)
  • 局域网ssh登录windows自带Linux系统(WSL)踩坑记录

    先按照网上的教程安装好Linux系统(一般都是安装Ubuntu),安装好ssh等工具: (这里有的教程写的是sshd而不是ssh,在ubuntu里会报错,提示sshd不存在之类的。) 通过ifconfig命令查看Linux的IP,在mac或者其他机器上尝试ping一下inet IP。注意这里要保证两个机器是在同一个局域网,

    2024年02月14日
    浏览(35)
  • 微信小程序给 thinkphp后端发送请求出现错误 Wrong number of segments 问题的解决 【踩坑记录】

    这里提示 wrong number of segements , 百度了一下说这个问题是 后端解码token缺了一些东西(没正确的解码),然后我去抓了下包发现,我小程序端发送请求的时候,token是undifend,然后检查了一下store中的token发现,是我写错了变量名(😂好低级的错误) 微信小程序向后端发送请求时

    2024年02月09日
    浏览(53)
  • uniapp使用微信小程序提供的原生插件(组件)

    小程序交易保障标展示组件 为例 参考uniapp加载插件、微信小程序加载插件 1. manifest.json: 先打开manifest.json文件,然后我们找到\\\"mp-weixin\\\",引入需要使用的插件 2. pages.json 打开pages.json文件,然后再对应的页面配置处添加东西 3.页面使用

    2024年02月11日
    浏览(63)
  • 【uniapp&微信小程序】跨平台使用echarts的方案选择&踩坑

    使用Uniapp(vue)开发微信小程序,想用echarts图表实现类似github热力图的效果。 简要列一些可行或不可行的方案。 有echarts官网提供的跨平台方案:在微信小程序中使用 ECharts 简单易用,图表齐全 renderjs-echarts-demo 可参考的使用总结 render.js+echarts echarts图表在移动端的应用 支持

    2024年02月13日
    浏览(119)
  • 微信小程序使用web-view,内嵌跳转h5踩坑记!!

    由于业务需要在微信小程序内,嵌入外网h5到小程序,项目整体在开发,调试完成都没有任何问题,但是,在部署到测试环境之后,跳转h5报如下错误:   通过查阅官方文档,以及各类技术文档,报错的原因是,没有在微信公众平台配置业务域名和合法域名;具体操作步骤 【

    2024年02月08日
    浏览(63)
  • 使用微信提供的云开发实现后端 微信小程序云开发的内容管理CMS

    以前开发一款小程序或者应用啥的,首先就是申请域名租服务器,这是必不可少的步骤。 现在小程序云开发出来后,又再出现内容管理的这个功能,对于开发一款简单的小程序来说,真的是太简单的了。 现成的后台直接配置,一个前端全部搞定。 1.有云开发环境的小程序

    2024年02月08日
    浏览(39)
  • 记录--H5页面对接微信支付踩坑杂记

    应用背景:vite搭建的vue3项目 需求背景:功能都涉及了支付业务,故需要和外部支付系统对接 外部支付系统:聚合支付、微信小程序支付、微信H5支付 读完本文,你将会对以下几个坑点有所了解: 对接第三方服务商过程踩坑 对接小程序支付踩坑 对接微信H5支付踩坑 关于客户

    2024年02月08日
    浏览(40)
  • 提供一个小工具:微信小程序自动转码机器人!供大家24小时免费使用!

    弄个微信小程序自动转码机器人就可以完成,今天把我的机器人安排给大家,外面很多都是收费的,2毛钱转一次,这个钱真没必要花,我的机器人供大家24小时免费用,下面简单介绍一下机器人的功能。 目前我的机器人,供大家常用的有三个功能,不常用的我就不多说了,后

    2024年02月09日
    浏览(93)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包