虚拟现实(Virtual Reality,VR)将人们带到了另一个世界,让大家体验到自己就好像置身于虚拟世界中的感觉。而增强现实(Augmented Reality,AR)提供了将现实世界和虚拟世界融合在一起的可能性。例如:直播、社交、以及艺术等场景,可以说,VR和AR都为人类行为的改变、知识的转移、培训、以及研究,提供了独特的机会与方式。不过,所有这些应用如今都可以在浏览器中实现了。下面,我将以渐进式Web应用为基础,使用A-Frame和WebXR的Web API与您深入探究。
什么是A-Frame?
A-Frame是一个基于HTML的、可用于构建VR和AR体验的Web框架。从本质上说,它是一个强大的实体框架,提供了可扩展和可重用的结构。由于A-Frame建立在WebXR和Three.js之上,因此开发者可以不受限制地访问JavaScript、DOM API、three.js、WebXR和WebGL。其中,WebXR是一种可用于在浏览器中创建VR和AR体验的Web API,Three.js是一种VR/AR框架,而WebGL则负责渲染。
如何上手?
您可以在无需额外安装的情况下,通过HTML文件来开发A-Frame应用。“A-Frame学校”提供了丰富的A-Frame学习资源。您可以通过Glitch上的“入门示例”,来了解和试用A-Frame。此处的Glitch是一个适用于JavaScript和Node.js的在线式IDE。
A-Frame中的ECS
基于ECS架构的A-Frame常被用于开发3D游戏。此处的ECS(实体-组件-系统,Entity-component-system)架构是一种遵循“组合优于继承(composition over inheritance)”原则的模式。也就是说,每个实体都是由组件所组成,并可以链接到容器的对象上。作为可重用的模块,组件可以链接到实体上,以向实体提供相应的功能。
所有逻辑都是通过组件实现的。我们可以通过配置和混合组件,来定义不同类型的实体。其中,A-Frame通过提供如下API,来代表ECS的各个部分:
- 用元素来表示实体
- 用上的HTML属性来表示组件
实体的抽象例子:
下面让我们来查看一些使用各种组件,来构建实体的抽象示例。其中Sphere(球体)是一个实体,而Position、Geometry和Material是该实体的组成部分。
Sphere = Position + Geometry + Material
Ball = Position + Velocity + Physics + Geometry + Material
A-Frame中的语法实体
如下代码段所示,我们根据前面的示例,创建了Sphere实体的语法:
HTML
<a-entity geometry="primitive: sphere; radius: 1.5"
material="color: white; shader: flat; src: glow.jpg"
position="0 0 -5"></a-entity>
代码清单 1
可见,要绘制该球体,您需要定义一个,并将组件添加为HTML属性。通常,大多数组件都会有多个属性,并使用类似于CSS的语法来表示。
几何体(Primitives)
A-Frame提供了诸如或等几何体元素。它们是一些方便初学者在A-Frame中使用的HTML元素,可被用于包装底层的实体组件。如下代码段展示了几何体 被包含在带有各种几何体和物料组件的之下。
HTML
Primitive:
<a-box color="red" width="3"></a-box>
Entity:
<a-entity geometry="primitive: box; width: 3" material="color: red"></a-entity>
代码清单 2
在DeBrowser中构建VR场景
下面,让我们来构建一个包含了各种实体和动画的基本A-Frame VR场景(如下图所示)。
图 1
首先,我们需要为此项目创建一个文件夹。接着,在该“项目文件夹”中创建一个index.html文档,并将如下HTML代码放入其中:
HTML
<html>
<head>
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
</head>
<body>
<a-scene>
</a-scene>
</body>
</html>
代码清单 3
我们需要将最新版本的A-Frame作为脚本标签,包含在中,并且在中包含标签。
什么是场景?
所有实体和组件都必须被添加到待渲染的场景中。在A-Frame中,场景是由实体表示的。能够为我们处理三个.js和WebXR样板,其中包括设置WebGL(负责渲染)、画布、相机、灯光、渲染器、渲染循环、以及针对HTC Vive、Oculus Rift、Samsung GearVR等平台开箱即用(out-of-the-box)的WebXR支持。
通过Entity类,场景实体继承了其所有属性、链接组件的能力、以及在开始渲染循环之前,等待其所有子实体和节点(例如和)的加载行为。
添加实体
在我们的中,您可以使用A-Frame的一种默认几何体(如)来添加各种3D实体。如下代码段定义了的颜色。
HTML
<a scene>
<a-box color="red"></a-box>
</a scene>
代码清单 4
图 2
如上图可见,由于相机和都默认位于0、0、0原点上,那么在未对其移动之前,您将无法看到该盒子。因此,您可以通过使用“位置组件(position component)”将box转换为3D形式的空间展示。
在3D中转换实体
让我们先来看看3D空间。如下图所示,A-Frame使用的是右手坐标系,即默认的相机方向为:X轴正方向向右延伸,Y轴正方向向上延伸,Z轴正方向向着我们伸出屏幕:
图 3
使对相机可见
我们需要让盒子对于相机可见、可旋转并可缩放。首先,为了使其可见,您可以使用位置组件在负Z轴上将盒子向后滑动5米。同时,您还应该在正Y轴上,将盒子向上移动2米,这样盒子就不会与底面相交。
为了使其可旋转与缩放,我们同样需要使用相同的右手坐标系,将盒子倾斜并让其尺寸翻倍(如下代码段所示)。
HTML
<a-scene>
<a-box color="red" position="0 2 -5" rotation="0 45 45" scale="2 2 2">
</a-box>
</a-scene>
代码清单 5
由于WebXR的API是以米为单位来返回位置的,因此A-Frame的距离单位也是“米”。在为VR设计场景时,我们需要考虑实体的真实世界缩放。一个height="10" 的盒子,在你的桌面上也许看起来很正常,但是在VR中就显得过大了。此外,旋转的单位为“度”,不过它在转换到three.js时,则会在内部被转换为弧度。
父子转换
A-Frame的HTML也可以表示3D场景图。在场景图中,实体可以有一个父级和多个子级。子实体能够从其父实体处继承各种变换(包括:位置、旋转和缩放)。例如,我们可以将某个“球体”作为某个盒子的子元素(如下图所示):
HTML
<a-scene>
<a-box position="0 2 0" rotation="0 45 45" scale="2 4 2">
<a-sphere position="1 0 3"></a-sphere>
</a-box>
</a-scene>
代码清单 6
由计算可知,球体的位置为1、2、3。这是通过将球体的父位置与其自身位置组装在一起而实现的。同样,球体将会继承盒子的旋转和缩放。
添加环境组件
A-Frame允许开发人员创建各种可以让其他人轻松使用的可重用组件。例如:环境组件就能够通过一行HTML代码,为我们生成了各种环境。它不但方便我们便捷地启动VR应用,而且提供了十多种具有众多参数的环境。
为此,我们首先需要添加带有脚本标签的环境组件。通过unpkg.com,您可以获得指向相关npm模块的最新CDN链接(如下代码段所示)。
HTML
<head>
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-environment-component/dist/aframe-environment-component.min.js">
</script>
</head>
代码清单 7
然后,如下代码段所示,请在由环境组件链接到的标记中,添加一个a-entity。您可以指定诸如preset:forest的预设环境,以及“树木数量”到“修整量”等许多其他参数。
HTML
<a-scene>
<a-box color="red" position="0 2 -5" rotation="0 45 45"
scale="2 2 2"></a-box>
<!-- Out of the box environment! -->
<a-entity environment="preset: forest; dressingAmount: 500"></a-entity>
</a-scene>
代码清单 8
预设是定义特定样式的参数值组合,它们是您实现自定义的起点。您可以按下ctrl+alt+i,调用检查器(Inspector)来调整这些参数。如下图所示,作为一种用于检查和调整实体/组件的工具,检查器类似于浏览器的DOM检查器,不过它是专为3D和A-Frame量身定制的。
图 4
添加资产管理系统
您可以使用元素将纹理(texture)应用到box中。其中,资产管理(Asset Management)可以在渲染场景之前,加载和缓存图像和视频。预加载和缓存的方式可提高性能。如下代码段便是如何将资产管理应用到图像上的示例:
HTML
<a-scene>
<a-assets>
<img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg">
</a-assets>
<a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2">
<a-sphere position="1 0 3"></a-sphere>
</a-box>
<a-entity environment="preset: forest; dressingAmount: 500"></a-entity>
</a-scene>
代码清单 9
上面定义了一个带有图像纹理的标签。如下图所示,该img有一个id="boxTexture"。该id会以src="#boxTexture"方式被引用到盒子中。
图 5
添加动画
如代码清单10所示,您可以使用动画组件为盒子和球体设置动画,例如,通过设置如下内容,让盒子可以上下移动:
- 设置属性:object3D.position.y; to: 2.2,实现盒子在Y轴上的2到2.2米之间移动。
- 在方向(dir)上可以交替上升和下降。
- 将2000毫秒设置为持续一个周期的时长。
- 用loop指定动画的无限重复。
HTML
<a-scene>
<a-assets>
<img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg">
</a-assets>
<a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2"
animation="property: object3D.position.y; to: 2.2; dir: alternate; dur: 2000; loop: true">
<a-sphere position="1 0 3"></a-sphere>
</a-box>
<a-entity environment="preset: forest; dressingAmount: 500"></a-entity>
</a-scene>
代码清单 10
上述代码的最终运行结果,如下图所示,您也可以在Glitch中查看到。
图 6
增强现实
当然,A-Frame也可以实现AR的体验。同样,您可以参考Glitch上给出了入门示例,作为实现AR的起点。
图 7
此示例已针对AR的“命中测试(hit testing)”应用进行了扩展。其结果可以在如下代码段中查看到。其中的粗体部分为添加的内容。当然,您也可以通过链接--https://glitch.com/edit/#!/ar-basic-hittest,参考glitch中的具体实现过程。此外,您还可以通过URL--https://ar-basic-hittest.glitch.me/,在自己的手机上测试其最终版本。
HTML
<html>
<head>
</head>
<body>
<a-scene webxr="optionalFeatures: hit-test">
<a-entity id="world" scale="0.1 0.1 0.1">
<a-box color="#4CC3D9" position="-1 0.5 0" rotation="0 45 0"></a-box>
<a-sphere color="#EF2D5E" position="0 1.25 -2" radius="1.25"></a-sphere>
<a-cylinder color="#FFC65D" height="1.5" position="1 0.75 -0"
radius="0.5"></a-cylinder>
<a-plane color="#7BC8A4" height="4" position="0 0 -1" rotation="-90 0 0"
width="4"></a-plane>
</a-entity>
<a-entity ar-hit-test="target:#world;">
<a-plane height="0.2" material="transparent:true" rotation="-90 0 0"
src="./arrow.png" width="0.2"></a-plane>
</a-entity>
</a-scene>
</body>
</html>
代码清单 11
什么是AR命中测试?
命中测试可以将虚拟对象与现实世界中的对象(如地板、桌子和墙壁等)相对齐。在下面的示例中,您可以将上图 7 中的对象内嵌放置到桌上。其方法是通过相机,使用十字线瞄准桌子,然后定位该桌子(即命中测试)。
在AR中进行命中测试前,您需要首先在脚本标签中包含ar-components.js。您可以直接从Glitch处复制此库--https://glitch.com/edit/#!/ar-basic-hittest。
在场景标签中,您应当通过hit test命令,指明要用到的WebXR功能。然后通过a-entity去应用对象的真实比例。
最后,请使用组件定义一个新实体:ar-hit-test。该组件可以将虚拟对象内联并放置在您通过相机看到的真实对象上,如下图所示。为了支持命中测试,请通过a-plane组件去定义一个20厘米的正方形标线。
图 8
展望
A-Frame还可以实现更多的VR和AR应用。您可以通过链接--https://aframe.io/,查阅到更多的示例和文档。例如,您可以使用命中测试去制作“AR篮球游戏”等。
译者介绍
陈 峻 (Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验;持续以博文、专题和译文等形式,分享前沿技术与新知;经常以线上、线下等方式,开展信息安全类培训与授课。
原文标题:Virtual Reality and Augmented Reality in the Browser,作者:Peter Eijgermans