评论

Web与小程序AR技术原理

本文详细的为大家梳理了“AR” 的技术原理,并为想要了解AR技术的前端同学提供了一些基础的功能和代码实现,一起来看看吧~

AR(Augmented Reality增强现实)技术,能够将虚拟数字信息与真实世界信息无缝连接,将虚拟物体带入现实中与用户进行互动。凭借其丰富真实的交互体验,AR技术成为了各大品牌的营销利器。

今天,我们就来简单梳理一下“AR” 究竟是一项什么样的技术原理,并为想要了解AR技术的前端同学提供了一些基础的功能和代码实现,一起来看看吧~

本文章适合于对AR技术还不甚了解的读者哦

AR效果的构成

由上面的视频可知,AR主打的效果就是“虚实融合”,那么有三个技术部分是必不可少的:

  1. Camera画面 - 呈现真实的现实画面,作为“实”的部分存在。一般来说,就是打开用户设备的摄像头即可(特殊情况下,也可以是视频流等其他介质)。
  2. 虚拟信息 - 呈现仿真的虚拟内容,作为“虚”的部分存在。一般来说和现实内容存在逻辑上的关联,会尽力做到真实、有趣或观赏度高,这也是AR技术最吸引人的部分。常用3D模型、透明特效视频、普通视频、容积视频、图片等作为介质。
  3. AR图像算法 - AR技术的核心部分,用来将现实内容与虚拟内容进行关联、追踪或融合,目的就是两者绑定,而不是独立的出现或运行。只有具备“虚实融合算法”的能力,才能展示出“增强现实”的质感。

Camera技术

原理上来说,展示Camera画面是独立且和平台相关的技术,且Android/iOS/Web/小程序各不相同。

     Android需要使用CameraManager获取Camera数据流CameraCaptureSession,并使用TextureView来呈现出Camera画面。

     iOS需要使用AVCaptureDevice来获取Camera数据流AVCaptureSession,并使用AVCaptureVideoPreviewLayer来呈现Camera画面。

     Web上则需要使用mediaDevices来获取Camera数据流MediaStream,并使用video标签来呈现出Camera画面。

     小程序则可以使用camera组件,直接呈现出Camera画面。而获取Camera数据流,则需要使用CameraContext.onCameraFrame

我们以表格的形式来简单的总结一下:

从表格中可以看出,Camera部分的技术的三个技术点:

  1. Camera硬件控制的API - 打开、关闭、闪光、对焦等。
  2. 展示Camera画面的UI - 呈现给用户。
  3. Camera的数据流 - 这是最为重要的部分,我们需要从数据流中,获取当前一帧画面的bitmap(可以简单理解为一张截图),拿给AR图像算法进行计算,得出一个4x4跟踪矩阵。而这个追踪矩阵,就用来实现出虚实融合的效果。

虚拟信息技术

为了打造更真实的虚实融合效果,虚拟部分最重要的特点就是要有3D感,否则一个平面2d UI 是无法和真实内容产生出你中有我,我中有你的融合感。因此常用的UI渲染技术在AR内容中基本不会使用。

我们通常会使用3D渲染的技术,这门技术广泛应用于游戏、仿真模拟、电影制作等领域,而实现这门技术的常用方案,就是渲染引擎,或者游戏引擎。

和Camera技术不同的是,通常渲染引擎都可以跨平台支持。比如常见的一些游戏引擎:Unity3D、Unreal、寒霜、CE等等。

特别是Unity3D,在开发App(Android/iOS)的AR领域,Unity3D是大多数人的首选方案。所以当你在网上搜索AR技术时,能看到很多和Unity3D引擎相关的文章。

遗憾的是,虽然Unity3D支持Web平台,但AR算法很少有适配于Web平台的,就导致了AR算法在Web平台不能使用。那么如果只使用Unity3D的渲染能力,又会特别笨重(资源大和加载慢),且相关插件少。并且对前端开发而言,需要学习一门全新的语言(C#)和平台(Unity3D),成本就变得很高。

那么在小程序/Web平台上,有没有类似于Unity3D的渲染引擎呢?

市面上虽然存在不少,但各方面来说,都没有Unity3D效果好。主要地,Three.js流行度和市占率可能是领先的,但Babylon.js也紧随其后(某些方面还会更好)。

对于前端开发来说,3D渲染已经完全是不同的技术领域,目前了解知道的人多,但善于此道且精通的就非常少了。

接下来,我们就分别演示一下在Web和小程序平台开发AR效果时,最基础的一些功能和代码实现。

WebAR开发


打开摄像头

// 打开后置摄像头
const stream = await navigator.mediaDevices.getUserMedia({
    video: { ideal: "environment" }
});
// 呈现Camera画面
const video = document.createElement("video");
video.srcObject = stream;
document.body.appendChild(video);

重要限制:需要网页以https协议或者localhost域名打开,这样才存在navigator.mediaDevices对象,否则为undefined。


渲染3D场景

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.domElement.style = "position:absolute;left:0;top:0;width:100%;height:100%";

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.positiin.z = -5;

function animate() {
    renderer.render(scene, camera);
    requestAnimationFrame(animate);
};

animate();


AR图像算法达成虚实融合效果

const canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const ctx = canvas.getContext("2d"); 

cube.matrixAutoUpdate = false;
cube.frustumCulled = false;
cube.onBeforeRender = () => {
    // 获取Camera当前一帧画面数据
    ctx.drawImage(video, 0, 0);
    const cameraFrame = ctx.getImageData(0, 0, canvas.width, canvas.height);

    // 利用AR图像算法,输入Camera画面数据,计算出追踪矩阵,再赋值给3D内容。
    // 这样,真实内容和虚拟内容,就融合在了一起。
    const trackMatrix = SomeArAlgorithm.tracking(cameraFrame);
    cube.matrix.copy(trackMatrix);
};

上述的示例代码仅供参考,可以提供WebAR技术应用层的基本实现思路。实际可用代码参考:https://meta.kivisense.com/basic-ar/index.html


小程序AR开发


打开摄像头

<camera resolution="high" frame-size="medium"></camera>
<canvas type="webgl" id="webgl"></canvas>


渲染3D场景

import { createScopedThreejs } from "threejs-miniprogram";

Page({
    onReady() {
        wx.createSelectorQuery()
        .select('#webgl')
        .node()
        .exec((res) => {
            const canvas = res[0].node;
            const THREE = createScopedThreejs(canvas);
            this.init3d(THREE);
        });
    },

    init3d(THREE) {
        const scene = new THREE.Scene();
        const { windowWidth, windowHeight } = wx.getSystemInfoSync();
        const camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000);

        const renderer = new THREE.WebGLRenderer({ alpha: true });
        renderer.setSize(windowWidth, windowHeight);

        const geometry = new THREE.BoxGeometry();
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);
        cube.positiin.z = -5;

        function animate() {
            renderer.render(scene, camera);
            requestAnimationFrame(animate);
        };

        animate();
    }
});


AR图像算法达成虚实融合效果

const cameraCtx = wx.createCameraContext();
const listener = cameraCtx.onCameraFrame((cameraFrame) => {
    // 利用AR图像算法,输入Camera画面数据,计算出追踪矩阵,再赋值给3D内容。
    // 这样,真实内容和虚拟内容,就融合在了一起。
    const trackMatrix = SomeArAlgorithm.tracking(cameraFrame);
    cube.matrix.copy(trackMatrix);
    cube.matrixAutoUpdate = false;
});
listener.start();


同样,上述的示例代码仅供参考,为大家提供了小程序AR技术应用层的基本实现思路。实际可用代码参考:https://developers.weixin.qq.com/s/aAUxADmW7Nzs


Kivicube平台

在上面的示例中,AR内容仅仅只是一个非常简单的Cube,毫无实际意义。而在真实的商业项目中,我们还需要随机应变处理非常多的细节和功能。

比如:

  1. 多类型的素材支持,比如3D模型、普通视频、透明特效视频、精灵图、图片、天空盒、音乐等;
  2. 简单方便的场景搭建(拖拉拽即可);
  3. camera功能的多浏览器兼容;
  4. 渲染效果的多平台兼容;
  5. 模型材质的实时预览调节;
  6. 渲染效果的优化;
  7. 等等。

这些问题的处理对于大部分的前端开发人员来说,就进入了一个全新的,从未接触过的领域,需要的学习时间和精力是非常高的。

那么在低代码平台流行的今天,有没有这样一个既能提升开发效率,又能快速出效果的平台呢?

免费的AR在线编辑器——Kivicube - https://www.kivicube.com,就能大致满足大家的需求。

Kivicube既拥有可视化的低代码搭建平台,也能提供简单灵活的API,可供开发人员快速的实现需求交互。

微信小程序

在微信小程序端,平台提供了一个Kivicube小程序AR插件,直接以组件的形式,给到开发人员使用。

组件kivicube-scene可以直接打开在Kivicube平台制作好的AR场景。省去了开发人员自己处理Camera、3D渲染、AR算法、多类型素材支持等等相关的工作。

既然是组件的形式,自然而然的,如果有特殊的UI和交互需求(Kivicube平台暂不支持的),开发人员也可以自行实现。

插件与组件接入方式

在使用插件前,首先要在小程序管理后台的“设置-第三方设置-插件管理”中添加插件。开发者可登录小程序管理后台,通过 appid [wx3bbab3920eabccb2] 查找插件并添加。

之后,可在小程序的app.json配置文件之中,增加插件的声明配置,如下所示:

{
  ...
  "plugins": {
    "kivicube": {
      "version": "1.6.6",
      "provider": "wx3bbab3920eabccb2"
    }
  }
  ...
}


再在需要接入AR场景的页面中,配置好kivicube-scene组件,如下所示:

{
  "usingComponents": {
    "kivicube-scene": "plugin://kivicube/kivicube-scene"
  }
}


然后,就可以直接在页面的wxml中使用组件了。

<kivicube-scene
    class="kivicube"
    scene-id="9vR08tpLesfKVWs2XbbnNKSsX3JqpaAp"
/>

.kivicube {
    display: block;
    width: 100vw;
    height: 100vh;
}

通过上面很简短的几句代码,我们就实现了一个AR功能,由此可见,Kivicube平台带来的优势是很明显的。

组件需要通过sceneId属性指定打开的场景,而场景Id,需要在Kivicube平台获取。

Kivicube平台制作并保存场景之后,点击右上角"分享"按钮,然后点击"复制链接",在链接中最后一个正斜杠,之后的一串乱码字符,就是场景id了。 比如复制的链接为:https://www.kivicube.com/scenes/9vR08tpLesfKVWs2XbbnNKSsX3JqpaAp ,则9vR08tpLesfKVWs2XbbnNKSsX3JqpaAp 就是场景id。

更为详细的教程,请参考:https://www.yuque.com/kivicube

Web

我们正在准备Web端的AR插件能力,使AR在Web平台上的开发变得一样的简单快捷,并会在不久的将来与大家见面!


今天关于“AR”技术原理的讲解就到这里啦,欢迎各位前端同学试用并给我们提出宝贵建议~

同时也欢迎大家来免费注册使用Kivicube平台,使用低代码编辑器快速创建出专属于你的AR场景。



最后一次编辑于  2022-06-07  
点赞 7
收藏
评论
登录 后发表内容