针对网络的增强现实

Joe Medley
Joe Medley

在 Chrome 67 中,我们宣布了适用于增强现实 (AR) 和虚拟现实 (VR) 的 WebXR Device API,但当时仅启用了 VR 功能。VR 是一种完全基于计算设备中内容的体验。另一方面,AR 可让您在现实世界中呈现虚拟对象。为了允许放置和跟踪这些对象,我们刚刚向 Chrome Canary 添加了 WebXR Hit Test API,这是一种新方法,可帮助沉浸式 Web 代码在现实世界中放置对象。

在哪里可以获取?

此 API 预计近期将保留在 Canary 中。我们希望延长测试期限,因为这是一个全新的 API 提案,我们希望确保其既可靠又适合开发者。

除了 Chrome Canary 之外,您还需要:

  • 一部搭载 Android O 或更高版本的兼容智能手机
  • 安装 ARCore
  • 两个 Chrome flag (chrome://flags):WebXRDevice API (#webxr) 和 WebXR 点击测试 (#webxr-hit-test)

有了这些知识,您就可以深入了解演示或试用我们的 Codelab。

只是网站

在今年的 Google IO 大会上,我们展示了 Chrome 的早期 build 中的增强现实功能。在那三天里,我反复对开发者和非开发者说过一句话,现在想起来,我真希望当时就把这句话写进我的沉浸式网络文章中:“这只是网络。”

“我需要安装哪个 Chrome 扩展程序?”“没有扩展程序。这只是网络。”

“我需要使用特殊的浏览器吗?”“这只是网络。”

“我需要安装哪个应用?”“没有任何特殊应用,只是网页。”

这对您来说可能很明显,因为您是在专门介绍网络的网站上阅读本文。如果您使用以下新 API 构建演示,请做好准备来回答此问题。您会经常看到。

说到 IO,如果您想详细了解沉浸式 Web 的现状和未来发展,请观看此视频

它有什么用途?

增强现实将为许多现有网页增添宝贵价值。 例如,它可以帮助用户在教育网站上学习,让潜在买家在购物时直观地看到家中的物品。

我们的演示对此进行了演示。借助此类功能,用户可以放置与现实中一样大的物体,放置后,图片会保留在所选 Surface 上,显示的尺寸与实际物品在该 Surface 上时的尺寸相同,并且允许用户围绕图片移动,以及向图片靠近或远离图片。与二维图片相比,这让观看者可以更深入地了解对象。

如果您不确定我所说的这些内容的含义,在使用演示版后就会明白。如果您没有可以运行演示版的设备,请查看本文顶部的视频链接。

演示和视频未展示的一件事是,AR 如何传达真实物体的大小。此视频展示了我们构建的教育演示版 Chacmool随附文章详细介绍了此演示。本讨论中的重要一点是,当您将 Chacmool 雕像放置在增强现实中时,您看到的尺寸就像它实际上就在您所在的房间中一样。

Chacmool 示例具有教育性,但同样可以用于商业用途。假设有一个家具购物网站,可让您在客厅中放置沙发。AR 应用会告诉您沙发是否适合您的空间,以及它在其他家具旁边的样子。

光线投射、命中测试和准星

实现增强现实时需要解决的一个关键问题是如何将对象放置在真实视图中。用于执行此操作的方法称为光线投射。光线投射是指计算指针光线与真实世界中的表面之间的相交点。该交叉点称为“命中”,确定是否发生了命中是“命中测试”。

不妨趁此机会在 Chrome Canary 中试用新的代码示例。在执行任何操作之前,请仔细检查您是否已启用正确的标志。现在,加载示例并点击“开始 AR”。

请注意以下几点。首先,您可能在其他沉浸式体验示例中看到过的速度计显示的是每秒 30 帧,而不是 60 帧。这是网页从相机接收图片的速率。

AR 以每秒 30 帧的速率运行

AR 点击测试演示

您还应该注意向日葵图片。它会随着您的移动而移动,并贴合地板和桌面等表面。如果您点按屏幕,系统会将一朵向日葵放置在平面上,然后新的向日葵会随设备移动。

随设备移动并尝试锁定到表面的图片称为十字准星。十字准星是一种临时图片,可帮助您在增强现实中放置对象。在此演示中,十字线是要放置的图片的副本。但这并非必然。例如,在 Chacmool 演示中,它是一个矩形框,形状与放置的对象底部大致相同。

进入代码

Chacmool 演示展示了 AR 在正式版应用中的可能外观。幸运的是,WebXR 示例代码库中有一个更简单的演示。我的示例代码来自该代码库中的 AR 点击测试演示。请注意,我会简化代码示例,以便帮助您了解所发生的情况。

进入 AR 会话和运行渲染循环的基本操作与 VR 相同。如果您不熟悉,可以参阅我之前的文章。更具体地说,进入和运行 AR 会话与进入 VR 魔法窗口会话几乎完全一样。与魔术窗口一样,会话类型必须是非沉浸式,并且引用类型的帧必须为 'eye-level'

新 API

现在,我将向您展示如何使用新 API。回想一下,在 AR 中,准星会在放置物品之前尝试查找平面。这可以通过命中测试来完成。如需执行点击测试,请调用 XRSession.requestHitTest()。如下所示:

xrSession.requestHitTest(origin, direction, frameOfReference)
.then(xrHitResult => {
  //
});

此方法的三个参数代表一条光线投射。光线投射由光线上的两个点 (origindirection) 以及这些点的计算位置 (frameOfReference) 定义。起点和方向都是 3D 矢量。无论您提交的值是什么,系统都会将其归一化(转换)为长度为 1 的值。

移动十字线

当您移动设备时,十字准星需要随之移动,以便尝试找到可放置对象的位置。这意味着,必须在每一帧中重新绘制瞄准镜。

requestAnimationFrame() 回调开始。与 VR 一样,您需要一个会话和一个姿势。

function onXRFrame(t, frame) {
  let xrSession = frame.session;
  // The frame of reference, which was set elsewhere, is 'eye-level'.
  // See onSessionStarted() ins the sample code for details.
  let xrPose = frame.getDevicePose(xrFrameOfRef);
  if (xrPose && xrPose.poseModelMatrix) {
    // Do the hit test and draw the reticle.
  }
}

获得会话和姿势后,确定光线投射的位置。示例代码使用 gl-matrix 数学库。但 gl-matrix 不是必需的。重要的是了解您要用它计算什么,以及它是根据设备的位置计算的。从 XRPose.poseModalMatrix 检索设备位置。准备好光线投射后,调用 requestHitTest()

function onXRFrame(t, frame) {
  let xrSession = frame.session;
  // The frame of reference, which was set elsewhere, is 'eye-level'.
  // See onSessionStarted() ins the sample code for details.
  let xrPose = frame.getDevicePose(xrFrameOfRef);
  if (xrPose && xrPose.poseModelMatrix) {
    // Calculate the origin and direction for the raycast.
    xrSession.requestHitTest(rayOrigin, rayDirection, xrFrameOfRef)
    .then((results) => {
      if (results.length) {
        // Draw for each view.
      }
    });
  }
  session.requestAnimationFrame(onXRFrame);
}

虽然在点击测试示例中不太明显,但您仍然需要循环遍历视图来绘制场景。绘制是使用 WebGL API 完成的。如果您有雄心壮志,可以这样做。不过,我们建议您使用框架。沉浸式 Web 示例使用的是专为演示而创建的 Cottontail,而 Three.js 自 5 月起就支持 WebXR。

放置对象

当用户点按屏幕时,系统会将对象放置在 AR 中。为此,您可以使用 select 事件。在此步骤中,重要的是知道将其放置在何处。 由于移动的准星会为您提供恒定的碰撞测试来源,因此放置对象的最简单方法是在上次碰撞测试时准星的位置绘制该对象。如果您需要(例如,您有正当理由不显示瞄准镜),可以在选择事件中调用 requestHitTest()如示例所示

总结

如需掌握此概念,最好的方法是逐步调试示例代码或尝试Codelab。希望我提供的背景信息足以让您了解这两者。

我们还在不断构建沉浸式 Web API,而且远远没有完成。我们会随着进展在此处发布新文章。