WebXR 开发者的视角回顾

由于 WebXR 使用 WebGL 来渲染构成通过 XR 硬件显示的 3D 环境的视图,因此很容易认为视角相关的问题与任何 WebGL 项目中的问题相同。这在很大程度上是正确的,但有几个特定的主题需要重新审视,并且需要考虑一些小的附加指南,以确保您的应用程序看起来正确,更重要的是,您的 3D 世界不会因为眩晕或其他效果导致人们生病,这些效果会在所见内容与大脑预期现实不符时发生。

在本文中,我们将探讨您的项目计算、应用和思考视角的方式可能与为非 XR 应用程序编写的代码不同的场景。

视锥体的困扰

每个 WebXR 会话(由 XRSession 对象表示)都提供一组可以通过创建新的 XRRenderState 对象来配置的选项,并通过调用会话的 updateRenderState() 方法来激活更新后的状态,以替换当前配置。

这些值中的大多数定义了 XR 设备的 视锥体;也就是说,应该渲染的设备视野的子集。视锥体可以使用四个关键数据点来表示:视场角、渲染图像的 纵横比,以及近剪切平面和远剪切平面的距离。

欢迎来到投影矩阵

大多数情况下,您将使用的投影模型是透视投影模型,因此其投影矩阵称为透视投影矩阵。此矩阵用于将 3D 虚拟世界中的每个像素映射到正在渲染的视图的 2D 后台缓冲区中的一个点。

在典型情况下,您可以并且应该直接从您正在渲染的视图中获取透视投影矩阵。 XRView 对象的 projectionMatrix 属性包含表示视图透视的投影矩阵,并且几乎应该始终按原样使用。对 XRView 提供的投影矩阵所做的更改很可能导致渲染内容相对于现实世界的风景出现失真或对齐不佳;这可能足够严重,至少会导致您的某些用户出现 虚拟现实疾病

例如,如果您的应用程序使用名为 uProjectionMatrix 的 WebGL uniform 将投影矩阵传递给您的着色器,您可以使用类似以下的代码来传递当前正在渲染的视图的投影矩阵

js
gl.uniformMatrix4fv(uProjectionMatrix, false, view.projectionMatrix);

自定义投影矩阵

虽然通常应避免手动构建或修改视图提供的投影矩阵,但在某些情况下可以这样做。最常见的原因可能是为了出于性能原因更改近剪切平面和远剪切平面的距离,以增加或减少要渲染的多边形数量。当游戏提供调整观看距离的首选项时,就是通过更改这些平面距离值来实现的。

在沉浸式模式下,WebXR 系统从硬件供应商提供的软件中获取默认的 视锥体。此视锥体基于设备的镜头、显示硬件和摄像头的某种组合。从图像传感器的尺寸到镜头的焦距,一切都参与了此计算。

沉浸式体验使用硬件定义的视场、焦距等,因此在使用沉浸式会话时,您只能更改近剪切距离和远剪切距离。这是通过设置 XRRenderState 属性 depthNeardepthFar 的值来完成的。

在内联模式下,您还可以通过设置 renderStateinlineVerticalFieldOfView 属性的值来直接更改视场。对于任何沉浸式会话,此属性需要设置为 null

一旦有了视锥体,您就可以使用像下面这样的函数来计算 WebGL 在渲染场景时使用的投影矩阵

js
function makePerspectiveMatrix(fieldOfViewInRadians, aspectRatio, near, far) {
  const f = 1.0 / Math.tan(fieldOfViewInRadians / 2);
  const rangeInv = 1 / (near - far);

  return [
    f / aspectRatio,
    0,
    0,
    0,
    0,
    f,
    0,
    0,
    0,
    0,
    (near + far) * rangeInv,
    -1,
    0,
    0,
    near * far * rangeInv * 2,
    0,
  ];
}

nearfar 的值直接从视锥体获得;它们分别是原点到近剪切平面和远剪切平面上最近点的距离。纵横比是通过将视场宽度除以其高度获得的值。如果目标显示器使用 16:9 的纵横比,则用于 aspectRatio 的值应为 16/9,即 1.7777777778。

如果您使用的是提供矩阵数学函数的库或框架,它几乎肯定会有一个类似的函数。例如,在流行的 glMatrix 库中,您会在函数 mat4.perspective() 中找到它。

无论它来自哪里,一旦您获得了投影矩阵,就可以在使用 WebGL 渲染场景时使用它。

与现实保持一致

在增强现实 (AR) 应用程序中,您渲染的内容会叠加在现实世界之上。要做到这一点,您的视角计算需要与观看者对周围世界的视角相匹配。否则,您的对象将无法正确地与现实对齐。

如果您的虚拟摄像头的透视投影矩阵不能使虚拟对象具有与现实世界相同的视观效果,那么虚拟世界和物理世界之间的差异可能会令人不适,甚至更糟的是,会在您的应用程序用户中引起眩晕、晕动症或其他形式的不适。

一个相关的问题是,如果您使用透视矩阵来确定对象的位置,那么您的透视投影矩阵与用户对世界的物理视角之间的不匹配可能导致对象放置不准确。例如,如果您的应用程序允许用户在墙上挂虚拟画作,但透视矩阵不匹配,那么放置的画作可能实际上不会贴在墙上,会部分与墙体相交,或者一端比另一端更靠近墙壁,而不是与墙壁平行。

另见