XRView

安全上下文:此功能仅在安全上下文(HTTPS)中可用,在某些或所有支持的浏览器中。

实验性:这是一种实验性技术
在生产环境中使用此功能之前,请仔细检查浏览器兼容性表

WebXR 设备 APIXRView接口描述了特定帧中 XR 场景的单个视图,提供了视点的方向和位置信息。您可以将其视为特定眼睛或相机的描述以及它如何观察世界。3D 帧将包含两个视图,每个眼睛一个,它们之间保持适当的距离,以近似模拟观察者眼睛之间的距离。这允许两个视图在单独投影到相应的眼睛中时,模拟一个 3D 世界。

实例属性

eye 只读 实验性

XRView表示的两个眼睛(left)或(right)中的哪一个。此值用于确保为呈现给特定眼睛而预先渲染的任何内容都正确分发或定位。如果XRView呈现单眼数据(例如 2D 图像、文本的全屏视图或不需要显示为 3D 的内容的特写视图),则该值也可以为none

isFirstPersonObserver 只读 实验性

返回一个布尔值,指示XRView是否为第一人称观察者视图。

projectionMatrix 只读 实验性

投影矩阵,它将转换场景以根据eye指示的视点正确显示。应直接使用此矩阵,以避免可能导致用户严重不适的呈现失真。

recommendedViewportScale 只读 实验性

如果用户代理有此建议,则可以用于requestViewportScale()的建议视口缩放值;否则为null

transform 只读 实验性

一个XRRigidTransform,它描述了视点相对于XRReferenceSpace的当前位置和方向,该空间在getViewerPose()在正在呈现的XRFrame上调用时指定。

实例方法

requestViewportScale() 只读 实验性

请求用户代理将此视口的请求视口缩放值设置为请求值。

使用说明

每帧的 XRView 位置和数量

在渲染场景时,用于在当前帧为观察者渲染场景的视图集是通过调用XRFrame对象的getViewerPose()方法来获取XRViewerPose(本质上)表示观察者头部的位置。该对象的views属性是所有XRView对象的列表,这些对象表示可以用于构建场景以呈现给用户的视点。

可能有XRView对象表示重叠区域以及完全不同的区域;例如,在游戏中,您可能拥有可以呈现的视图,以使用安全摄像头或其他设备观察远程站点。换句话说,不要假设给定观察者恰好有两个视图;可能只有一个(例如,当在inline模式下渲染场景时),也可能有很多(尤其是在视野非常大的情况下)。还可能存在表示观察者观看动作或与玩家眼睛没有直接关联的其他视点的视图。

此外,视图的数量可以随时更改,具体取决于当时的需要。因此,您应该每次都处理视图列表,而不要根据之前的帧进行假设。

给定XRViewerPose的视图内的所有位置和方向都指定在传递给XRFrame.getViewerPose()的参考空间中;这称为**查看器参考空间**。transform属性描述了由XRView表示的眼睛或摄像机的位置和方向,该位置和方向在该参考空间中给出。

目标渲染层

要渲染帧,您需要遍历XRViewerPose的视图,并将每个视图渲染到帧的XRWebGLLayer内的相应视口中。目前,规范(以及所有当前的WebXR实现)都是围绕将每个XRView渲染到单个XRWebGLLayer中设计的,然后在XR设备上呈现,其中一半用于左眼,一半用于右眼。XRViewport用于每个视图,用于将渲染定位到图层的正确一半。

如果将来每个视图都能够渲染到不同的图层中,则API将需要进行更改,因此现在可以安全地假设所有视图都将渲染到同一图层中。

示例

准备渲染姿势的每个视图

要绘制用户看到的所有内容,每个帧都需要遍历XRViewerPose对象的views列表返回的视图列表

js
for (const view of pose.views) {
  const viewport = glLayer.getViewport(view);

  gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

  // Draw the scene; the eye being drawn is identified
  // by view.eye.
}

特殊视图变换

在渲染和照明场景时,视图上会使用一些特殊的变换。

模型视图矩阵

**模型视图矩阵**是一个矩阵,它定义了对象相对于其所在空间的位置:如果objectMatrix是应用于对象以提供其基本位置和旋转的变换,则可以通过将对象的矩阵乘以视图变换矩阵的逆矩阵来计算模型视图矩阵,如下所示

js
mat4.multiply(modelViewMatrix, view.transform.inverse.matrix, objectMatrix);

法线矩阵

模型视图的**法线矩阵**用于照明场景,以便变换每个表面的法线向量,以确保光线以正确的方向反射,这取决于表面相对于光源或光源的方向和位置。它是通过反转然后转置模型视图矩阵来计算的

js
mat4.invert(normalMatrix, modelViewMatrix);
mat4.transpose(normalMatrix, normalMatrix);

传送对象

要以编程方式移动和/或旋转(通常称为**传送**)对象,您需要为该对象创建一个新的参考空间,该空间应用一个封装所需更改的变换。createTeleportTransform()函数返回将对象(其当前情况由参考空间refSpace描述)移动和旋转到新位置和方向所需的变换,该位置和方向是使用先前记录的鼠标和键盘输入数据计算得出的,这些数据已生成偏航、俯仰和沿所有三个轴的位置偏移。

js
function applyMouseMovement(refSpace) {
  if (
    !mouseYaw &&
    !mousePitch &&
    !axialDistance &&
    !transverseDistance &&
    !verticalDistance
  ) {
    return refSpace;
  }

  // Compute the quaternion used to rotate the image based
  // on the pitch and yaw.

  quat.identity(inverseOrientation);
  quat.rotateX(inverseOrientation, inverseOrientation, -mousePitch);
  quat.rotateY(inverseOrientation, inverseOrientation, -mouseYaw);

  // Compute the true "up" vector for our object.

  vec3.cross(vecX, vecY, cubeOrientation);
  vec3.cross(vecY, cubeOrientation, vecX);

  // Now compute the transform that teleports the object to the
  // specified point and save a copy of it to display to the user
  // later; otherwise we probably wouldn't need to save mouseMatrix
  // at all.

  let newTransform = new XRRigidTransform(
    { x: transverseDistance, y: verticalDistance, z: axialDistance },
    {
      x: inverseOrientation[0],
      y: inverseOrientation[1],
      z: inverseOrientation[2],
      w: inverseOrientation[3],
    },
  );
  mat4.copy(mouseMatrix, newTransform.matrix);

  // Create a new reference space that transforms the object to the new
  // position and orientation, returning the new reference space.

  return refSpace.getOffsetReferenceSpace(newTransform);
}

此代码分为四个部分。在第一个部分中,计算四元数inverseOrientation。这表示给定mousePitch(围绕对象参考空间的X轴旋转)和mouseYaw(围绕对象的Y轴旋转)的值时对象的旋转。

第二部分计算对象的“向上”向量。此向量指示场景中整体的“向上”方向,但在对象的参考空间中。

第三部分创建新的XRRigidTransform,将沿三个轴提供偏移量的点作为第一个参数,将方向四元数作为第二个参数。返回的对象的matrix属性是将点从场景的参考空间变换到对象的新位置的实际矩阵。

最后,创建一个新的参考空间来完整地描述这两个参考空间之间的关系。该参考空间将返回给调用方。

要使用此函数,我们将返回的参考空间传递给XRFrame.getPose()getViewerPose(),具体取决于您的需要。然后,将使用返回的XRPose渲染当前帧的场景。

您可以在我们的文章移动、方向和运动中找到更广泛和完整的示例。

规范

规范
WebXR设备API
# xrview-interface

浏览器兼容性

BCD表格仅在浏览器中加载