本文以渐进式Web应用程序为基础,和您讨论如何使用A-Frame和WebXR,来构建虚拟现实(VR)和增强现实(AR)。

虚拟现实(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 + MaterialBall = Position + Velocity + Physics + Geometry + Material1.2.

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.2.3.

代码清单 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>1.2.3.4.

代码清单 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>1.2.3.4.5.6.7.8.9.

代码清单 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>1.2.3.

代码清单 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>1.2.3.4.

代码清单 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>1.2.3.4.5.

代码清单 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>1.2.3.4.5.

代码清单 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>1.2.3.4.5.6.

代码清单 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>1.2.3.4.5.6.7.8.9.

代码清单 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>1.2.3.4.5.6.7.8.9.10.

代码清单 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>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.

代码清单 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