1. 简介
现在,支持虚拟现实(VR)和增强现实(AR)应用的硬件已广泛面向消费者,为用户带来沉浸式计算平台,既有新的机遇也伴随新的挑战。直接与沉浸式硬件交互的能力对于确保 Web 能够成为该环境中的一等公民至关重要。WebXR 游戏手柄模块为 WebXR Device API 及 Gamepads API 增加了接口与行为,以便查询许多兼容 WebXR 设备上可用的按钮、扳机、拇指杆和触控板的状态。
该模块是对 WebXR 设备 API 的补充。
1.1. 术语
本文档全篇采用缩写 XR 指代用于虚拟现实、增强现实及相关技术的硬件、应用和技术方案。例如,包括但不限于:
-
头戴式显示器,无论是黑暗型、透明型,还是利用视频透视的形式
-
具备位置追踪功能的移动设备
-
具备头部追踪功能的固定显示器
它们的重要共性在于都能实现一定程度的空间追踪,用于模拟虚拟内容的视图。
像“XR 设备”,“XR 应用”等术语一般适用于上述任何一种设备。仅适用于部分设备的内容将在文档中做出说明。
XR 设备通常会配备额外的控制器硬件,允许用户通过按钮、扳机、拇指杆或触控板输入与沉浸式体验交互。这些设备通常也会被空间追踪,被称为“运动控制器”、“手持控制器”或“追踪控制器”。
2. WebXR 设备 API 集成
如 WebXR 设备 API 中所定义,XRInputSource
表示一个 XR 输入源,也就是允许用户在与 viewer
相同虚拟空间中执行定向操作的任何输入机制。XR 输入源
的示例包括(但不限于)手持控制器、光学追踪手势输入,以及基于视线的输入方式等。
本文档概述了 XRInputSource
在可报告按钮、扳机、拇指杆或触控板数据时的行为。这通常是运动控制器,也可以是带有按钮、扳机、拇指杆或触控板的头显 XR
设备。如 WebXR 设备 API 所述,与 XR
设备 并无明确关联的输入机制(如传统手柄)不得视为 XR 输入源。
2.1. XRInputSource
按钮、扳机、拇指杆和触控板数据通过关联于 XRInputSource
的 Gamepad
对象进行报告。
partial interface XRInputSource { [SameObject ]readonly attribute Gamepad ?gamepad ; };
gamepad 属性是一个 Gamepad
,用于描述 XR 输入源 上所有按钮和轴的状态。如果
XR 输入源 不具备下列至少一项,则 gamepad 属性必须为 null:
-
一个按钮和 gripSpace
-
多于一个按钮
-
一个或多个轴
2.2. XRSession
XRInputSource
会在 inputSources
数组中作为设备连接或断开时汇报。当 gamepad
的存在性在 inputSources
数组的任何条目上发生变化时,User Agent 必须调用 WebXR Device API 的“响应输入源属性变化”算法。
为 XRFrame
frame 应用游戏手柄帧更新 时,User Agent 必须运行以下步骤:
-
对
XRInputSource拥有与 frame 的session关联的gamepadgamepad ,执行以下步骤:-
将 gamepad 更新为反映 frame 在 time 时刻的游戏手柄数据。
-
注意: 即 gamepad
对象是“活”的,所有内部状态应当在每一帧中就地更新。因此,将某帧的 XRInputSource
的
gamepad 引用后,与后续帧中的同一 XRInputSource
的
gamepad
直接作对象比较以判断状态变化会失败,因为它们总是同一个对象。想要实现帧到帧的输入状态比对,开发者应缓存相关状态值。
3. Gamepad API 集成
Gamepad
实例由 XRInputSource
的
gamepad
属性返回,其行为遵循 Gamepad API,并有额外的行为限制说明。
由 XRInputSource
关联的 Gamepad
可由 User Agent 选择暴露于 navigator.getGamepads()
,即使没有活跃的 XR 会话。这使得 XR 设备可以按常规手柄方式供使用,只要 User Agent 允许。
注意:如 [WEBXR-HAND-INPUT-1]
所述的手势追踪 XRInputSource
若 User Agent 允许,可带有 Gamepad
以支持基于手势的内容与基于手柄的内容兼容。
3.1. Navigator
Gamepad API 说明可以通过调用 navigator.getGamepads()
获取 Gamepad
数据快照。但 XRInputSource
的
gamepad
属性返回的
Gamepad
实例不得包含在 navigator.getGamepads()
返回的数组中。
3.2. Gamepad
下列 Gamepad
属性当 Gamepad
由 XRInputSource
的
gamepad
返回时,必须满足如下行为约束:
-
gamepad的index属性若未通过navigator.getGamepads()暴露,必须为-1,否则按照 选择未使用手柄索引 的规范分配。 -
gamepad的connected属性在XRInputSource被移除出 活跃 XR 输入源列表 或XRSession结束前必须为true。 -
如果
gamepad的axes数组中某个轴表示触控板,则当关联GamepadButton的touched为false时,该轴值必须为0。
3.3. "xr-standard" 手柄映射
"xr-standard"
映射定义于 Gamepad API,专供本规范使用。该映射表明 gamepad
的按钮和轴布局与下列表格尽可能一致。
欲上报 mapping
为 "xr-standard"
,设备必须上报 targetRayMode
为 "tracked-pointer"
,且 gripSpace
非 null。设备必须至少有一个独立于触控板或拇指杆的 主扳机。主扳机必须触发该输入源的主操作。设备可选带有 主握持按钮,如有,此按钮必须触发该输入源的主握持操作。若设备不符合 "xr-standard"
映射要求,则可上报 gamepad
,其 mapping
为空字符串("")。仅允许 Gamepad
实例上报 "xr-standard"
映射,且该实例必须由 XRInputSource
上报。
| 按钮 | xr-standard 映射
| 必选 |
|---|---|---|
| buttons[0] | 主扳机 | 是 |
| buttons[1] | 主握持按钮 | 否 |
| buttons[2] | 主触控板 | 否 |
| buttons[3] | 主拇指杆 | 否 |
| 轴 | xr-standard 映射
| 必选 |
|---|---|---|
| axes[0] | 主触控板 X | 否 |
| axes[1] | 主触控板 Y | 否 |
| axes[2] | 主拇指杆 X | 否 |
| axes[3] | 主拇指杆 Y | 否 |
缺失上述表格中任一可选输入的设备,必须保留其在 buttons
或 axes
数组中的位置,依次上报 占位按钮 或 占位轴。占位按钮
必须上报 0 为 value,
false 为 pressed,
false 为 touched。占位轴
必须上报 0。占位按钮 及 占位轴 若为最后元素,或后续均为占位,则应省略。
允许在这些保留索引之后暴露更多按钮或轴,且应按重要性降序排列。相关轴(如拇指杆的两个轴)必须成组,并按 X、Y(Z)顺序表示。
3.4. UA/平台保留按钮
User Agent 应尽可能保留至少一个物理按钮,用于执行不可伪造的 可信 UI 操作。例如,User Agent 可指定许多控制器上都有的“菜单”或“应用”按钮为退出沉浸模式的专用键。此外,许多 XR 平台还会为平台专属操作(如返回主页)保留一个按钮。
由 UA 或平台保留的按钮不得暴露于 Gamepad。
User Agent 还应协调 XR 平台应保留哪些按钮。推荐在 WebXR Input
Profiles Registry 协调按钮的保留情况。
3.5. 示例映射
"xr-standard"
映射暴露的方式。图片仅作参考,不代表任何实际设备。4. 安全与隐私
WebXR 设备 API 提供了强大的新功能,同时也带来了多种独特的隐私、安全与舒适性风险,User Agent 必须采取措施加以防范。详见 WebXR 设备 API。本模块在此基础上补充说明,但不改变 WebXR 的基本安全与隐私原则。
4.1. 指纹识别
由于 API 描述用户可用的硬件及其能力,因此不可避免地增加了指纹识别面。虽然无法彻底避免,User Agent 仍应采取措施降低风险。就如 WebXR 设备 API 所定义,XRInputSource
仅在建立 XRSession
后才会汇报,从而能在暴露 敏感信息
时采取额外保护措施。此外,本模块要求 XRInputSource
的 gamepad.id
不得返回字符串标识符。
变更
源自 2019年10月10日首次公开工作草案 的变更
-
明确 Gamepad API 集成交由 User Agent 决定(GitHub #49)
-
补充规定保留按钮不得暴露于接口(GitHub #48)
-
放宽 gamepad.index 的定义限制(GitHub #46,GitHub #47)
-
定义主扳机及相关按钮(GitHub #24)
-
澄清手柄状态时的更新行为(GitHub #22)
5. 致谢
以下人员为 WebXR 设备 API 规范设计做出过贡献:
特别感谢 Vladimir Vukicevic (Unity),助力本项目的启动!