微信开发者

2D变3D,小程序酷炫玩法在等你!

随着小程序的广泛应用,不少商家都希望通过小程序实现线上与线下营销活动联动。例如用户购买游戏实体卡,使用小程序扫描并形成 3D 立体效果,增强实体卡的营销价值。

Image

然而实现这样流畅又酷炫的 AR 效果并不容易,不仅需要对三维效果、关键点、边缘等部分进行不断调优,同时还需要保证整体流畅的性能表现。不过开发者也无需过分担心,现在通过 小程序 XR-Frame 框架 即可轻松实现,我们一起来看看吧👇

开发思路分析

以上述实体卡为例,用户体验的流程主要是:

  1. 打开摄像头,识别实体卡

  2. 识别成功后,自动渲染成 AR 效果

  3. AR 效果不局限于图片,支持视频流

  4. 用户移动实体卡时,AR 效果自动跟随

为了实现这样的效果,开发者先完成 AR 效果渲染,再进行图像识别即可:

  1. 实现基础的 AR 效果

  2. 根据项目情况去调整 AR 效果图片及尺寸

  3. 在图片渲染的基础上,增加视频流渲染

  4. 完成 AR 效果渲染后,增加图像识别能力,实现实体卡内容与 3D 电子内容匹配

实现基础 AR 效果

由于上述实体卡需要用到 2DMarker 场景,开发者在引入 XR-Frame 框架、创建场景 xr-scene 后,可以直接使用框架提供的各种标签,简单便捷,开箱即用:

  1. 给 <xr-scene> 设置 ar-system="modes:Marker",开启 marker 能力

  2. <xr-ar-tracker> 设置对应的类型  mode="Marker",并且设置 src,用于识别和追踪,src 为目标图片地址,即上述项目中实体卡对应的电子版内容

  3. 设置 <xr-camera> 的相关属性 is-ar-camera 和 background="ar",开启 AR 能力

  4. 在 <xr-ar-tracker> 中使用 <xr-mesh> 进行简单的贴图渲染

👉 点击查看代码

// app.json"lazyCodeLoading":"requiredComponents"
// index.json{  "component": true,  "renderer": "xr-frame",  "usingComponents": {}}
// index.wxml<xr-scene ar-system="modes:Marker">  <xr-node>    <xr-ar-tracker mode="Marker" src="{{markerImage}}">      <xr-mesh geometry="plane" uniforms="u_baseColorFactor:0.6 0.8 0.6 1"/>    </xr-ar-tracker>  <xr-camera clear-color="0.925 0.925 0.925 1" background="ar" is-ar-camera></xr-camera>  </xr-node></xr-scene>

完成上述开发过程后,开发者用手机摄像头对准预设的目标物,自动渲染出一个正方形;移动卡片,正方形也会跟着移动,完成基础的 AR 效果。

Image

调整图片及尺寸

我们希望 3D 效果显示对应的图片内容,而不是一个简单的正方形。因此开发者需要将正方形添加图片纹理,替换成目标图片。这里也可以开箱即用地调用 XR-Frame 框架提供的标签 <xr-asset-load> 即可实现。

👉 点击查看代码

<xr-scene ar-system="modes:Marker">  <xr-assets>    <xr-asset-load type="texture" asset-id="photo" src="https://vip.image.video.qpic.cn/vupload/20230411/05.png" />  </xr-assets>  <xr-node>    <xr-ar-tracker mode="Marker" src="{{markerImg}}">      <xr-mesh geometry="plane" uniforms="u_baseColorMap: photo"/>    </xr-ar-tracker>    <xr-camera position="0.8 2.2 -5" clear-color="0.925 0.925 0.925 1" background="ar" is-ar-camera></xr-camera>  </xr-node></xr-scene>

替换图片后,我们发现显示的 AR 效果仍然是正方形,不能与实体卡尺寸匹配,那么我们可以用 <xr-mesh>  的 scale 进行尺寸调整。

Image

👉 点击查看代码

<xr-mesh scale="1 1 1.5" geometry="plane" uniforms="u_baseColorMap: photo" />

视频流渲染

项目目标不仅是平面图的三维展示,更希望能够出现视频流的 AR 效果。那么应用 XR-Frame 框架提供的视频纹理 VideoTexture 资源即可实现:

  1. 设置 type="video-texture",并设定相关参数

  2. 在 js 中获取视频纹理对象,控制视频播放与暂停

👉 点击查看代码

// 设置 type="video-texture",并设定相关参数即可<xr-asset-load type="video-texture" asset-id="ar-video" options="abortAudio:false" src="{{video}}" /><xr-asset-material asset-id="video-mat" effect="simple" uniforms="u_baseColorMap: video-ar-video" />

// 控制视频播放与暂停
videoCtx = xrScene.assets.getAsset('video-texture', 'ar-video');// 播放await videoCtx.play();
// 停止videoCtx.stop();
// 在基础库v2.33.0及以上,提供了暂停/唤醒方法和播放状态const xrSystem = wx.getXrFrameSystem();if (videoCtx.state === xrSystem.EVideoState.Playing) {  videoCtx.pause();} else if (videoCtx.state === xrSystem.EVideoState.Paused) {  videoCtx.resume();}

图片识别

通过上述操作,我们已经完成整个 AR 渲染的过程。接下来就需要进行图片识别操作,识别哪张实体卡对应哪个电子内容,仅需 3 步即可实现:

  1. 借助 XR-Frame 框架的 tick 事件监听每一帧的变化,实现前端获取屏幕画面

  2. 在绑定的 handleTick 事件中,调用 分享系统,将当前帧的画面转为 base64 格式

  3. 将 base 64 数据传输给后台,后台接口在图片库中进行比对计算,返回最相似的图片给前端进行追踪渲染

👉 点击查看代码

// 绑定 tick 事件监听帧变化<xr-scene bind:tick="handleTick">......</xr-scene>
// 帧画面转成 base64 格式const base64 = xrScene.share.captureToDataURL({ quality: 0.5 });

通过以上操作,小程序够识别图片并且生成 AR 效果,但是在不同光线、角度、背景下,扫描实体卡可能会出现扫描失败 / 扫描错误的情况。

因此我们增加拍摄引导框,对屏幕画面按照引导框进行裁剪,再调用接口进行检索,优化图片识别率。这里使用 canvas 能力即可解决。

Image

👉 点击查看代码

const renderWidth = clipWidth * dpi / 2;const renderHeight = clipHeight * dpi / 2;wx.createSelectorQuery()  .select('#myCanvas')  .fields({ node: true, size: true })  .exec((res) => {    const canvas = res[0].node;    // 渲染上下文    const ctx = canvas.getContext('2d');
   // 初始化画布大小    canvas.width = renderWidth;    canvas.height = renderHeight;    ctx.clearRect(0, 0, renderWidth, renderHeight);
   // 图片对象    const image = canvas.createImage();    // 图片加载完成回调    image.onload = () => {      // 将图片绘制到 canvas 上      ctx.drawImage(        image,        clipLeft * dpi / 2, clipTop * dpi / 2, renderWidth, renderHeight,        0, 0, renderWidth, renderHeight,      );      const newBase64 = canvas.toDataURL('image/jpeg');    };    // 设置图片src    image.src = base64;  });

通过 小程序 XR-Frame 框架,我们能够实现扫描实体卡出现流畅的 AR 视频流效果,开发门槛更低,性能表现更好。欢迎各位开发者接入使用!

Image

如有更多关于小程序的问题,可在 小程序交流专区 发帖互动,技术专员将为大家解答及进行深度交流。

原创|腾讯前端工程师 teeniechen、manmanyu

Image