XRView
WebXR Device API 的 XRView
接口描述了特定帧的 XR 场景的单个视图,提供了视点的方向和位置信息。你可以将其理解为描述一只眼睛或一个摄像机如何观察世界的描述。一个 3D 帧会包含两个视图,分别对应于两只眼睛,它们之间有适当的距离,以近似观察者眼睛之间的距离。这样,当这两个视图分别投射到对应的眼睛时,就可以模拟出 3D 世界。
实例属性
eye
只读 实验性-
此
XRView
所代表的视角是两只眼睛中的哪一只(left
)或(right
)。此值用于确保任何预先渲染的、用于呈现给特定眼睛的内容都能被正确分发或定位。当XRView
呈现单视图数据时(例如 2D 图像、文本的全屏视图,或不需要以 3D 形式显示的近距离视图),该值也可以是none
。 isFirstPersonObserver
只读 实验性-
返回一个布尔值,指示
XRView
是否为第一人称观察者视图。 projectionMatrix
只读 实验性-
投影矩阵,用于根据
eye
指示的视角正确地转换场景。应直接使用此矩阵,以避免可能导致用户严重不适的演示失真。 recommendedViewportScale
只读 实验性-
如果你希望用户代理(user agent)设置此视口的推荐视口比例,你可以使用 `requestViewportScale()`;否则返回
null
。 transform
只读 实验性-
一个
XRRigidTransform
对象,描述了当前视点相对于在渲染的XRFrame
上调用getViewerPose()
时指定的XRReferenceSpace
的位置和方向。
实例方法
requestViewportScale()
只读 实验性-
请求用户代理将此视口的请求视口比例设置为请求的值。
用法说明
每帧的 XRView 位置和数量
在渲染场景时,用于渲染当前帧观察者场景的视图集合是通过调用 XRFrame
对象的 getViewerPose()
方法来获取的,该方法返回表示(本质上)观察者头部位置的 XRViewerPose
。该对象的 views
属性是一个 XRView
对象列表,代表可以用来构建场景并呈现给用户的视点。
XRView
对象可能代表重叠区域,也可能代表完全不同的区域;例如,在游戏中,你可能会有可以呈现出来以观察远程站点(通过安全摄像头或其他设备)的视图。换句话说,不要假设一个给定的观察者只有两个视图;可能只有一种(例如,在 inline
模式下渲染场景时),也可能有很多(尤其是在视场非常大的情况下)。也可能存在代表观察正在发生事件的观察者,或其他不直接与玩家眼睛相关的视点。
此外,视图的数量可以随时更改,具体取决于当时的需要。因此,你应该每次都处理视图列表,而不应基于之前帧做出假设。
给定 XRViewerPose
的所有视图中的所有位置和方向,都是在传递给 XRFrame.getViewerPose()
的参考空间中指定的;这被称为观察者参考空间。 transform
属性描述了由 XRView
表示的眼睛或摄像机在该参考空间中的位置和方向。
目标渲染层
要渲染一帧,你需要遍历 XRViewerPose
的视图,并将每个视图渲染到该帧 XRWebGLLayer
中的相应视口。目前,规范(因此所有当前的 WebXR 实现)都是围绕将每个 XRView
渲染到单个 XRWebGLLayer
来设计的,然后该层会呈现到 XR 设备上,其中一半用于左眼,一半用于右眼。每个视图的 XRViewport
用于将渲染定位到图层的正确一半。
如果将来每个视图都可以渲染到不同的图层,那么 API 将需要进行修改,因此目前可以安全地假设所有视图都将渲染到同一个图层。
示例
准备渲染姿势的每个视图
要绘制用户看到的所有内容,每一帧都需要遍历 XRViewerPose
对象 views
列表返回的视图列表。
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
是应用于对象的变换,用于提供其基本位置和旋转,那么模型视图矩阵可以通过将对象的矩阵乘以视图变换矩阵的逆来计算,如下所示:
mat4.multiply(modelViewMatrix, view.transform.inverse.matrix, objectMatrix);
法线矩阵
模型视图的法线矩阵用于在光照场景时,通过变换每个表面的法向量,以确保光线能够朝着正确的方向反射,这取决于表面相对于光源的方向和位置。它是通过反转然后转置模型视图矩阵来计算的。
mat4.invert(normalMatrix, modelViewMatrix);
mat4.transpose(normalMatrix, normalMatrix);
传送对象
要以编程方式移动和/或旋转(通常称为传送)一个对象,你需要为该对象创建一个新的参考空间,该空间应用一个封装了所需更改的变换。 `createTeleportTransform()` 函数返回了将对象从当前情况(由参考空间 `refSpace` 描述)移动和旋转到新位置和方向所需的变换。这个新位置和方向是通过先前记录的鼠标和键盘输入数据计算得出的,这些数据生成了偏航(yaw)、俯仰(pitch)以及沿三个轴的位置偏移。
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 Device API # xrview-interface |
浏览器兼容性
加载中…