Web与小程序AR技术原理
AR(Augmented Reality增强现实)技术,能够将虚拟数字信息与真实世界信息无缝连接,将虚拟物体带入现实中与用户进行互动。凭借其丰富真实的交互体验,AR技术成为了各大品牌的营销利器。 [图片] 今天,我们就来简单梳理一下“AR” 究竟是一项什么样的技术原理,并为想要了解AR技术的前端同学提供了一些基础的功能和代码实现,一起来看看吧~ 本文章适合于对AR技术还不甚了解的读者哦 AR效果的构成由上面的视频可知,AR主打的效果就是“虚实融合”,那么有三个技术部分是必不可少的: Camera画面 - 呈现真实的现实画面,作为“实”的部分存在。一般来说,就是打开用户设备的摄像头即可(特殊情况下,也可以是视频流等其他介质)。虚拟信息 - 呈现仿真的虚拟内容,作为“虚”的部分存在。一般来说和现实内容存在逻辑上的关联,会尽力做到真实、有趣或观赏度高,这也是AR技术最吸引人的部分。常用3D模型、透明特效视频、普通视频、容积视频、图片等作为介质。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部分的技术的三个技术点: Camera硬件控制的API - 打开、关闭、闪光、对焦等。展示Camera画面的UI - 呈现给用户。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,毫无实际意义。而在真实的商业项目中,我们还需要随机应变处理非常多的细节和功能。 比如: 多类型的素材支持,比如3D模型、普通视频、透明特效视频、精灵图、图片、天空盒、音乐等;简单方便的场景搭建(拖拉拽即可);camera功能的多浏览器兼容;渲染效果的多平台兼容;模型材质的实时预览调节;渲染效果的优化;等等。这些问题的处理对于大部分的前端开发人员来说,就进入了一个全新的,从未接触过的领域,需要的学习时间和精力是非常高的。 那么在低代码平台流行的今天,有没有这样一个既能提升开发效率,又能快速出效果的平台呢? 免费的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场景。