20. WebAR那些事: 一个40行的ARDemo

紧接上文

WebVR+Three.js可以快速高效的搭建VR场景,降低了初学者的准入门槛,节省多平台重复开发,开始了H5在VR的新时代。

本次Demo所需二维码

用户可以本地启动HTTP服务,将URL填写到播放路径
本次demo已经集成到APK中,用户可以点击《AR地球》来体验
20. WebAR那些事: 一个40行的ARDemo

AR地球

环境准备

  1. Demo使用r82版本,向下兼容
  2. Three.js 到http://www.threejs.org下载最新源码,这里使用three.min.js作为渲染引擎。
  3. WebVR.js WebVR的工具库,用于切换VR状态(three.js的源码包中,自己拷贝)
  4. VREffect.js WebVR的展示库,用于分屏展示(three.js的源码包中,自己拷贝)
  5. VRControls.js WebVR的控制库,用于监控陀螺仪、Camera、重力等(three.js的源码包中,自己拷贝)

纹理准备

可以使用其他3D模型,为了方便起见,我们使用老的模型

  1. 地球纹理,在网上可以找到最新的地图纹理,最好使用4k,比较清晰
    20. WebAR那些事: 一个40行的ARDemo

兼容性准备

常见的浏览器对摄像头的支持,良莠不齐,这里只是简单的支持了一种API标准

捕获音视频接口: Navigator.getUserMedia

点击进入: Mozilla官方使用文档
使用方法:

var params = { video: true, video: { width: 1280, height: 720 } };
window.navigator.getUserMedia(params, function(stream) {
    var video = document.querySelector('video');
    video.src = window.URL.createObjectURL(stream);
    video.onloadedmetadata = function(e) {
        video.play();
    };
});

兼容性分析

Navigator.getUserMedia接口目前Safari是不支持的,常见的浏览器使用摄像头,往往通过Flash插件来完成。所以这些代码不一定能够成功运行在用户的浏览器上,但没有关系,我们的的WebVRSDK已经提供了支持,开发者可以放心的使用。
Navigator.getUserMedia已经废弃了,使用MediaDevices.getUserMedia来取代。因为我对Promise原理不是很清楚,所以暂时只支持Navigator.getUserMedia。
开发者需要提前申请App的Camera权限,Android6.0以后支持动态权限管理,开发者需要确保App拥有Camera的使用权限,最直接的的办法是在设置中手动的打开权限,否则背景会出现黑屏。

准备空白的html

我们会将所有JS代码写在单独的index.js中,因此index.html只是提供JS运行的环境,这一步为代码迁移到WebVRSDK做准备。代码如下:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebGL Earth</title>
    <style>
        body { margin: 0; overflow: hidden; background-color: #000; }
    </style>
</head>
<body>
    <script src="three.js"></script>
    <script src="WebVR.js"></script>
    <script src="VREffect.js"></script>
    <script src="VRControls.js"></script>
    <script src="index.js"></script> 
</body>
</html>

index.js核心代码

  1. 代码行数控制在40行以内
  2. 渲染器,使用WebGL渲染three.js中的3D对象
  3. 加载器,使用XMLHttpRequest或者Image,异步加载图片纹理
  4. 摄像机,模拟观察者的位置和方向,从不同角度来观看3D世界
  5. 控制器,接受用户点击、触摸、鼠标等事件,控制摄像机的参数,实现人机交互
  6. 材料,任何3D对象,是由骨骼和图像组成,材料就像油漆,粉刷过的对象更加真实
  7. 几何,3D对象的结构描述,这里只用球状几何
  8. 场景,用来管理所有需要展示的3D对象,以及他们之间的层级和关系
  9. video标签,用于承载摄像头内容的呈现

代码如下

var w = window.innerWidth;
var h = window.innerHeight;
var renderer = new THREE.WebGLRenderer();        // 创建渲染器
renderer.setSize(w, h);                            // 设置渲染器为全屏
document.body.appendChild(renderer.domElement);    // 将渲染器添加到body上

var camera    = new THREE.PerspectiveCamera(45, w / h, 0.01, 100);
var effect    = new THREE.VREffect(renderer);        // 控制器,用来控制VR渲染
var loader    = new THREE.TextureLoader();        // 加载器,用于异步加载图片
var control    = new THREE.VRControls(camera);        // 控制器,用来控制摄像机

var mater = { map : new THREE.TextureLoader().load('earth_map.jpg') };
var earth = new THREE.Mesh(new THREE.SphereGeometry(20, 32, 32), new THREE.MeshBasicMaterial(mater));
earth.position.x = -100;

var scene  = new THREE.Scene();                    // 创建场景
scene.add(earth);                                // 添加地球
scene.add(new THREE.AmbientLight(0xFFFFFF));    // 创建环境光

window.navigator.getUserMedia({ audio : true, video: { width: w, height: h }}, function(stream) {
    var video = document.createElement('video');
    video.src = stream;
    video.play();

    var image = new THREE.VideoTexture(video);
    image.generateMipmaps = false;
    image.format    = THREE.RGBAFormat;
    image.maxFilter = THREE.NearestFilter;
    image.minFilter = THREE.NearestFilter;
    scene.background = image;                    // 背景视频纹理
}, null);

animate();
function animate() {
    effect.requestAnimationFrame(animate);
    control.update();
    earth.rotation.y += 0.002;
    effect.render(scene, camera);
}

用浏览器打开index.html

在Safari上是无法打开的,因为navigator没有成员函数:getUserMedia
开发者可以添加判断,因为WebVRSDK我添加了支持,所以就不判断了,代码如下:

navigator.getUserMedia = navigator.getUserMedia        ||
                         navigator.mozGetUserMedia    ||
                         navigator.webkitGetUserMedia;

if (navigator.getUserMedia) {
    ....
}

效果展示

悬浮的3D地球
20. WebAR那些事: 一个40行的ARDemo

畅想

AR距离我们很近

AR翻译过来是增强现实,简单一点说,就是在摄像头捕获的视频或者图片中,加入3D效果,并融入背景。就像二次元或者三次元一样,给用户带来更多的欢乐。

如果我们把3D地球换成一只可爱的猫咪,是不是就是淘宝双十一的抓猫猫游戏了?

下一回

我们把地球换成一个复杂的3D模型,并想办法让TA动起来,就像淘宝双十一的AR抓猫猫一样,会动会跳,还会发红包。

上一篇:让你的 Qt 桌面程序看上去更加 native(六):跨平台技术


下一篇:NitroShare —— 跨平台的局域网文件传输工具