WebXR 层 API 第 1 级

W3C 工作草案,

关于此文档的更多详细信息
此版本:
https://www.w3.org/TR/2026/WD-webxrlayers-1-20260811/
最新发布版本:
https://www.w3.org/TR/webxrlayers-1/
编辑草案:
https://immersive-web.github.io/layers/
先前版本:
历史:
https://www.w3.org/standards/history/webxrlayers-1/
反馈:
GitHub
规范内嵌议题
编辑:
(Meta)
参与:
提交议题 (开放议题)
邮件列表归档
W3C 的 #immersive-web IRC

摘要

本规范描述了对 WebXR 会话中使用的各种层类型的支持。

本文档状态

本节描述的是本文档在发布时的状态。当前 W3C 出版物列表以及本 技术报告的最新修订版,可在 W3C 标准和草案索引中找到。

沉浸式 Web 工作组维护着一份 该组尚未处理的所有错误 报告列表。此草案突出了部分待处理议题,这些议题 仍需在工作组中讨论。对于这些议题的结果,包括其是否有效, 尚未作出决定。 强烈鼓励为未解决议题提交带有拟议规范文本的拉取请求。

本文档由沉浸式 Web 工作组作为工作草案发布,并使用 推荐标准 轨道。本文档预期成为 W3C 推荐标准。

作为工作草案发布并不意味着获得 W3C 及其成员的认可。本文档是草案文档,可能 随时被其他文档更新、替换或废弃。除作为进行中的工作外,不应引用本文档。

本文档由一个依据 W3C 专利政策运作的组制作。 W3C 维护着一份与该组交付物相关的任何 专利 披露的公开列表;该页面还包括 披露专利的说明。实际知晓某项专利,且该个人 认为该专利包含 必要 权利要求的个人,必须根据 W3C 专利政策第 6 节披露该信息。

本文档受 2025 年 8 月 18 日 W3C 流程文档约束。

1. 简介

本规范为 WebXR 规范添加对 `composition` 层的支持。层的优点如下:

1.1. 术语

1.2. 应用流程

如果作者想使用 GL 层,则必须执行以下步骤:

  1. 对于除 XRProjectionLayer 之外的任何层类型,通过 requiredFeatures 或 optionalFeatures 在 requestSession() 中请求支持。

  2. 创建一个 XRWebGLBinding 或 XRMediaBinding。

  3. 使用这些对象创建层。

  4. 将层添加到 XRRenderStateInit 并调用 updateRenderState()。

  5. 在用于 webgl 层的 requestAnimationFrame() 期间,绘制每个 WebGL 层的内容。

2. 初始化

如果应用想在会话期间创建 XRProjectionLayer 类型之外的层, 则必须使用适当的特性 描述符来请求该会话。本模块引入字符串 "layers", 作为 WebXR Layers 特性的新的有效特性描述符。

XRProjectionLayer 类型的层必须始终受支持,无论是否请求了该特性 描述符。

以下代码将 layers 作为可选特性请求。
navigator.xr.requestSession('immersive-vr', {
    optionalFeatures: ['layers']
  }

层仅支持用于以 "immersive-vr" 或 "immersive-ar" 的 XRSessionMode 创建的 XRSession。 "inline" 会话不得支持层。

"layers" 特性 描述符有一个特性要求:当存在活动的沉浸式会话时,不能启用它。

注: 这意味着,使用 "layers" 执行 request(permissionDesc) API 不会 为当前活动会话启用层支持。

3. 层类型

3.1. 单目和立体层

立体层必须为每个视图提供一个 XRSubImage 以供渲染。

单目层必须提供一个单独的 XRSubImage, 该图像会显示给每个视图。

XR Compositor 必须确保层以正确的立体方式呈现给观察者。

3.2. XRLayerLayout

XRLayerLayout 枚举定义层的布局。
enum XRLayerLayout {
  "default",
  "mono",
  "stereo",
  "stereo-left-right",
  "stereo-top-bottom"
};

注: 如果使用 "default" 或 "stereo" XRLayerLayout 创建 XRCompositionLayer, 强烈建议 使用 "texture-array" 纹理类型来分配它。

注: "stereo-left-right" 和 "stereo-top-bottom" 布局旨在最大限度减少已经是立体的内容(例如立体视频或图像)的绘制 调用。不需要此类资源类型的体验 应使用 "default" 或 "stereo" 布局。

3.3. XRLayerQuality

XRLayerQuality 枚举定义层的显示质量。
enum XRLayerQuality {
  "default",
  "text-optimized",
  "graphics-optimized"
};

注: text-optimized 和 graphics-optimized 标志可能会导致 XR Compositor 进行额外处理,这可能会影响性能。

3.4. XRCompositionLayer

XRCompositionLayer 定义一组在某些层类型之间共享的公共属性和行为。
[Exposed=Window] interface XRCompositionLayer : XRLayer {
  readonly attribute XRLayerLayout layout;

  attribute boolean blendTextureSourceAlpha;
  attribute boolean forceMonoPresentation;
  attribute float opacity;
  readonly attribute unsigned long mipLevels;
  attribute XRLayerQuality quality;

  readonly attribute boolean needsRedraw;

  undefined destroy();
};

layout 属性返回层的布局。

blendTextureSourceAlpha 属性 启用层的纹理 alpha 通道。

forceMonoPresentation 属性 强制右眼使用与左眼相同的层配置。这必须向 XR Compositor 发送信号,以 移除此 XRCompositionLayer 的 stereo 效果。 在 mono 层上将其设置为 true 没有任何效果。

注: 此属性对 XRSession 返回的其他信息没有其他副作用。 只有 XR Compositor 的操作会受到此设置影响,体验应该 继续绘制到双眼。

opacity 属性设置应用于 层像素的不透明度。XR Compositor 必须 将每个像素(在预乘空间中)乘以此值。 opacity 默认为 1.0。将 opacity 设置为小于 0 的值会将其设置为 0,设置为大于 1.0 的值会将其设置为 1.0。

needsRedraw 属性发出信号,表示 XRCompositionLayer 应该在下一个 XR 动画帧中 重新渲染。当层的底层资源 丢失,或当 XR Compositor 无法再重投影该层时,可以设置它。未能在下一个 XR 动画帧 中重绘内容可能会导致闪烁或其他副作用。

mipLevels 属性返回 mip 链的深度。这必须等于 或小于 mipLevels 中请求的值。

注: 某些平台不支持 mip 级别。作者 应查询 mipLevels 以确定是否可以 目标到某个 mip 级别,而不应依赖其传入 mipLevels 的值。

quality 属性设置并返回 XRCompositionLayer 的质量。 default 是初始值。

当 XRCompositionLayer layer 的 层的底层资源丢失时, 用户代理必须运行以下步骤:
  1. 将 layer 的 needsRedraw 设置为 true。

  2. 如果 layer 不是 XRProjectionLayer, 则排入一个任务,以在 layer 上使用 XRLayerEvent 触发 一个事件,其名称为 redraw。

每个 XRCompositionLayer 都有一个关联的 destroyed 布尔值,初始值为 false。

destroy() 会立即将该层标记为已销毁,并使其图形资源无法用于 未来的渲染。 对一个已经销毁的层调用 destroy() 不会执行任何操作。 即使在应用待处理的渲染状态更新时,该层仍存在于 layers 数组中,已销毁的层也不得由 XR 合成器呈现。

如果调用某个方法来获取已销毁层的 XRSubImage, 则该方法必须抛出 InvalidStateError。

当其层被销毁时,先前返回的 XRSubImage 对象本身不会被销毁。它们的属性会继续返回相同的 对象和值,但这些对象公开的任何图形资源都必须失效,不能用于未来的 渲染操作。在资源失效之前排队的 GPU 工作可以完成。

要使用一个 XRCompositionLayer layer 销毁层的资源,用户代理必须运行以下步骤:

  1. 对于 layer 的 colorTextures、depthStencilTextures 或 motionVectorTextures 数组中存在的每个不透明 纹理,将该纹理标记为待删除,就像已经在 layer 的上下文上以该纹理为参数调用了 deleteTexture 一样。这是用户代理的内部操作,不得生成 INVALID_OPERATION 错误。

  2. 如果 layer 是 XRProjectionLayer:

    1. 如果 layer 的辅助视图的 colorTextures 不是 null,则对于该 数组中的每个不透明纹理,以相同方式将该纹理标记为待删除。

    2. 如果 layer 的辅助视图的 depthStencilTextures 不是 null,则对于该 数组中的每个不透明纹理,以相同方式将该纹理标记为待删除。

  3. 如果 layer 有一个 colorTextures 数组,则将其设置为空数组。

  4. 如果 layer 有一个 depthStencilTextures 数组,则将其设置为空数组。

  5. 如果 layer 有一个 motionVectorTextures 数组,则将其设置为空数组。

  6. 如果 layer 是 XRProjectionLayer, 则将其辅助视图的 colorTextures 和辅助视图的 depthStencilTextures 设置为空数组。

  7. 对于 layer 的每个底层资源,一旦在资源失效之前排队的所有 GPU 工作 均已完成,并且 XR 合成器不再访问该资源,用户代理就可以实际释放该资源。

要使用一个 XRSession session 和一个可选的 WebGLRenderingContext 或 WebGL2RenderingContext 实例 context 初始化合成层,用户代理必须运行以下步骤:

  1. 将此对象的会话设置为 session。

  2. 如果定义了 context,则将此对象的上下文设置为 context。

  3. 将此对象的destroyed 设置为 false。

  4. 将此对象的 blendTextureSourceAlpha 设置为 true。

  5. 将此对象的 opacity 设置为 1.0。

当在一个 XRCompositionLayer layer 上调用 destroy() 时,用户代理必须运行以下步骤:

  1. 如果 layer 的destroyed 为 true,则返回。

  2. 将 layer 的destroyed 设置为 true。

  3. 使用 layer 运行销毁层的资源。

  4. 令 session 为 layer 的会话。

  5. 如果 session 的待处理渲染状态为 null:

    1. 如果 session 的活动渲染状态的 layers 不包含 layer,则返回。

    2. 将 session 的待处理渲染状态设置为 session 的活动渲染状态的副本。

  6. 令 state 为 session 的待处理渲染状态。

  7. 如果 state 的 layers 为 null 或不包含 layer,则返回。

  8. 将 state 的 layers 设置为一个新的冻结数组,其中按顺序包含 state 的 layers 中除 layer 之外的每个条目。

每个 XRCompositionLayer 都有一个 context 对象,它是 null 或 WebGLRenderingContext 或 WebGL2RenderingContext 的实例,并且还有一个 media 对象,它是 null 或 HTMLVideoElement 的实例。

每个 XRCompositionLayer 都有一个关联的 session,即创建它时使用的 XRSession。

当使用 XRSpace space 和 XRCompositionLayer layer 设置 层上的空间时,用户代理必须运行以下步骤,以验证 space 是否 有效:

  1. 如果 space 为 null,则抛出 TypeError 并中止这些步骤。

  2. 如果 space 的会话不等于 layer 的会话,则抛出 TypeError 并中止这些步骤。

XRCompositionLayer 有一个内部布尔值 isStatic,它表示作者只能在 needsRedraw 为 true 时向 此层绘制内容。

注:如果 isStatic 为 true,作者只能在创建后向该层绘制一次,或者在 redraw 事件后绘制一次。这使用户代理只需分配一个 GPU 缓冲区。

当在 XRCompositionLayer 或其任何派生类上设置一个可写属性时, 读取该属性必须返回该值。 在 requestAnimationFrame() 回调结束时,该值必须发送给 底层的 XR 合成器。XR 合成器必须 在下一次呈现传递给 requestAnimationFrame() 回调的 XRFrame 时应用该值。

注:这意味着,当 XR 合成器使用新的 XRFrame 重绘场景时,即使与 XRCompositionLayer 关联的 colorTexture 或与媒体层关联的视频帧没有发生变化,也必须应用这些值。如果 XR 合成器使用前一个 XRFrame 的 状态重绘场景,则不得使用这些新 值。

3.5. XRProjectionLayer

An XRProjectionLayer 是一个填充观察者整个视图的层。 投影层应以接近设备原生帧率的频率刷新。

投影层的表示

[Exposed=Window] interface XRProjectionLayer : XRCompositionLayer {
  readonly attribute unsigned long textureWidth;
  readonly attribute unsigned long textureHeight;
  readonly attribute unsigned long textureArrayLength;

  readonly attribute boolean ignoreDepthValues;
  attribute float? fixedFoveation;
  attribute XRRigidTransform? deltaPose;
};

textureWidth 属性返回 此层的 colorTextures 纹理的 像素宽度。

textureHeight 属性返回 此层的 colorTextures 纹理的 像素高度。

textureArrayLength 属性返回 此层的 colorTextures 纹理的 层数,前提是 XRProjectionLayer 使用 textureType 为 "texture-array" 进行初始化。 否则它将返回 1。

fixedFoveation 属性控制 XR 合成器使用的注视点渲染程度。如果用户代理或设备不支持此属性,则 获取时应返回 null,设置时应为 no-op。 将 fixedFoveation 设置为小于 0 的值会将其设置为 0,而设置为 大于 1 的值会将其设置为 1。0 设置最小的 注视点渲染程度,而 1 设置最大的程度。由用户代理决定 XR 合成器 如何解释这些值。 如果 fixedFoveation 级别发生更改,它将在下一个 XRFrame 生效。

ignoreDepthValues 属性如果为 true,则表示 XR 合成器在渲染时不得使用深度缓冲区附件中的值。当该 属性 为 false 时,表示深度缓冲区附件的内容将由 XR 合成器使用,并且预期它能够代表渲染到该层中的场景。

deltaPose 属性描述自上一帧以来影响视图的、 由应用程序应用的增量变换(如果有)。 如果用户代理或设备不支持此属性,或者未请求“space-warp”特性描述符,则用户代理在获取时应返回 null,设置时应为 no-op。 null 值表示未提供由应用程序应用的变换。 deltaPose 的值会一直保持,直到作者更改它;用户代理不会在 requestAnimationFrame() 回调结束时将其重置。 当人工移动在帧之间将世界从一个应用程序姿态变换为另一个应用程序姿态时,将 deltaPose 设置为这些姿态之间的差值,有助于 XR 合成器 合成缺失的帧。 当该变换发生变化时,作者应更新 deltaPose, 并且对于未发生由应用程序应用的变换的帧,将其设置为 null 或恒等变换。

3.6. XRQuadLayer

An XRQuadLayer 渲染一个在虚拟环境中占据平坦矩形空间的层。 只有该层的正面必须可见;背面不得由 XR 合成器绘制。

XRQuadLayer 没有厚度。它是一个在 3D 空间中定位和定向的二维对象。四边形的 位置 是指四边形的中心。

四边形层的表示

[Exposed=Window] interface XRQuadLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute XRRigidTransform transform;

  attribute float width;
  attribute float height;

  // 事件
  attribute EventHandler onredraw;
};

transform 属性设置并返回相对于 space 属性的偏移和 方向。transform 和 space 属性 建立层在用户物理环境中的空间关系。 设置 space 时,首先运行设置层上的空间的步骤。

width 和 height 属性 设置并返回层的宽度和高度,单位为米。

当使用 XRQuadLayerInit init初始化 XRQuadLayer layer 时,用户代理必须运行以下步骤:
  1. 将 layer 的 width 初始化为 init 的 width。

  2. 将 layer 的 height 初始化为 init 的 height。

  3. 令 layer 的 space 为 init 的 space。

  4. 按如下方式初始化 layer 的 transform:

    如果设置了 init 的 transform
    令 layer 的 transform 为在 layer 的相关 Realm 中新建的 XRRigidTransform, 并使用 init 的 transform 的 position 和 orientation 初始化。
    否则
    令 layer 的 transform 为在 layer 的相关 Realm 中新建的 XRRigidTransform, 并使用 DOMPointInit position { x: 0.0, y: 0.0, z: 0.0, w: 1.0 } 初始化。
  5. 将 layer 的 isStatic 初始化为 init 的 isStatic

onredraw 属性是 redraw 事件类型的事件处理器 IDL 属性。

3.7. XRCylinderLayer

An XRCylinderLayer 渲染一个在虚拟环境中占据弯曲矩形空间的层。 只有该层的正面必须可见;背面不得由 XR 合成器绘制。

圆柱层的表示

XRCylinderLayer 没有厚度。它是一个在 3D 空间中定位和定向的二维对象。圆柱的 位置 是指四边形的中心。

[Exposed=Window] interface XRCylinderLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute XRRigidTransform transform;

  attribute float radius;
  attribute float centralAngle;
  attribute float aspectRatio;

  // 事件
  attribute EventHandler onredraw;
};

transform 属性设置并返回相对于 space 属性的偏移 和方向。transform 和 space 属性 建立层在用户物理环境中的空间关系。 设置 space 时,首先运行设置层上的空间的步骤。

radius 属性控制圆柱的 半径,单位为米。

centralAngle 属性控制圆柱可见部分的角度, 单位为弧度。 它围绕 0 角对称增长。

aspectRatio 属性控制 可见圆柱部分的比例。它是圆柱可见部分的宽度除以其 高度的比值。宽度通过将 radius 乘以 centralAngle 计算得出。

圆柱层参数的描述

当使用 XRCylinderLayerInit init初始化 XRCylinderLayer layer 时,用户代理必须运行以下步骤:
  1. 将 layer 的 radius 初始化为 init 的 radius。

  2. 将 layer 的 centralAngle 初始化为 init 的 centralAngle。

  3. 将 layer 的 aspectRatio 初始化为 init 的 aspectRatio。

  4. 令 layer 的 space 为 init 的 space。

  5. 按如下方式初始化 layer 的 transform:

    如果设置了 init 的 transform
    令 layer 的 transform 为在 layer 的相关 Realm 中新建的 XRRigidTransform, 并使用 init 的 transform 的 position 和 orientation 初始化。
    否则
    令 layer 的 transform 为在 layer 的相关 Realm 中新建的 XRRigidTransform, 并使用 DOMPointInit position { x: 0.0, y: 0.0, z: 0.0, w: 1.0 } 初始化。
  6. 将 layer 的 isStatic 初始化为 init 的 isStatic

onredraw 属性是 redraw 事件类型的事件处理器 IDL 属性。

3.8. XREquirectLayer

一个 XREquirectLayer 渲染一个层,其中 XR 合成器必须将等距柱状投影编码的数据映射到 球体的内表面。

等距柱状投影层的表示

本节需要 澄清

[Exposed=Window] interface XREquirectLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute XRRigidTransform transform;

  attribute float radius;
  attribute float centralHorizontalAngle;
  attribute float upperVerticalAngle;
  attribute float lowerVerticalAngle;

  // 事件
  attribute EventHandler onredraw;
};

transform 属性设置并返回相对于 space 的偏移和方向。 transform 属性和 space 建立层在用户物理环境中的空间关系。

radius 属性是球体的非负半径,单位为米。 zero 或 infinity 值被视为无限球体。

将 radius 设置为小于 0 的值会将其设置为 0。

centralHorizontalAngle、upperVerticalAngle 和 lowerVerticalAngle 属性设置并 返回纹理如何映射到球体。

将 centralHorizontalAngle 设置为小于 0 的值会将其设置为 0,而设置为 大于 2π 的值会将其设置为 2π。

将 upperVerticalAngle 或 lowerVerticalAngle 设置为小于 -π/2 的值会将其 设置为 -π/2,而设置为大于 π/2 的值会将其设置为 π/2。

等矩形层参数的描述

将 XRSpace 分配给 space 属性时,首先运行以下步骤。

当使用 XRSpace space 和 XREquirectLayer layer 设置等矩形层上的空间时,用户代理必须运行以下步骤来验证 space 是否 有效:

  1. 如果 init 的 space 不是 XRReferenceSpace 类型的实例, 则抛出 TypeError 并中止这些步骤。

  2. 如果 init 的 space 具有 "viewer" 的type, 则抛出 TypeError 并中止这些步骤。

  3. 使用 space 和 layer 运行设置层上的空间。

当使用 XREquirectLayerInit init初始化 XREquirectLayer layer 时,用户代理必须运行以下步骤:
  1. 将 layer 的 radius 初始化为 init 的 radius。

  2. 将 layer 的 centralHorizontalAngle 初始化为 init 的 centralHorizontalAngle。

  3. 将 layer 的 upperVerticalAngle 初始化为 init 的 upperVerticalAngle。

  4. 将 layer 的 lowerVerticalAngle 初始化为 init 的 lowerVerticalAngle。

  5. 令 layer 的 space 为 init 的 space。

  6. 按如下方式初始化 layer 的 transform:

    如果设置了 init 的 transform
    令 layer 的 transform 为在 layer 的相关 Realm 中新建的 XRRigidTransform, 并使用 init 的 transform 的 position 和 orientation 初始化。
    否则
    令 layer 的 transform 为在 layer 的相关 Realm 中新建的 XRRigidTransform。
  7. 将 layer 的 isStatic 初始化为 init 的 isStatic

onredraw 属性是 redraw 事件类型的事件处理器 IDL 属性。

3.9. XRCubeLayer

一个 XRCubeLayer 渲染一个层,其中 XR 合成器直接从立方体贴图进行渲染。

立方体层的表示

本节需要 澄清

[Exposed=Window] interface XRCubeLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute DOMPointReadOnly orientation;

  // 事件
  attribute EventHandler onredraw;
};

orientation 属性设置并返回相对于 space 属性的方向。orientation 和 space 属性 建立层在用户物理环境中的空间关系。 放置 XRCubeLayer 时,仅考虑 space 的方向。立方体层将始终以 视点位于中心的方式渲染。

将 XRSpace 分配给 space 属性时,首先运行以下步骤。

当使用 XRSpace space 和 XRCubeLayer layer 设置立方体层上的空间时,用户代理必须运行以下步骤来验证 space 是否 有效:

  1. 如果 init 的 space 不是 XRReferenceSpace 类型的实例, 则抛出 TypeError 并中止这些步骤。

  2. 如果 init 的 space 具有 "viewer" 的type, 则抛出 TypeError 并中止这些步骤。

  3. 使用 space 和 layer 运行设置层上的空间。

onredraw 属性是 redraw 事件类型的事件处理器 IDL 属性。

4. 空间

XRProjectionLayer 和 XRWebGLLayer 没有关联的 XRSpace, 因为它们渲染到完整帧。

XRCubeLayer 和 XREquirectLayer 必须仅支持非 "viewer" 类型的 XRReferenceSpaces。

XRQuadLayer 和 XRCylinderLayer 必须支持所有 XRSpace 类型。

通常,开发者不应使用 "viewer" 空间来稳定层,因为这几乎总会破坏位置或 旋转重投影,并导致渲染内容相对于世界的稳定性下降。 例外是一些小型 UI 元素, 例如凝视光标或瞄准标线。

以下是与层类型一起使用的空间的一些最佳实践:

5. 渲染

5.1. XRSubImage

XRSubImage 对象表示要使用颜色 GPU 纹理的哪个视口。
[Exposed=Window] interface XRSubImage {
  [SameObject] readonly attribute XRViewport viewport;
};

注意: 此类旨在容纳未来的扩展

viewport 属性返回在渲染子图像的颜色附件时要使用的 XRViewport。

5.2. XRWebGLSubImage

XRWebGLSubImage 对象在层的渲染期间使用。
[Exposed=Window] interface XRWebGLSubImage : XRSubImage {
  [SameObject] readonly attribute WebGLTexture colorTexture;
  [SameObject] readonly attribute WebGLTexture? depthStencilTexture;
  [SameObject] readonly attribute WebGLTexture? motionVectorTexture;

  readonly attribute unsigned long? imageIndex;
  readonly attribute unsigned long colorTextureWidth;
  readonly attribute unsigned long colorTextureHeight;
  readonly attribute unsigned long? depthStencilTextureWidth;
  readonly attribute unsigned long? depthStencilTextureHeight;
};

The colorTexture 属性返回用于 XRCompositionLayer 的颜色不透明纹理。 viewport 描述 colorTexture 中与所请求视图对应的区域。它不描述 depthStencilTexture 或 motionVectorTexture 的区域。

depthStencilTexture 属性返回 XRCompositionLayer 的深度/模板不透明 纹理。 如果该层创建时没有深度/模板,则此属性返回 null。

motionVectorTexture 属性返回 XRProjectionLayer 的运动不透明纹理。 如果 XRSession 创建时没有 space-warp 特性 描述符,或者该层不是 XRProjectionLayer, 则此属性必须返回 null。

imageIndex 属性返回纹理 数组中的偏移量。仅对请求时使用 texture-array 的层有效。

colorTextureWidth 和 colorTextureHeight 属性 返回 GL 颜色附件的像素宽度和高度。

depthStencilTextureWidth 和 depthStencilTextureHeight 属性 返回 GL 深度/模板附件的像素宽度和高度。如果该层创建时没有 深度/模板,则这些属性返回 null。

5.3. XRTextureType

XRTextureType 枚举定义分配何种类型的纹理。
enum XRTextureType {
  "texture",
  "texture-array"
};

6. GPU 层和视图创建

6.1. 概述

创建层时,它由一个 GPU 资源作为后备,通常是纹理,由 Web 平台的某个图形 API 提供。为了 指定由哪个 API 提供该层的 GPU 资源,必须为相关 API 创建一个 XRWebGLBinding。 每个图形 API 可能都有独特的要求,在上下文可用于 创建层之前必须满足这些要求。例如, WebGLRenderingContext 在传递给 XRWebGLBinding 实例的构造函数之前,必须设置其 xrCompatible 标志。

XRSession 与图形 API 之间的任何交互,例如分配或取回纹理,都将通过这个 XRWebGLBinding 实例进行,并且该交互的确切机制 通常会是 API 特定的。这使 WebXR API 的其余部分能够与 图形 API 无关,并更容易适应未来渲染技术的发展。

一旦获得了 XRWebGLBinding 实例,它就可用于创建各种 XRCompositionLayer。 由该实例创建的任何层随后都能够 在每一帧查询关联的 GPU 资源,通常预期该资源是原生 API 的纹理 接口。

各种层类型是通过 XRWebGLBinding 实例上的 create____Layer 系列方法创建的。关于所需图形资源的信息, 例如是否分配深度缓冲区或 alpha 通道,会在创建层时传入, 并且在层的生命周期内保持不可变。 该方法将返回关联的 XRCompositionLayer 类型。

如果 XRSession 是使用 “layers” 特性 描述符创建的,则它必须支持所有层类型。 如果某个层类型不受支持,则其创建方法必须抛出异常。XRProjectionLayer 必须被所有 XRSession 支持, 无论它是否是使用 “layers” 特性 描述符创建的。

6.2. 不透明纹理

When using WebXR GPU layers, the XRWebGLBinding 对象将为颜色和深度/模板附件返回不透明纹理的实例。

不透明纹理的功能 与标准 WebGLTexture 完全相同,但有以下变化:

当 clearOnAccess 为 true 时,在每个 XR 动画帧中第一次调用 getViewSubImage() 或 getSubImage() 的处理期间,必须将附加到不透明纹理的缓冲区清除为下表中的值。 如果 clearOnAccess 为 false,则附加到不透明纹理的缓冲区必须在首次访问时清除。 后续帧中的再次访问可以不清除缓冲区。

缓冲区 清除值
颜色 (0, 0, 0, 0)
深度 1.0
模板 0

如果不透明纹理 创建时具有 2 个或更多 mipLevels, 作者应填充所有 mip 级别。用户代理不得假定其应创建这些 mip 级别。

注:不透明纹理是在构造层时使用 分配颜色 纹理和分配深度纹理算法进行分配的。这种 预分配的副作用是,使用相同参数调用 getSubImage() 和 getViewSubImage() 将始终返回相同的纹理对象。

注:不允许更改不透明纹理的尺寸或格式。GL 命令 只能修改纹素值和纹理参数。对 WebGLTexture 使用以下任何 命令都会导致生成 INVALID_OPERATION 错误, 即使该命令不会影响尺寸或格式也是如此:TexImage*、CompressedTexImage*、 CopyTexImage* 和 TexStorage*。 OpenGL ES 3.0 规范中的 “不可变格式 纹理图像” 一节更详细地定义了这些限制。

层资源(例如内存)的分配必须通过与 WebGL 相同的机制完成。

如果一个 XRLayer 使用 RGBA 或 RGB colorFormat 进行分配, 则其 colorTextures 必须以 RGBA 或 RGB 的形式公开给 WebGLRenderingContext 上下文。 但是,XR 合成器必须将 colorTextures 的像素视为采用 SRGB8_ALPHA8 或 SRGB8 colorFormat。

注:这意味着 XR 合成器在处理 colorTextures 时,不得对线性的 RGBA 或 RGB 执行任何伽马转换。否则,最终渲染中的像素会显得 过亮,这与常规 2D WebGLRenderingContext 上下文中的渲染结果不匹配。

6.3. XRProjectionLayerInit

The XRProjectionLayerInit 字典表示一组可配置的值,用于描述如何初始化 XRProjectionLayer。
dictionary XRProjectionLayerInit {
  XRTextureType textureType = "texture";
  GLenum colorFormat = 0x1908; // RGBA
  GLenum depthFormat = 0x1902; // DEPTH_COMPONENT
  double scaleFactor = 1.0;
  boolean clearOnAccess = true;
};

textureType 属性定义 该层所具有的纹理类型。

colorFormat 属性定义 颜色纹理数据的数据类型。

以下是 XR 合成器必须支持的投影层颜色格式列表:

对于 WebGL2 上下文,还支持以下格式:

depthFormat 属性定义 深度纹理数据的数据类型。 如果 depthFormat 为 0,则该层不会提供深度/模板纹理。

以下是 XR 合成器必须支持的投影层深度格式列表:

对于启用了“WEBGL_depth_texture” 扩展的 WebGLRenderingContext 上下文,或 WebGL2 上下文:

如果未启用该扩展,则对深度纹理的请求将被忽略。

注:这可能会让作者感到困惑,因为他们 可能期望获得深度纹理。如果可能,请提供警告,说明纹理未 创建的原因。

对于 WebGL2RenderingContext 上下文,还支持以下格式:

scaleFactor 属性定义 在确定该层附件的分辨率时,session 的 推荐的 WebGL 帧缓冲区分辨率必须 乘以的值。

clearOnAccess 属性 定义与此层关联的纹理是应在初始帧中清除,还是在每一帧中清除。

注:XRProjectionLayerInit 字典不像 XRLayerInit 那样支持配置 mipLevels。 如果用户代理希望在投影层上支持 mipmapping,则可以自由地为纹理分配 mip。 在这种情况下,由用户代理(而不是作者)负责生成所有 mip 级别。

6.4. XRLayerInit

XRLayerInit 字典表示一组通用可配置值,用于 XRQuadLayer、 XRCylinderLayer、 XREquirectLayer 和 XRCubeLayer。
dictionary XRLayerInit {
  required XRSpace space;
  XRTextureType textureType = "texture";
  GLenum colorFormat = 0x1908; // RGBA
  GLenum? depthFormat;
  unsigned long mipLevels = 1;
  required unsigned long viewPixelWidth;
  required unsigned long viewPixelHeight;
  XRLayerLayout layout = "mono";
  boolean isStatic = false;
  boolean clearOnAccess = true;
};

space 属性定义与 用户物理环境的空间关系。

textureType 属性定义层的 纹理类型。XR Compositor 必须支持:

对于 WebGL2RenderingContext, 还支持这些附加类型:

colorFormat 属性定义 颜色纹理数据的数据类型。

这是 XR Compositor 必须支持的非投影 层颜色格式列表:

对于 WebGL2 上下文,还支持以下附加格式:

对于启用了 'WEBGL_compressed_texture_etc' 扩展的上下文,支持以下附加格式:

对于启用了 'WEBGL_compressed_texture_astc' 扩展的上下文,支持该扩展的所有格式。

depthFormat 属性定义 深度纹理数据的数据类型。 如果未提供 depthFormat, 则该层不会提供深度/模板纹理。

这是 XR Compositor 必须支持的非投影 层深度格式列表:

对于启用了 'WEBGL_depth_texture' 扩展的 WebGLRenderingContext 上下文或 WebGL2 上下文:

对于 WebGL2RenderingContext 上下文,支持以下附加格式:

mipLevels 属性定义颜色和纹理数据中期望的 mip 级别数量。 如果用户代理无法创建请求的数量,则可以创建更少的数量。作者必须查询 mipLevels 以确定 实际的 mip 级别数量。

viewPixelWidth 和 viewPixelHeight 属性定义 XRCompositionLayer 的矩形尺寸。

layout 属性定义层的布局。

clearOnAccess 属性定义与此层 关联的纹理应在初始帧中清除,还是在每一帧中清除。

6.5. XRQuadLayerInit

XRQuadLayerInit 字典表示一组可配置值,这些值描述如何初始化 XRQuadLayer。

dictionary XRQuadLayerInit : XRLayerInit {
  XRRigidTransform? transform;
  float width = 1.0;
  float height = 1.0;
};

6.6. XRCylinderLayerInit

XRCylinderLayerInit 字典表示一组可配置值,这些值描述如何初始化 XRCylinderLayer。

dictionary XRCylinderLayerInit : XRLayerInit {
  XRRigidTransform? transform;
  float radius = 2.0;
  float centralAngle = 0.78539;
  float aspectRatio = 2.0;
};

centralAngle 的默认值为 π / 4。

6.7. XREquirectLayerInit

XREquirectLayerInit 字典表示一组可配置值,这些值描述如何初始化 XREquirectLayer。

dictionary XREquirectLayerInit : XRLayerInit {
  XRRigidTransform? transform;
  float radius = 0;
  float centralHorizontalAngle = 6.28318;
  float upperVerticalAngle = 1.570795;
  float lowerVerticalAngle = -1.570795;
};

centralHorizontalAngle 的默认值为 2π。 upperVerticalAngle 的默认值为 π/2。 lowerVerticalAngle 的默认值为 -π/2。

6.8. XRCubeLayerInit

XRCubeLayerInit 字典表示一组可配置值,这些值描述如何初始化 XRCubeLayer。

dictionary XRCubeLayerInit : XRLayerInit {
  DOMPointReadOnly? orientation;
};

6.9. XRWebGLBinding

XRWebGLBinding 对象用于创建具有 GPU 后端的层。
[Exposed=Window] interface XRWebGLBinding {
  constructor(XRSession session, XRWebGLRenderingContext context);

  readonly attribute double nativeProjectionScaleFactor;
  readonly attribute boolean usesDepthValues;

  XRProjectionLayer createProjectionLayer(optional XRProjectionLayerInit init = {});
  XRQuadLayer createQuadLayer(optional XRQuadLayerInit init = {});
  XRCylinderLayer createCylinderLayer(optional XRCylinderLayerInit init = {});
  XREquirectLayer createEquirectLayer(optional XREquirectLayerInit init = {});
  XRCubeLayer createCubeLayer(optional XRCubeLayerInit init = {});

  XRWebGLSubImage getSubImage(XRCompositionLayer layer, XRFrame frame, optional XREye eye = "none");
  XRWebGLSubImage getViewSubImage(XRProjectionLayer layer, XRView view);

  undefined foveateBoundTexture(GLenum target, float fixed_foveation);
};

init 字典 不应是可选的。这是 Bikeshed issue 1566。

每个 XRWebGLBinding 都有一个类型为 XRWebGLRenderingContext 的 context 对象,它是 WebGLRenderingContext 或 WebGL2RenderingContext 的实例。

每个 XRWebGLBinding 都有一个关联的 session,即创建它时使用的 XRSession。

每个 XRWebGLBinding 都有一个内部 WeakSet foveatedTextures,其中保存 在调用 foveateBoundTexture 时绑定到指定目标的纹理的弱引用。

注:可以创建多个 XRWebGLBinding。 使用一个 XRWebGLBinding 实例创建的任何层, 只要二者使用相同的session 和相同的 context 创建, 就可以与另一个 XRWebGLBinding 实例一起使用。层或 XRWebGLSubImage 实例的生命周期并不与创建它们的 XRWebGLBinding 的生命周期绑定。

每个通过 XRWebGLBinding 创建的 XRCompositionLayer 都有一个内部 colorTextures 数组,它是一个由用于颜色纹理的 WebGLTextures 构成的 array; 一个内部 depthStencilTextures,它是一个由用于 深度/模板纹理的不透明纹理 构成的 array;以及 一个内部 motionVectorTextures,它是一个由用于运动 纹理的不透明纹理构成的 array。

每个通过 XRWebGLBinding 创建的 XRProjectionLayer 都有一个内部 辅助视图的 colorTextures 数组,它是一个由用于颜色纹理的不透明纹理构成的 array;以及一个内部 辅助视图的 depthStencilTextures 数组,它是一个由用于渲染辅助视图的深度/模板纹理的不透明纹理构成的 array。

XRWebGLBinding(session, context) 构造函数 在调用时必须执行以下步骤:

  1. 令 binding 为 session 的相关领域中的一个新 XRWebGLBinding。

  2. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  3. 如果 context 已丢失,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 session 不是沉浸式会话,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 context 的XR 兼容布尔值为 false,则抛出 InvalidStateError 并中止这些步骤。

  6. 将 binding 的context 初始化为 context。

  7. 将 binding 的session 初始化为 session。

  8. 将 binding 添加到 session 的bindings。

  9. 返回 binding。

nativeProjectionScaleFactor 函数返回一个值,session 的推荐的 WebGL 帧缓冲区分辨率 必须乘以该值,才能得到 session 的原生 WebGL 帧缓冲区分辨率。

如果尺寸导致布局发生变化, 则需特殊处理用户代理行为(例如在 "stereo-left-right" 下请求的宽度超过限制时)

usesDepthValues 属性如果为 false,则表示存在深度缓冲区附件时, XR 合成器不得使用其中的值。当该属性 为 true 时,表示深度缓冲区附件的内容将由 XR 合成器使用,并且预期它能够代表渲染到该层中的场景。

要使用一个 XRTextureType textureType、一个 XRWebGLRenderingContext context 和一个 XRLayerLayout layout 确定 layout 属性,用户代理必须运行以下步骤:

  1. 如果 context 不是 WebGL2RenderingContext 且 textureType 为 "texture-array", 则抛出 TypeError 并中止这些步骤。

  2. 如果 textureType 为 "texture-array" 且会话视图列表中的所有视图并非都具有相同的推荐的 WebGL 颜色纹理 分辨率,则抛出 NotSupportedError 并中止这些步骤。

  3. 如果 layout 为 "mono", 则返回 layout 并中止这些步骤。

  4. 如果 layout 为 "default", 则运行以下步骤:

    1. 如果视图列表的大小为 1,则返回 "mono" 并中止这些步骤。

    2. 如果 textureType 为 "texture-array", 则返回 layout 并中止这些步骤。

  5. 如果 layout 为 "default" 或 "stereo" 且 textureType 为 "texture", 则运行以下步骤:

    1. 如果用户代理偏好 "stereo-left-right" 布局,则返回 "stereo-left-right" 并中止这些步骤。

    2. 如果用户代理偏好 "stereo-top-bottom" 布局,则返回 "stereo-top-bottom" 并中止这些步骤。

  6. 返回 layout。

要使用一个 XRSession session、一个 XRWebGLRenderingContext context 和一个 XRLayerLayout layout 确定最大 scaleFactor,用户代理必须运行以下步骤:

  1. 令 largest width 为 session 的视图列表中除辅助视图之外各视图的推荐的 WebGL 颜色纹理 分辨率中的最大宽度。

  2. 令 largest height 为 session 的视图列表中除辅助视图之外各视图的推荐的 WebGL 颜色纹理 分辨率中的最大高度。

  3. 如果 layout 是 "stereo-left-right" 布局,则将 largest width 乘以 2。

  4. 如果 layout 是 "stereo-top-bottom" 布局,则将 largest height 乘以 2。

  5. 令 largest view dimension 为 largest width 与 largest height 中较大的值。

  6. 令 largest texture dimension 为由 context 创建的 WebGLTexture 的最大尺寸。

  7. 返回 largest texture dimension 除以 largest view dimension 的结果。

要使用一个 XRProjectionLayer layer、一个 XRTextureType textureType、一个 GLenum textureFormat 和一个 float scaleFactor 为投影层分配颜色纹理,用户代理必须运行以下 步骤:

  1. 令 array 为 context 的相关领域中的一个新数组。

  2. 令 context 为 layer 的context。

  3. 令 session 为 layer 的session。

  4. 令 numViews 为 session 的视图列表中除辅助视图之外的视图数量。

  5. 令 view 为 session 的视图列表中第一个不是辅助视图的条目。

  6. 令 width 为 view 的推荐的 WebGL 颜色纹理 分辨率的宽度乘以 scaleFactor。

  7. 令 height 为 view 的推荐的 WebGL 颜色纹理 分辨率的高度乘以 scaleFactor。

  8. 如果 textureFormat 不在投影层颜色格式 列表中,则抛出 NotSupportedError 并中止这些步骤。

  9. 如果 layer 的 layout 为 "mono" 或 "default":

    如果 textureType 为 "texture-array":
    如果会话的视图列表中的视图在排除辅助视图后并非都具有相同的推荐的 WebGL 颜色纹理 分辨率,则抛出 NotSupportedError 并中止这些步骤。
    使用 1 个新的不透明 纹理实例初始化 array,该实例位于 context 的相关领域中,并使用 context、textureFormat、 width 和 height 创建为一个具有 numViews 个层的 TEXTURE_2D_ARRAY 纹理。
    如果由于任何原因无法创建该不透明 纹理,则抛出 OperationError 并中止这些步骤。
    返回 array 并中止这些步骤。
    否则
    对于 session 的视图列表中的每个 view:
    1. 如果 view 是辅助视图,则继续。

    2. 令 width 为 view 的推荐的 WebGL 颜色纹理分辨率的宽度乘以 scaleFactor。

    3. 令 height 为 view 的推荐的 WebGL 颜色纹理分辨率的高度乘以 scaleFactor。

    4. 令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、textureFormat、width 和 height 创建为 TEXTURE_2D 纹理。

    5. 如果由于任何原因无法创建 texture,则抛出 OperationError 并中止这些步骤。

    6. 将 texture 追加到 array。

    返回 array 并中止这些步骤。
  10. 如果会话视图列表中的视图在排除辅助 视图后并非都具有相同的推荐的 WebGL 颜色纹理 分辨率,则抛出 NotSupportedError 并中止这些步骤。

  11. 如果 layer 的 layout 为 stereo-left-right, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context、textureFormat、 numViews 乘以 width 以及 height 创建为 textureType 纹理。

  12. 如果 layer 的 layout 为 stereo-top-bottom, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context、textureFormat、 width 以及 numViews 乘以 height 创建为 textureType 纹理。

  13. 如果由于任何原因无法创建该不透明 纹理,则抛出 OperationError 并中止这些步骤。

  14. 返回 array。

要使用一个 XRProjectionLayer layer、一个 XRTextureType textureType、一个 GLenum textureFormat 和一个 float scaleFactor 为投影层分配深度纹理,用户代理必须运行以下 步骤:

  1. 令 context 为 layer 的context。

  2. 令 array 为 context 的相关领域中的一个新数组。

  3. 令 session 为 layer 的session。

  4. 如果 textureFormat 为 0,则返回 array 并中止这些步骤。

  5. 如果 context 是 WebGLRenderingContext 且 WEBGL_depth_texture 扩展未在 context 中启用,则返回 array 并中止这些步骤。

  6. 如果 textureFormat 不在投影层深度格式 列表中,则抛出 NotSupportedError 并中止这些步骤。

  7. 令 numViews 为 session 的视图列表中除辅助视图之外的视图数量。

  8. 令 view 为 session 的视图列表中第一个不是辅助视图的条目。

  9. 令 recommendedDepthResolution 为 view 的推荐的 WebGL 深度纹理 分辨率。

  10. 如果 session 创建时使用了“space-warp”特性描述符,则将 recommendedDepthResolution 设置为 view 的推荐的运动矢量纹理 分辨率。

  11. 令 width 为 recommendedDepthResolution 的宽度乘以 scaleFactor。

  12. 令 height 为 recommendedDepthResolution 的高度乘以 scaleFactor。

  13. 如果 layer 的 layout 为 "mono" 或 "default":

    如果 textureType 为 "texture-array":
    使用 1 个新的不透明 纹理实例初始化 array,该实例位于 context 的相关领域中,并使用 context、textureFormat、 stencil、width 和 height 创建为一个具有 numViews 个层的 TEXTURE_2D_ARRAY 纹理。
    如果由于任何原因无法创建该不透明 纹理,则抛出 OperationError 并中止这些步骤。
    返回 array 并中止这些步骤。
    否则
    对于 session 的视图列表中的每个 view:
    1. 如果 view 是辅助视图,则继续。

    2. 令 recommendedDepthResolution 为 view 的推荐的 WebGL 深度纹理分辨率。

    3. 如果 session 创建时使用了“space-warp”特性描述符,则将 recommendedDepthResolution 设置为 view 的推荐的 运动矢量纹理分辨率。

    4. 令 width 为 recommendedDepthResolution 的宽度乘以 scaleFactor。

    5. 令 height 为 recommendedDepthResolution 的高度乘以 scaleFactor。

    6. 令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、textureFormat、stencil、 width 和 height 创建为 TEXTURE_2D 纹理。

    7. 如果由于任何原因无法创建 texture,则抛出 OperationError 并中止这些步骤。

    8. 将 texture 追加到 array。

    返回 array 并中止这些步骤。
  14. 如果 session 创建时使用了“space-warp”特性描述符,并且会话视图列表中的视图 在排除辅助 视图后并非都具有相同的推荐的运动矢量纹理 分辨率,则抛出 NotSupportedError 并中止这些步骤。

  15. 如果 session 创建时未使用“space-warp”特性描述符,并且会话视图列表中的视图 在排除辅助 视图后并非都具有相同的推荐的 WebGL 深度纹理 分辨率,则抛出 NotSupportedError 并中止这些步骤。

  16. 如果 layer 的 layout 为 stereo-left-right, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context、textureFormat、 stencil、numViews 乘以 width 以及 height 创建为 textureType 纹理。

  17. 如果 layer 的 layout 为 stereo-top-bottom, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context、textureFormat、 stencil、width 以及 numViews 乘以 height 创建为 textureType 纹理。

  18. 如果由于任何原因无法创建该不透明 纹理,则抛出 OperationError 并中止这些步骤。

  19. 返回 array。

要使用一个 XRProjectionLayer layer、一个 XRTextureType textureType 和一个 float scaleFactor 为投影层分配运动矢量纹理,用户代理必须运行以下步骤:

  1. 令 context 为 layer 的context。

  2. 令 array 为 context 的相关领域中的一个新数组。

  3. 令 session 为 layer 的session。

  4. 如果 session 创建时未使用“space-warp”特性描述符,则返回 array 并中止 这些步骤。

  5. 如果 context 是 WebGLRenderingContext 且 WEBGL_depth_texture 扩展未在 context 中启用,则返回 array 并中止这些步骤。

  6. 令 numViews 为 session 的视图列表中除辅助视图之外的视图数量。

  7. 令 view 为 session 的视图列表中第一个不是辅助视图的条目。

  8. 令 width 为 view 的推荐的运动矢量纹理 分辨率的宽度乘以 scaleFactor。

  9. 令 height 为 view 的推荐的运动矢量纹理 分辨率的高度乘以 scaleFactor。

  10. 如果 layer 的 layout 为 "mono" 或 "default":

    如果 textureType 为 "texture-array":
    使用 1 个新的不透明 纹理实例初始化 array,该实例位于 context 的相关领域中,并使用 context、RGBA16F、 width 和 height 创建为一个具有 numViews 个层的 TEXTURE_2D_ARRAY 纹理。
    如果由于任何原因无法创建该不透明 纹理,则抛出 OperationError 并中止这些步骤。
    返回 array 并中止这些步骤。
    否则
    对于 session 的视图列表中的每个 view:
    1. 如果 view 是辅助视图,则继续。

    2. 令 width 为 view 的推荐的 运动矢量纹理分辨率的宽度乘以 scaleFactor。

    3. 令 height 为 view 的推荐的 运动矢量纹理分辨率的高度乘以 scaleFactor。

    4. 令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、RGBA16F、 width 和 height 创建为 TEXTURE_2D 纹理。

    5. 如果由于任何原因无法创建 texture,则抛出 OperationError 并中止这些步骤。

    6. 将 texture 追加到 array。

    返回 array 并中止这些步骤。
  11. 如果会话视图列表中的视图在排除辅助 视图后并非都具有相同的推荐的运动矢量纹理 分辨率,则抛出 NotSupportedError 并中止这些步骤。

  12. 如果 layer 的 layout 为 stereo-left-right, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context、RGBA16F、 numViews 乘以 width 以及 height 创建为 textureType 纹理。

  13. 如果 layer 的 layout 为 stereo-top-bottom, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context、RGBA16F、 width 以及 numViews 乘以 height 创建为 textureType 纹理。

  14. 如果由于任何原因无法创建该不透明 纹理,则抛出 OperationError 并中止这些步骤。

  15. 返回 array。

要使用一个 XRProjectionLayer layer、一个 XRTextureType textureType、一个 GLenum textureFormat 和一个 float scaleFactor 为 辅助视图分配颜色纹理,用户代理必须运行以下 步骤:

  1. 令 context 为 layer 的context。

  2. 令 session 为 layer 的session。

  3. 令 array 为 context 的相关领域中的一个新数组。

  4. 如果 textureFormat 不在投影层颜色格式 列表中,则抛出 NotSupportedError 并中止这些步骤。

  5. 对于 session 的视图列表中的每个 view:

    1. 如果 view 不是辅助视图,则继续。

    2. 令 width 为 view 的推荐的 WebGL 颜色 纹理分辨率的宽度乘以 scaleFactor。

    3. 令 height 为 view 的推荐的 WebGL 颜色 纹理分辨率的高度乘以 scaleFactor。

    4. 按如下方式初始化 texture:

      如果 textureType 为 "texture-array":
      令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、textureFormat、width 和 height 创建为 TEXTURE_2D_ARRAY 纹理。
      否则
      令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、textureFormat、width 和 height 创建为 TEXTURE_2D 纹理。
    5. 如果由于任何原因无法创建 texture,则抛出 OperationError 并中止这些步骤。

    6. 将 texture 追加到 array。

  6. 返回 array 并中止这些步骤。

要使用一个 XRProjectionLayer layer、一个 XRTextureType textureType、一个 GLenum textureFormat 和一个 float scaleFactor 为 辅助视图分配深度纹理,用户代理必须运行以下 步骤:

  1. 令 context 为 layer 的context。

  2. 令 session 为 layer 的session。

  3. 如果 textureFormat 为 0,则返回 array 并中止这些步骤。

  4. 如果 context 是 WebGLRenderingContext 且 WEBGL_depth_texture 扩展未在 context 中启用,则返回 array 并中止这些步骤。

  5. 如果 textureFormat 不在投影层深度格式 列表中,则抛出 NotSupportedError 并中止这些步骤。

  6. 令 array 为 context 的相关领域中的一个新数组。

  7. 对于 session 的视图列表中的每个 view:

    1. 如果 view 不是辅助视图,则继续。

    2. 令 width 为 view 的推荐的 WebGL 深度 纹理分辨率的宽度乘以 scaleFactor。

    3. 令 height 为 view 的推荐的 WebGL 深度 纹理分辨率的高度乘以 scaleFactor。

    4. 按如下方式初始化 texture:

      如果 textureType 为 "texture-array":
      令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、textureFormat、stencil、 width 和 height 创建为 TEXTURE_2D_ARRAY 纹理。
      否则
      令 texture 为 context 的相关领域中的一个新 不透明纹理实例, 使用 context、textureFormat、stencil、 width 和 height 创建为 TEXTURE_2D 纹理。
    5. 将 texture 追加到 array。

  8. 返回 array 并中止这些步骤。

需要针对辅助视图 重新计算 scaleFactor。

要使用一个 XRCompositionLayer layer、一个 XRTextureType textureType 和一个 XRLayerInit init 分配颜色 纹理,用户代理必须运行以下步骤:

  1. 令 array 为 context 的相关领域中的一个新数组。

  2. 令 context 为 layer 的context。

  3. 如果 init 的 colorFormat 不在非投影层颜色格式 列表中,则抛出 NotSupportedError 并中止这些步骤。

  4. 如果 init 的 mipLevels 小于 1,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 init 的 mipLevels 大于 1,并且 viewPixelWidth 和 viewPixelHeight 不是 2 的幂,则抛出 InvalidStateError 并中止这些步骤

  6. 如果 layer 的 layout 为 "mono":

    如果 textureType 为 "texture-array":
    使用位于此 context 的相关领域中的 1 个新不透明 纹理实例初始化 array,该实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 1 个内部纹理的 TEXTURE_2D_ARRAY 纹理。
    否则
    使用位于 context 的相关领域中的 1 个新不透明 纹理实例初始化 array,该实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_2D 纹理。
  7. 如果 layer 的 layout 为 "stereo":

    如果 textureType 为 "texture-array":
    使用位于 context 的相关领域中的 1 个新不透明 纹理实例初始化 array,该实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 2 个层的 TEXTURE_2D_ARRAY 纹理。
    返回 array 并中止这些步骤。
    否则
    使用位于 context 的相关领域中的 2 个新不透明 纹理实例初始化 array,这些实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_2D 纹理。
    返回 array 并中止这些步骤。
  8. 如果 layer 的 layout 为 stereo-left-right, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context 和 init 的 colorFormat、 mipLevels、 两倍的 viewPixelWidth 和 viewPixelHeight 值创建为 textureType 纹理。

  9. 如果 layer 的 layout 为 stereo-top-bottom, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和两倍的 viewPixelHeight 值创建为 textureType 纹理。

  10. 返回 array。

要使用一个 XRCompositionLayer layer、一个 XRTextureType textureType 和一个 XRLayerInit init 分配深度 纹理,用户代理必须运行以下步骤:

  1. 令 array 为 context 的相关领域中的一个新数组。

  2. 令 context 为 layer 的context。

  3. 如果未设置 init 的 depthFormat, 则返回 array 并中止这些步骤。

  4. 如果 init 的 depthFormat 不在非投影层深度格式 列表中,则抛出 NotSupportedError 并中止这些步骤。

  5. 如果 init 的 mipLevels 小于 1,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 init 的 mipLevels 大于 1,并且 viewPixelWidth 和 viewPixelHeight 不是 2 的幂,则抛出 InvalidStateError 并中止这些步骤。

  7. 如果 layer 的 layout 为 "mono":

    如果 textureType 为 "texture-array":
    使用位于 context 的相关领域中的 1 个新不透明 纹理实例初始化 array,该实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 1 个内部纹理的 TEXTURE_2D_ARRAY 纹理。
    否则
    使用位于 context 的相关领域中的 1 个新不透明 纹理实例初始化 array,该实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_2D 纹理。
  8. 如果 layer 的 layout 为 "stereo":

    如果 textureType 为 "texture-array":
    使用位于 context 的相关领域中的 1 个新不透明 纹理实例初始化 array,该实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 2 个层的 TEXTURE_2D_ARRAY 纹理。
    返回 array 并中止这些步骤。
    否则
    使用位于 context 的相关领域中的 2 个新不透明 纹理实例初始化 array,这些实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_2D 纹理。
    返回 array 并中止这些步骤。
  9. 如果 layer 的 layout 为 stereo-left-right, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context 和 init 的 depthFormat、 mipLevels、 两倍的 viewPixelWidth 和 viewPixelHeight 值创建为 textureType 纹理。

  10. 如果 layer 的 layout 为 stereo-top-bottom, 则使用位于 context 的相关领域中的 1 个新不透明纹理 实例初始化 array,该实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和两倍的 viewPixelHeight 值创建为 textureType 纹理。

  11. 返回 array。

createProjectionLayer(optional XRProjectionLayerInit init) 方法创建一个新的 XRProjectionLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 令 context 为此对象的context。

  3. 令 layer 为此对象的相关领域中的一个新 XRProjectionLayer。

  4. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 context 已丢失,则抛出 InvalidStateError 并中止这些步骤。

  6. 使用 session 和 context 在 layer 上运行初始化合成层。

  7. 将 layer 的isStatic 初始化为 false。

  8. 按如下方式初始化 layer 的 ignoreDepthValues:

    如果 session 创建时使用了“space-warp”特性描述符
    将 layer 的 ignoreDepthValues 初始化为 false
    如果 init 的 depthFormat 为 false 且 XR 合成器将使用深度值
    将 layer 的 ignoreDepthValues 初始化为 false
    否则
    将 layer 的 ignoreDepthValues 初始化为 true
  9. 将 layer 的 fixedFoveation 初始化为 0。

  10. 令 layout 为使用 init 的 textureType、 context 和 "default" 确定 layout 属性的结果。

  11. 令 maximum scalefactor 为使用 session、context 和 layout 确定最大 scaleFactor的结果。

  12. 如果 scaleFactor 大于 maximum scalefactor,则将 scaleFactor 设置为 maximum scalefactor。

  13. 将 layer 的 layout 初始化为 layout。

  14. 将 layer 的 needsRedraw 初始化为 true。

  15. 令 layer 的colorTextures 为使用 layer、init 的 textureType、 init 的 colorFormat 和 init 的 scaleFactor 为投影层分配颜色纹理的结果。

  16. 令 layer 的depthStencilTextures 为使用 layer、init 的 textureType、 init 的 depthFormat 和 init 的 scaleFactor 为投影层分配深度纹理的结果。

  17. 令 layer 的motionVectorTextures 为使用 layer、init 的 textureType 和 init 的 scaleFactor 为投影层分配运动矢量 纹理的结果。

  18. 按如下方式初始化辅助视图的 colorTextures:

    如果 session 创建时启用了“secondary-views”
    令辅助视图的 colorTextures 为使用 layer、init 的 textureType、 init 的 colorFormat 和 init 的 scaleFactor 为辅助视图分配颜色 纹理的结果。
    否则
    令辅助视图的 colorTextures 为 null。
  19. 按如下方式初始化辅助视图的 depthStencilTextures:

    如果 session 创建时启用了“secondary-views”
    令辅助视图的 depthStencilTextures 为使用 layer、init 的 textureType、 init 的 depthFormat 和 init 的 scaleFactor 为辅助视图分配深度 纹理的结果。
    否则
    令辅助视图的 depthStencilTextures 为 null。
  20. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  21. 返回 layer。

createQuadLayer(XRQuadLayerInit init) 方法创建一个新的 XRQuadLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 令 context 为此对象的context。

  4. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 context 已丢失,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 layout 为 "default", 则抛出 TypeError 并中止这些步骤。

  7. 令 layer 为此对象的相关领域中的一个新 XRQuadLayer。

  8. 使用 session 和 context 在 layer 上运行初始化合成层。

  9. 使用 layer 和 init 运行初始化四边形层。

  10. 令 layout 为使用 init 的 textureType、 context 和 init 的 layout 确定 layout 属性的结果。

  11. 将 layer 的 layout 初始化为 layout。

  12. 将 layer 的 needsRedraw 初始化为 true。

  13. 令 layer 的colorTextures 为使用 layer、init 的 textureType 和 init 分配颜色 纹理的结果。

  14. 令 layer 的depthStencilTextures 为使用 layer、 init 的 textureType 和 init 分配深度纹理的结果。

  15. 令 layer 的motionVectorTextures 为 context 的相关领域中的一个新数组。

  16. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  17. 返回 layer。

createCylinderLayer(XRCylinderLayerInit init) 方法创建一个新的 XRCylinderLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 令 context 为此对象的context。

  4. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 context 已丢失,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 layout 为 "default", 则抛出 TypeError 并中止这些步骤。

  7. 令 layer 为此对象的相关领域中的一个新 XRCylinderLayer。

  8. 使用 session 和 context 在 layer 上运行初始化合成层。

  9. 使用 layer 和 init 运行初始化圆柱层。

  10. 令 layout 为使用 init 的 textureType、 context 和 init 的 layout 确定 layout 属性的结果。

  11. 将 layer 的 layout 初始化为 layout。

  12. 将 layer 的 needsRedraw 初始化为 true。

  13. 令 layer 的colorTextures 为使用 layer、init 的 textureType 和 init 分配颜色 纹理的结果。

  14. 令 layer 的depthStencilTextures 为使用 layer、 init 的 textureType 和 init 分配深度纹理的结果。

  15. 令 layer 的motionVectorTextures 为 context 的相关领域中的一个新数组。

  16. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  17. 返回 layer。

createEquirectLayer(XREquirectLayerLayerInit init) 方法创建一个新的 XREquirectLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 令 context 为此对象的context。

  4. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 context 已丢失,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 layout 为 "default", 则抛出 TypeError 并中止这些步骤。

  7. 如果 init 的 space 不是 XRReferenceSpace 类型的实例,则抛出 TypeError 并中止这些步骤。

  8. 如果 init 的 space 的类型为 "viewer", 则抛出 TypeError 并中止这些步骤。

  9. 令 layer 为此对象的相关领域中的一个新 XREquirectLayer。

  10. 使用 session 和 context 在 layer 上运行初始化合成层。

  11. 使用 layer 和 init 运行初始化等距柱状投影层。

  12. 令 layout 为使用 init 的 textureType、 context 和 init 的 layout 确定 layout 属性的结果。

  13. 将 layer 的 layout 初始化为 layout。

  14. 将 layer 的 needsRedraw 初始化为 true。

  15. 令 layer 的colorTextures 为使用 layer、init 的 textureType 和 init 分配颜色 纹理的结果。

  16. 令 layer 的depthStencilTextures 为使用 layer、 init 的 textureType 和 init 分配深度纹理的结果。

  17. 令 layer 的motionVectorTextures 为 context 的相关领域中的一个新数组。

  18. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  19. 返回 layer。

createCubeLayer(XRCubeLayerInit init) 方法创建一个新的 XRCubeLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 令 context 为此对象的context。

  4. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 context 不是 WebGL2RenderingContext 上下文,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 context 已丢失,则抛出 InvalidStateError 并中止这些步骤。

  7. 如果 init 的 space 不是 XRReferenceSpace 类型的实例,则抛出 TypeError 并中止这些步骤。

  8. 如果 init 的 space 的类型为 "viewer", 则抛出 TypeError 并中止这些步骤。

  9. 令 layer 为此对象的相关领域中的一个新 XRCubeLayer。

  10. 使用 session 和 context 在 layer 上运行初始化合成层。

  11. 令 layer 的 space 为 init 的 space。

  12. 将 layer 的isStatic 初始化为 init 的 isStatic

  13. 按如下方式初始化 layer 的 orientation:

    如果设置了 init 的 orientation
    令 layer 的 orientation 为使用 init 的 orientation 运行 fromPoint 的结果。
    否则
    令 layer 的 orientation 为此对象的相关领域中的一个新 DOMPointReadOnly。
  14. 令 layout 为 init 的 layout。

  15. 令 textureType 为 init 的 textureType。

  16. 将 layer 的 needsRedraw 初始化为 true。

  17. 如果 layout 为 "default" 或 "stereo-left-right" 或 "stereo-top-bottom", 则抛出 TypeError 并中止这些步骤。

  18. 令 layer 的colorTextures 为此 XRCubeLayer 的相关领域中的一个新数组。

  19. 根据 layout 的值,按如下方式初始化 layer 的colorTextures:

    1. 如果 layer 的 layout 为 "mono":

      如果 textureType 为 "texture-array":
      使用位于此 XRCubeLayer 的相关领域中的 1 个新不透明纹理实例初始化colorTextures,该实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 6 个层的 TEXTURE_2D_ARRAY 纹理。
      否则
      使用位于此 XRCubeLayer 的相关领域中的 1 个新不透明纹理实例初始化colorTextures,该实例使用 context 和 init 的 colorFormat、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_CUBE_MAP 纹理。
    2. 否则,如果 layer 的 layout 为 "stereo":

      如果 textureType 为 "texture-array":
      使用位于此 XRCubeLayer 的相关领域中的 1 个新不透明纹理实例初始化colorTextures,该实例使用 context 和 init 的 colorFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 12 个层的 TEXTURE_2D_ARRAY 纹理。
      否则
      使用位于此 XRCubeLayer 的相关领域中的 2 个新不透明纹理实例初始化colorTextures,这些实例使用 context 和 init 的 colorFormat、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_CUBE_MAP 纹理。
  20. 令 layer 的depthStencilTextures 为此 XRCubeLayer 的相关领域中的一个新数组。

  21. 令 layer 的motionVectorTextures 为此 XRCubeLayer 的相关领域中的一个新数组。

  22. 如果设置了 init 的 depthFormat, 则按如下方式初始化 layer 的depthStencilTextures:

    1. 如果 context 不是 WebGL2RenderingContext 且 WEBGL_depth_texture 扩展未在 context 中启用,则抛出 TypeError 并中止这些步骤。

    2. 如果 layer 的 layout 为 "mono":

      如果 textureType 为 "texture-array":
      使用位于此 XRCubeLayer 的相关领域中的 1 个新不透明纹理实例初始化 depthStencilTextures,该实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 6 个层的 TEXTURE_2D_ARRAY 纹理。
      否则
      使用位于此 XRCubeLayer 的相关领域中的 1 个新不透明纹理实例初始化 depthStencilTextures,该实例使用 context 和 init 的 depthFormat、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_CUBE_MAP 纹理。
    3. 否则,如果 layer 的 layout 为 "stereo":

      如果 textureType 为 "texture-array":
      使用位于此 XRCubeLayer 的相关领域中的 1 个新不透明纹理实例初始化 depthStencilTextures,该实例使用 context 和 init 的 depthFormat、 mipLevels、 viewPixelWidth 和 viewPixelHeight 值创建为一个具有 12 个层的 TEXTURE_2D_ARRAY 纹理。
      否则
      使用位于此 XRCubeLayer 的相关领域中的 2 个新不透明纹理实例初始化 depthStencilTextures,这些实例使用 context 和 init 的 depthFormat、 viewPixelWidth 和 viewPixelHeight 值创建为 TEXTURE_CUBE_MAP 纹理。
  23. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  24. 返回 layer。

当使用值为 "texture-array" 的 textureType 时,XRCubeLayer 必须使用 6 个纹理层按以下顺序存储立方体贴图的各个面: [TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_Z]

当使用值为 "texture-array" 的 textureType 和值为 "stereo" 的 layout 时,左眼的内容必须从层索引 0 开始存储,而右眼的内容 必须从层索引 6 开始存储。

定义如何确定立方体贴图的 尺寸。

应如何处理 space。 可以走到立方体贴图的边缘吗?

确定 orientation 的初始状态。

要使用参数 XRCompositionLayer layer 和 XRFrame frame 验证 XRWebGLBinding binding 的 XRWebGLSubImage 创建函数的状态,用户代理必须运行以下步骤:

  1. 如果 frame 的 session 不等于 layer 的session,则返回 false 并中止 这些步骤。

  2. 如果 frame 的active 布尔值为 false,则返回 false 并中止这些步骤。

  3. 如果 frame 的animationFrame 布尔值为 false,则返回 false 并中止这些步骤。

  4. 如果 binding 的session 不等于 layer 的session,则返回 false 并中止 这些步骤。

  5. 如果 binding 的context 不等于 layer 的context,则返回 false 并中止 这些步骤。

  6. 如果 layer 的colorTextures 数组为空或缺失,则返回 false 并中止这些步骤。

  7. 如果 layer 的isStatic 为 true,且 layer 的 needsRedraw 为 false,则返回 false 并中止这些步骤。

  8. 返回 true。

要使用一个不透明纹理 texture、一个 XRLayerLayout layout、一个整数 offset 和一个整数 num 初始化 XRViewport viewport,用户代理必须运行以下步骤:

  1. 将 viewport 的 x 设置为 0。

  2. 将 viewport 的 y 设置为 0。

  3. 将 viewport 的 width 设置为 texture 的像素宽度。

  4. 将 viewport 的 height 设置为 texture 的像素高度。

  5. 按如下方式更新 viewport:

    如果 layout 为 "stereo-left-right"
    将 viewport 的 x 设置为 texture 的像素宽度乘以 offset 再除以 num。
    将 viewport 的 width 设置为 subimage 的 texture 的像素宽度除以 num。
    否则,如果 layout 为 "stereo-top-bottom"
    将 viewport 的 y 设置为 texture 的像素高度乘以 offset 再除以 num。
    将 viewport 的 height 设置为 subimage 的 texture 的像素高度除以 num。
getSubImage(XRCompositionLayer layer, XRFrame frame, optional XREye eye = "none") 方法创建一个新的 XRWebGLSubImage。

当在 XRWebGLBinding binding 上调用此方法时,它必须运行以下步骤:

  1. 按如下方式初始化 subimage:

    如果此前曾使用相同的 binding、layer 和 eye 调用 getSubImage(), 则用户代理可以
    令 subimage 为之前使用相同参数调用时返回的同一个 XRWebGLSubImage 对象。
    否则
    令 subimage 为此对象的相关领域中的一个新 XRWebGLSubImage。
    令 subimage 的 viewport 为此对象的相关领域中的一个新 XRViewport。
  2. 令 session 为此对象的session。

  3. 如果 layer 的destroyed 为 true,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 layer 不在 session 的 layers 数组中,则抛出 TypeError 并中止这些步骤。

  5. 如果 layer 的类型为 XRProjectionLayer, 则抛出 TypeError 并中止这些步骤。

  6. 如果 layer 的 layout 属性为 "default", 则抛出 TypeError 并中止这些步骤。

  7. 令 index 为 0。

  8. 如果 layer 的 layout 属性为 "stereo":

    1. 如果 eye 为 "none", 则抛出 TypeError 并中止这些步骤。

    2. 如果 eye 为 "right":

      如果 layer 的类型为 XRCubeLayer
      将 index 设置为 6
      否则
      将 index 设置为 1
  9. 如果使用 layer 和 frame 验证 XRWebGLSubImage 创建函数的状态的结果为 false,则抛出 InvalidStateError 并中止这些步骤。

  10. 按如下方式初始化 subimage 的 imageIndex:

    如果 layer 创建时使用的 textureType 为 "texture-array"
    使用 index 初始化 subimage 的 imageIndex。
    否则
    使用 0 初始化 subimage 的 imageIndex。
  11. 按如下方式初始化 subimage 的 colorTexture:

    如果 layer 创建时使用的 textureType 为 "texture"
    使用 layer 的colorTextures 数组中偏移量为 index 的元素 初始化 subimage 的 colorTexture。
    否则
    使用 layer 的colorTextures 数组中的第一个元素 初始化 subimage 的 colorTexture。
  12. 按如下方式初始化 subimage 的 depthStencilTexture:

    如果 layer 的depthStencilTextures 是空数组
    使用 null 初始化 subimage 的 depthStencilTexture。
    否则,如果 layer 创建时使用的 textureType 为 "texture"
    使用 layer 的depthStencilTextures 数组中偏移量为 index 的元素 初始化 subimage 的 depthStencilTexture。
    否则
    使用 layer 的depthStencilTextures 数组中的第一个元素 初始化 subimage 的 depthStencilTexture。
  13. 使用 null 初始化 subimage 的 depthStencilTextureWidth、 depthStencilTextureHeight 和 motionVectorTexture。

  14. 将 subimage 的 colorTextureWidth 设置为 subimage 的 colorTexture 的像素宽度。

  15. 将 subimage 的 colorTextureHeight 设置为 subimage 的 colorTexture 的像素高度。

  16. 如果 subimage 的 depthStencilTexture 不为 null,则将 subimage 的 depthStencilTextureWidth 设置为 depthStencilTexture 数组中第一个纹理的像素宽度。

  17. 如果 subimage 的 depthStencilTexture 不为 null,则将 subimage 的 depthStencilTextureHeight 设置为 depthStencilTexture 数组中第一个纹理的像素高度。

  18. 令 viewsPerTexture 为 1。

  19. 如果 layer 的 layout 属性为 "stereo-left-right" 或 "stereo-top-bottom", 则将 viewsPerTexture 设置为 2。

  20. 使用 subimage 的 colorTexture、 layer 的 layout、 index 和 viewsPerTexture,在 subimage 的 viewport 上运行初始化视口。

  21. 排入一个任务,将 needsRedraw 设置为 false。

  22. 返回 subimage。

getViewSubImage(XRProjectionLayer layer, XRView view) 方法创建一个新的 XRWebGLSubImage。

当在 XRWebGLBinding binding 上调用此方法时,它必须运行以下步骤:

  1. 按如下方式初始化 subimage:

    如果此前曾使用相同的 binding、layer 和 view 调用 getViewSubImage(), 则用户代理可以
    令 subimage 为之前使用相同参数调用时返回的同一个 XRWebGLSubImage 对象。
    否则
    令 subimage 为此对象的相关领域中的一个新 XRWebGLSubImage。
    令 subimage 的 viewport 为此对象的相关领域中的一个新 XRViewport。
  2. 令 frame 为 view 的 frame。

  3. 令 session 为此对象的session。

  4. 如果 layer 的destroyed 为 true,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果使用 layer 和 frame 验证 XRWebGLSubImage 创建函数的状态的结果为 false,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 layer 不在 session 的 layers 数组中,则抛出 TypeError 并中止这些步骤。

  7. 如果 view 的active 标志为 false,则抛出 InvalidStateError 并中止这些步骤。

  8. 按如下方式初始化 index:

    如果 view 是 session 的视图列表中的辅助视图
    令 index 为 session 的视图列表中排除主视图后,view 的视图的偏移量。
    否则
    令 index 为 session 的视图列表中排除辅助视图后,view 的视图的偏移量。
  9. 按如下方式初始化 subimage 的 imageIndex:

    如果 layer 创建时使用的 textureType 为 "texture-array":
    使用 index 初始化 subimage 的 imageIndex。
    否则
    将 subimage 的 imageIndex 初始化为 0。
  10. 按如下方式初始化 subimage 的 colorTexture:

    如果 view 是 session 的视图列表中的辅助视图
    使用 layer 的辅助视图的 colorTextures 中偏移量为 index 的元素 初始化 subimage 的 colorTexture。
    否则,如果 layer 的 layout 为 "default" 且 layer 创建时使用的 textureType 为 "texture"
    使用 layer 的colorTextures 数组中偏移量为 index 的元素 初始化 subimage 的 colorTexture。
    否则
    使用 layer 的colorTextures 数组中的第一个元素 初始化 subimage 的 colorTexture。
  11. 按如下方式初始化 subimage 的 depthStencilTexture:

    如果 layer 的depthStencilTextures 是空数组
    使用 null 初始化 subimage 的 depthStencilTexture。
    否则,如果 view 是 session 的视图列表中的辅助视图
    使用 layer 的辅助视图的 depthStencilTextures 中偏移量为 index 的元素 初始化 subimage 的 colorTexture。
    否则,如果 layer 的 layout 为 "default" 且 layer 创建时使用的 textureType 为 "texture"
    使用 layer 的depthStencilTextures 数组中偏移量为 index 的元素 初始化 subimage 的 depthStencilTexture。
    否则
    使用 layer 的depthStencilTextures 数组中的第一个元素 初始化 subimage 的 depthStencilTexture。
  12. 按如下方式初始化 subimage 的 motionVectorTexture:

    如果 layer 的motionVectorTextures 是空数组,或者 view 是 session 的视图列表中的辅助视图
    使用 null 初始化 subimage 的 motionVectorTexture。
    否则,如果 layer 创建时使用的 textureType 为 "texture"
    使用 layer 的motionVectorTextures 数组中偏移量为 index 的元素 初始化 subimage 的 motionVectorTexture。
    否则
    使用 layer 的motionVectorTextures 数组中的第一个元素初始化 subimage 的 motionVectorTexture。
  13. 将 subimage 的 colorTextureWidth 设置为 subimage 的 colorTexture 的像素宽度。

  14. 将 subimage 的 colorTextureHeight 设置为 subimage 的 colorTexture 的像素高度。

  15. 使用 null 初始化 subimage 的 depthStencilTextureWidth 和 depthStencilTextureHeight。

  16. 如果 subimage 的 depthStencilTexture 不为 null,则将 subimage 的 depthStencilTextureWidth 设置为 depthStencilTexture 数组中第一个纹理的像素宽度。

  17. 如果 subimage 的 depthStencilTexture 不为 null,则将 subimage 的 depthStencilTextureHeight 设置为 depthStencilTexture 数组中第一个纹理的像素高度。

  18. 使用 subimage 的 colorTexture、 layer 的 layout、 index 和 session 的视图列表中的视图数量,在 subimage 的 viewport 上运行初始化视口。

  19. 将 needsRedraw 设置为 false。

  20. 返回 subimage

注:会话应尽量将对 getSubImage() 和 getViewSubImage() 的调用推迟到体验开始使用 WebGL 绘制时。 通常,这会发生在游戏逻辑运行之后。对于某些用户代理,将依赖 CPU 和 GPU 的代码划分为不同阶段,可以让它们动态优化系统资源。

foveateBoundTexture(GLenum target, float fixed_foveation) 对当前绑定的纹理或纹理数组应用注视点渲染。

当在 XRWebGLBinding binding 上调用此方法时,它必须运行以下步骤:

  1. 如果 target 的类型不是 TEXTURE_2D 或 TEXTURE_2D_ARRAY, 则抛出 InvalidStateError 并中止这些步骤。

  2. 如果用户代理或设备不支持注视点渲染,则中止这些步骤。

  3. 如果 fixed_foveation 小于 0,则将其设置为 0。

  4. 如果 fixed_foveation 大于 1,则将其设置为 1。

  5. 如果 binding 的context中没有纹理绑定到 target,则抛出 InvalidStateError 并中止这些步骤。

  6. 使用 binding 的context,采用与 fixedFoveation 相同的算法,将 fixed_foveation 应用于 target。

  7. 将通过 binding 的context绑定到 target 的纹理添加到foveatedTextures。

注:注视点渲染的效果将立即生效。

当一个 XRLayer 是 layers 数组的成员时,在一个XR 动画帧完成后,它必须立即呈现给沉浸式 XR 设备,但前提是自上一个XR 动画 帧以来至少发生了以下情况之一:

在将不透明帧缓冲区或 colorTexture 纹理呈现给沉浸式 XR 设备之前,用户代理必须确保所有渲染 操作都已刷新。

7. 视频层创建

7.1. XRMediaLayerInit

XRMediaLayerInit 字典表示一组可配置的值,用于描述包含视频的 XRCompositionLayer 如何 初始化。
dictionary XRMediaLayerInit {
  required XRSpace space;
  XRLayerLayout layout = "mono";
  boolean invertStereo = false;
};

space 属性定义与 用户物理环境的空间关系。

layout 属性定义视频在 XRCompositionLayer 中的布局。

invertStereo 属性定义视频中每个视图的自然 位置 是否应反转。

7.2. XRMediaQuadLayerInit

XRMediaQuadLayerInit 字典表示一组可配置值,用于描述包含视频的 XRQuadLayer 如何初始化。
dictionary XRMediaQuadLayerInit : XRMediaLayerInit {
  XRRigidTransform? transform;
  float? width;
  float? height;
};

7.3. XRMediaCylinderLayerInit

XRMediaCylinderLayerInit 字典表示一组可配置值,用于描述包含视频的 XRCylinderLayer 如何初始化。
dictionary XRMediaCylinderLayerInit : XRMediaLayerInit {
  XRRigidTransform? transform;
  float radius = 2.0;
  float centralAngle = 0.78539;
  float? aspectRatio;
};

7.4. XRMediaEquirectLayerInit

XRMediaEquirectLayerInit 字典表示一组可配置值,用于描述包含视频的 XREquirectLayer 如何初始化。
dictionary XRMediaEquirectLayerInit : XRMediaLayerInit {
  XRRigidTransform? transform;
  float radius = 0.0;
  float centralHorizontalAngle = 6.28318;
  float upperVerticalAngle = 1.570795;
  float lowerVerticalAngle = -1.570795;
};

7.5. XRMediaBinding

XRMediaBinding 对象用于创建显示 HTMLVideoElement 内容的层。
[Exposed=Window] interface XRMediaBinding {
  constructor(XRSession session);

  XRQuadLayer createQuadLayer(HTMLVideoElement video, optional XRMediaQuadLayerInit init = {});
  XRCylinderLayer createCylinderLayer(HTMLVideoElement video, optional XRMediaCylinderLayerInit init = {});
  XREquirectLayer createEquirectLayer(HTMLVideoElement video, optional XRMediaEquirectLayerInit init = {});
};

init 字典 不应是可选的。这是 bikeshed 议题 1566。

每个 XRMediaBinding 都有关联的 session,即 创建它时使用的 XRSession。

注: 可以创建多个 XRMediaBinding。 层的生命周期并不绑定到创建它的 XRMediaBinding 的生命周期。

每个通过 XRMediaBinding 创建的层都有一个内部 HTMLVideoElement media。 如果该层是会话的 renderState 的一部分,则它会显示视频的当前帧。该层会以 XR 设备或视频的原生帧率 进行更新,取两者中较低者。

注: 层中只会显示视频帧。视频控件应由作者实现,并且必须 绘制在另一个层中。

需要进一步说明 如何将视频 blit 到层中。

当带有 HTMLVideoElement media 的 XRCompositionLayer layer 需要渲染时,用户代理 必须运行以下步骤:
  1. 令 usability 为检查 media 的可用性的结果。

  2. 如果 usability 为 bad,则用透明 黑色填充 layer 并中止这些步骤。

  3. 使用 media 元素的内容填充 layer。

添加一个更好的算法来 描述绘制过程。

XRMediaBinding(XRSession session) 构造函数 在调用时必须执行以下步骤:

  1. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  2. 如果 session 不是沉浸式会话,则抛出 InvalidStateError 并中止这些步骤。

  3. 令 binding 为 session 的相关领域中的一个新 XRMediaBinding。

  4. 将 binding 的session 初始化为 session。

  5. 返回 binding。

要计算一个 HTMLVideoElement video 和一个 XRLayerLayout layout 的宽高比,运行以下步骤:
  1. 令 width 为 video 的 videoWidth。

  2. 令 height 为 video 的 videoHeight。

  3. 如果 layout 为 "stereo-left-right", 则将 width 除以 2。

  4. 如果 layout 为 "stereo-top-bottom", 则将 height 除以 2。

  5. 返回 width 除以 height 的结果。

createQuadLayer(HTMLVideoElement video, XRMediaQuadLayerInit init) 方法创建一个新的 XRQuadLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 init 的 layout 为 "default", 则抛出 TypeError 并中止这些步骤。

  5. 令 layer 为此对象的相关领域中的一个新 XRQuadLayer。

  6. 使用 session 在 layer 上运行初始化合成层。

  7. 将 layer 的media 初始化为 video。

  8. 将 layer 的 needsRedraw 初始化为 false。

  9. 令 aspectRatio 为使用 video 和 init 的 layout 计算 宽高比的结果。

  10. 如果 init 的 width 和 height 都为 undefined,则将 width 设置为 1。

  11. 如果 init 的 height 为 undefined,则将 height 设置为 width 除以 aspectRatio。

  12. 如果 init 的 width 为 undefined,则将 width 设置为 height 乘以 aspectRatio。

  13. 使用 layer 和 init 运行初始化四边形层。

  14. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  15. 返回 layer。

createCylinderLayer(HTMLVideoElement video, XRMediaCylinderLayerInit init) 方法创建一个新的 XRCylinderLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 init 的 layout 为 "default", 则抛出 TypeError 并中止这些步骤。

  5. 令 layer 为此对象的相关领域中的一个新 XRCylinderLayer。

  6. 使用 session 在 layer 上运行初始化合成层。

  7. 将 layer 的media 初始化为 video。

  8. 将 layer 的 needsRedraw 初始化为 false。

  9. 令 aspectRatio 为使用 video 和 init 的 layout 计算 宽高比的结果。

  10. 如果 init 的 aspectRatio 为 undefined,则将 aspectRatio 设置为 aspectRatio。

  11. 使用 layer 和 init 运行初始化圆柱层。

  12. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  13. 返回 layer。

createEquirectLayer(HTMLVideoElement video, XRMediaEquirectLayerInit init) 方法创建一个新的 XREquirectLayer layer。

调用此方法时,用户代理必须运行以下步骤:

  1. 令 session 为此对象的session。

  2. 如果 session 创建时未启用“layers”, 则抛出 NotSupportedError 并中止这些步骤。

  3. 如果 session 的 ended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 init 的 layout 为 "default", 则抛出 TypeError 并中止这些步骤。

  5. 如果 init 的 space 不是 XRReferenceSpace 类型的实例,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 init 的 space 的类型为 "viewer", 则抛出 InvalidStateError 并中止这些步骤。

  7. 令 layer 为此对象的相关领域中的一个新 XREquirectLayer。

  8. 使用 session 在 layer 上运行初始化合成层。

  9. 将 layer 的media 初始化为 video。

  10. 将 layer 的 needsRedraw 初始化为 false。

  11. 使用 layer 和 init 运行初始化等距柱状投影层。

  12. 如果 XR 合成器知道由于任何原因无法为 layer 创建资源,则抛出 OperationError 并中止这些步骤。

  13. 返回 layer。

定义 XREquirectLayer 的 参数如何影响视频显示。

8. 事件

8.1. XRLayerEvent

XRLayerEvent 会被触发,以指示 XRLayer 状态的变化。

[SecureContext, Exposed=Window] interface XRLayerEvent : Event {
  constructor(DOMString type, XRLayerEventInit eventInitDict);
  [SameObject] readonly attribute XRLayer layer;
};

dictionary XRLayerEventInit : EventInit {
  required XRLayer layer;
};

layer 属性指示生成该事件的 XRLayer。

8.2. 事件类型

用户代理必须提供以下新事件。事件的注册和触发必须遵循 DOM4 Events 的通常行为。

当层的底层资源丢失或 XR Compositor 无法再重投影该层时,用户代理可以在 XRLayer 对象上触发一个 redraw 事件。

作者应该在下一个 XR 动画 帧重新绘制该层的内容。该事件必须属于 XRLayerEvent 类型。

9. 层之间的深度排序

默认情况下,layers 数组定义层的合成顺序,并且每一层都绘制在前一层之上。 如果应用程序想要拥有按深度排序的层,则必须使用 "depth-sorted-layers" 特性 描述符请求会话。

如果 XRSession 是使用 "depth-sorted-layers" 特性 描述符创建的,则 XRProjectionLayer、 XRQuadLayer 和 XRCylinderLayer 层必须基于它们的深度来显示,而不是基于其在 layers 数组中的位置。 其他层类型必须继续像以前一样排序。

XRQuadLayer 和 XRCylinderLayer 层必须按其维度(例如 width 或 centralAngle)、 变换和空间进行排序。

XRProjectionLayer 层必须根据其 depthStencilTexture 中的值进行排序。 这也意味着,如果启用了 "depth-sorted-layers",则 XR Compositor 必须使用深度值,并且 ignoreDepthValues 和 usesDepthValues 必须被设置为 `true`。

10. 空间扭曲

空间扭曲是一种 改善 XR 合成器重投影的技术。 通过同时提交 motionVectorTexture 和 depthStencilTexture, XR 合成器可以执行高质量的帧外推和重投影, 从而允许用户代理以较低的帧率运行,同时仍为用户提供流畅的体验。 requestAnimationFrame() 回调的传递频率可能低于显示器的原生刷新率。XR 合成器将 使用体验提供的运动矢量和深度信息合成缺失的帧。

要启用空间扭曲,XRSession 必须使用“space-warp”特性 描述符创建。 如果启用了“space-warp”,则 XR 合成器必须 使用深度值,ignoreDepthValues 必须设置为 `false`,并且 usesDepthValues 必须设置为 `true`。

当启用 space-warp 特性 描述符时,体验应为其提交的每个 XRProjectionLayer 将具有代表性的深度值渲染到 depthStencilTexture 中。 depthStencilTexture 和 motionVectorTexture 将具有相同的尺寸,该尺寸可能不同于 colorTexture 的尺寸。 作者可以使用 depthStencilTextureWidth 和 depthStencilTextureHeight 来确定深度/模板附件和运动矢量附件二者的尺寸。 作者应在这些附件的完整范围内渲染深度/模板和运动矢量信息, 而不是渲染到 viewport。

注:由于深度/模板和运动矢量 附件的尺寸可能不同于颜色附件,因此它们并不打算附加到 用于渲染到 colorTexture 的帧缓冲区。 作者应按照各自附件的尺寸分别渲染深度/模板和运动矢量信息。

motionVectorTexture 必须采用 RGBA16F 格式。作者应使用该区域的二维屏幕空间运动矢量填充此纹理的 RG 分量, 该运动矢量表示为当前帧与上一帧之间归一化设备坐标(NDC)中的增量。 运动矢量计算为 `(currentClipPos / currentW) - (prevClipPos / prevW)`,其中 `currentClipPos` 和 `prevClipPos` 分别是片段在当前帧和上一帧中的裁剪空间位置。 红色通道对应 NDC X(水平方向)的增量,而绿色通道对应 NDC Y(垂直方向)的增量。蓝色通道可以包含 NDC Z(深度)的增量,而 alpha 通道 不使用。

如果在处理 XRFrame 期间未提交 motionVectorTexture 或 depthStencilTexture, 则 XR 合成器必须像未启用空间扭曲一样处理该 XRFrame

11. WebXR 设备 API 集成

11.1. XRRenderState 变更

此模块扩展了 XRRenderStateInit 和 XRRenderState 接口,新增一个可选的 layers 数组,其中包含 XRLayer
[SecureContext, Exposed=Window] partial interface XRRenderState {
  readonly attribute FrozenArray<XRLayer> layers;
};

layers 属性返回一个数组,其中包含 由 XR 合成器显示的 XRLayer 实例。

默认情况下,layers 数组定义各层的合成顺序。XR 合成器必须 按照每个层在数组中的位置顺序绘制它们,并使用 source-over 混合。除非启用了“depth-sorted-layers”特性 描述符,否则 XR 合成器不得对各层应用任何深度排序。

注:这意味着每个层都有可能 覆盖之前的层,无论之前的层在虚拟空间中是否更靠近观察者。

此模块替换了初始化渲染状态给出的步骤。相反,当为一个 XRSession session 创建一个 XRRenderState 对象 state 时,用户代理必须通过运行以下步骤来初始化渲染状态:
  1. 通过运行原始的初始化渲染状态步骤来初始化 state。

  2. 使用位于 session 的相关领域中的一个新空数组初始化 state 的 layers。

11.2. updateRenderState 变更

此模块替换了 WebXR 规范中“更新待处理的层状态”给出的步骤。相反,当用户代理要使用 XRSession session 和 XRRenderStateInit newState 更新待处理的层状态时,必须运行以下步骤:

  1. 如果 newState 的 baseLayer 和 newState 的 layers 都已设置,则抛出 NotSupportedError 并中止这些步骤。

  2. 令 activeState 为 session 的活动渲染状态。

  3. 如果设置了 newState 的 baseLayer:

    1. 如果 session 的待处理渲染状态为 null, 则将其设置为 activeState 的副本。

    2. 将 session 的待处理渲染状态的 layers 设置为 null。

  4. 如果设置了 newState 的 layers:

    1. 如果 newState 的 layers 包含一个其destroyed 布尔值为 true 的 XRCompositionLayer, 则抛出 InvalidStateError 并中止这些步骤。

    2. 如果 session 创建时未启用“layers”,且 newState 的 layers 包含多于 1 个实例,则抛出 NotSupportedError 并中止这些步骤。

    3. 如果 newState 的 layers 包含多于 maxRenderLayers 个条目,则抛出 NotSupportedError 并中止这些步骤。

    4. 如果 session 的待处理渲染状态为 null, 则将其设置为 activeState 的副本。

    5. 如果 newState 的 layers 包含重复实例,则抛出 TypeError 并中止这些步骤。

    6. 对于 newState 的 layers 中的每个 layer:

      1. 如果 layer 是 XRCompositionLayer 且 layer 的session 与 session 不同,则抛出 TypeError 并中止这些步骤。

      2. 如果 layer 是 XRWebGLLayer 且 layer 的session 与 session 不同,则抛出 TypeError 并中止这些步骤。

    7. 将 session 的待处理渲染状态的 baseLayer 设置为 null。

    8. 将 session 的待处理渲染状态的 layers 设置为 newState 的 layers。

11.3. XRCompositor 变更

必须扩展 XR 合成器,使 XRLayer layers 数组中的所有实例都能同时进行合成。 WebXR 的所有其他要求必须继续

如果 XR 合成器正在渲染到一个 视图,其 XREye 为 "none", 并且正在绘制一个不是 XRProjectionLayer 且其 layout 不为 "mono" 的 XRCompositionLayer, 则 XR 合成器必须像该视图 的 XREye 为 "left" 一样渲染该层。

注:这意味着该层中供右眼使用的一侧 会被忽略。这使作者能够为立体显示设备和 单目显示设备使用相同的资源。

11.4. XRView 变更

每个 视图必须定义一个 推荐 WebGL 颜色纹理分辨率,它 表示足以包含该视图的 WebGL 纹理 分辨率的最佳估计。

如果 XRSession 是使用“space-warp”特性 描述符创建的,则每个 视图必须定义一个推荐运动矢量纹理分辨率, 该分辨率基于推荐 WebGL 颜色纹理 分辨率。

每个 视图还必须 定义一个 推荐 WebGL 深度纹理分辨率, 它表示足以包含该视图的 WebGL 深度纹理 分辨率的最佳估计。 如果 XRSession 是使用“space-warp”特性 描述符创建的,则推荐 WebGL 深度纹理分辨率 必须等于推荐运动矢量纹理 分辨率。

如果启用了“depth-sorted-layers”特性描述符,则推荐 WebGL 深度纹理 分辨率必须等于推荐 WebGL 颜色纹理 分辨率。

11.5. 动画帧变更

此模块替换了 WebXR 规范中“检查层状态”给出的步骤。相反,要使用 renderState state 检查层 状态,用户代理必须运行以下步骤:
  1. 如果 state 的 baseLayer 不为 null,则返回 true。

  2. 对于 state 的 layers 中的每个 layer:

    1. 如果 layer 不是 XRCompositionLayer 或 layer 的destroyed 布尔值为 false,则返回 true。

  3. 返回 false。

11.6. XRSession 更改

此模块扩展了 XRSession 接口并向其中添加以下内容:
[SecureContext, Exposed=Window] partial interface XRSession {
  readonly attribute unsigned long maxRenderLayers;
};

maxRenderLayers 表示 合成器必须处理的最大层数,因此也是任何 XRRenderStateInit 的 layers 数组的最大大小。在给定时间内,应当能够创建超过此数量的层。

注:此指导并非旨在限制 用户代理可分配的层数量,如层的分配中所述。例如,用户代理可以允许创建 20 个层, 同时仅允许一次通过 updateRenderState() 设置 10 个。还值得注意的是,由于不同的层可能需要不同数量的后端处理能力或 对象,用户代理在设置 `maxRenderLayers` 值时具有一定的裁量权,以确保至少 可以渲染那么多层。但是,当传入更多层时,用户代理仍然需要拒绝,并且在向 updateRenderState 传入更少的层时不能拒绝。

每个 XRSession 都有一个内部 WeakSet bindings,其中保存 使用该会话创建的每个 XRWebGLBinding 的弱引用。

此模块向 WebXR 规范中的“关闭 会话”添加一个步骤。 将以下内容添加到列表中:

  1. 对于 session| 的bindings中的每个 binding:

    1. 对于 binding 的foveatedTextures中的每个 texture:

    2. 移除 texture 的注视点渲染。

12. 安全和隐私考量

12.1. 合成的时序

合成时序必须独立于所渲染的内容。 此外,一个层中的内容不得在其他层中被观察到。

如果可能,层的合成应该在浏览器之外进行,以降低时序攻击或 其他安全漏洞的风险。

12.2. 层的分配

用户代理可以限制任何资源分配,例如最大像素大小或 层数,以降低 GPU 硬件的可识别性。

变更

自 2020 年 12 月 3 日第一份公开工作 草案以来的变更

新特性:

变更:

一致性

文档 约定

一致性要求通过 描述性断言 与 RFC 2119 术语的组合来表达。 本文档规范性部分中的关键字 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY” 和 “OPTIONAL” 应按 RFC 2119 中的描述来解释。 但是,为提高可读性, 这些词在本规范中并不全都以大写字母出现。

本规范的所有文本均为规范性内容, 但明确标记为非规范性的章节、示例和注释除外。 [RFC2119]

本规范中的示例以 “for example” 等词引入,或通过 class="example" 与规范性文本分隔开, 如下所示:

这是一个资料性示例。

资料性注释以 “Note” 开头,并通过 class="note" 与规范性文本分隔开, 如下所示:

注,这是一个资料性注释。

一致性 算法

作为算法一部分以祈使语气表述的要求 (例如 "strip any leading space characters" 或 "return false and abort these steps") 应按引入该算法时所使用的关键字 ("must"、"should"、"may" 等) 的含义来解释。

以算法或具体步骤表述的一致性要求 可以以任何方式实现, 只要最终结果等价即可。 特别是,本规范中定义的算法 旨在易于理解, 并不旨在具有高性能。 鼓励实现者进行优化。

索引

由本 规范定义的术语

由引用定义的术语

参考文献

规范性参考文献

[COMPOSITING-1]
Chris Harrelson. 合成与混合级别 1. 2024年3月21日. CRD. URL: https://www.w3.org/TR/compositing-1/
[DOM]
Anne van Kesteren. DOM 标准. 现行标准. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 语言规范. URL: https://tc39.es/ecma262/multipage/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. 几何接口 模块级别 1. 2025年12月4日. CRD. URL: https://www.w3.org/TR/geometry-1/
[HTML]
Anne van Kesteren; et al. HTML 标准. 现行标准. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. 用于 RFC 中表示 要求级别的关键词. 1997年3月. 当前最佳实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBGL-2]
Kelsey Gilbert. WebGL 2.0 规范. URL: https://www.khronos.org/registry/webgl/specs/latest/2.0/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行 标准. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR 设备 API. 2026年6月9日. CRD. URL: https://www.w3.org/TR/webxr/
[WEBXR-AR-MODULE-1]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR 增强现实模块 - 级别 1. 2025年4月25日. CRD. URL: https://www.w3.org/TR/webxr-ar-module-1/

资料性参考文献

[PERMISSIONS-REQUEST]
Requesting Permissions. 社区组报告草案. URL: https://wicg.github.io/permissions-request/

IDL 索引

enum XRLayerLayout {
  "default",
  "mono",
  "stereo",
  "stereo-left-right",
  "stereo-top-bottom"
};

enum XRLayerQuality {
  "default",
  "text-optimized",
  "graphics-optimized"
};

[Exposed=Window] interface XRCompositionLayer : XRLayer {
  readonly attribute XRLayerLayout layout;

  attribute boolean blendTextureSourceAlpha;
  attribute boolean forceMonoPresentation;
  attribute float opacity;
  readonly attribute unsigned long mipLevels;
  attribute XRLayerQuality quality;

  readonly attribute boolean needsRedraw;

  undefined destroy();
};

[Exposed=Window] interface XRProjectionLayer : XRCompositionLayer {
  readonly attribute unsigned long textureWidth;
  readonly attribute unsigned long textureHeight;
  readonly attribute unsigned long textureArrayLength;

  readonly attribute boolean ignoreDepthValues;
  attribute float? fixedFoveation;
  attribute XRRigidTransform? deltaPose;
};

[Exposed=Window] interface XRQuadLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute XRRigidTransform transform;

  attribute float width;
  attribute float height;

  // Events
  attribute EventHandler onredraw;
};

[Exposed=Window] interface XRCylinderLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute XRRigidTransform transform;

  attribute float radius;
  attribute float centralAngle;
  attribute float aspectRatio;

  // Events
  attribute EventHandler onredraw;
};

[Exposed=Window] interface XREquirectLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute XRRigidTransform transform;

  attribute float radius;
  attribute float centralHorizontalAngle;
  attribute float upperVerticalAngle;
  attribute float lowerVerticalAngle;

  // Events
  attribute EventHandler onredraw;
};

[Exposed=Window] interface XRCubeLayer : XRCompositionLayer {
  attribute XRSpace space;
  attribute DOMPointReadOnly orientation;

  // Events
  attribute EventHandler onredraw;
};

[Exposed=Window] interface XRSubImage {
  [SameObject] readonly attribute XRViewport viewport;
};

[Exposed=Window] interface XRWebGLSubImage : XRSubImage {
  [SameObject] readonly attribute WebGLTexture colorTexture;
  [SameObject] readonly attribute WebGLTexture? depthStencilTexture;
  [SameObject] readonly attribute WebGLTexture? motionVectorTexture;

  readonly attribute unsigned long? imageIndex;
  readonly attribute unsigned long colorTextureWidth;
  readonly attribute unsigned long colorTextureHeight;
  readonly attribute unsigned long? depthStencilTextureWidth;
  readonly attribute unsigned long? depthStencilTextureHeight;
};

enum XRTextureType {
  "texture",
  "texture-array"
};

dictionary XRProjectionLayerInit {
  XRTextureType textureType = "texture";
  GLenum colorFormat = 0x1908; // RGBA
  GLenum depthFormat = 0x1902; // DEPTH_COMPONENT
  double scaleFactor = 1.0;
  boolean clearOnAccess = true;
};

dictionary XRLayerInit {
  required XRSpace space;
  XRTextureType textureType = "texture";
  GLenum colorFormat = 0x1908; // RGBA
  GLenum? depthFormat;
  unsigned long mipLevels = 1;
  required unsigned long viewPixelWidth;
  required unsigned long viewPixelHeight;
  XRLayerLayout layout = "mono";
  boolean isStatic = false;
  boolean clearOnAccess = true;
};

dictionary XRQuadLayerInit : XRLayerInit {
  XRRigidTransform? transform;
  float width = 1.0;
  float height = 1.0;
};

dictionary XRCylinderLayerInit : XRLayerInit {
  XRRigidTransform? transform;
  float radius = 2.0;
  float centralAngle = 0.78539;
  float aspectRatio = 2.0;
};

dictionary XREquirectLayerInit : XRLayerInit {
  XRRigidTransform? transform;
  float radius = 0;
  float centralHorizontalAngle = 6.28318;
  float upperVerticalAngle = 1.570795;
  float lowerVerticalAngle = -1.570795;
};

dictionary XRCubeLayerInit : XRLayerInit {
  DOMPointReadOnly? orientation;
};

[Exposed=Window] interface XRWebGLBinding {
  constructor(XRSession session, XRWebGLRenderingContext context);

  readonly attribute double nativeProjectionScaleFactor;
  readonly attribute boolean usesDepthValues;

  XRProjectionLayer createProjectionLayer(optional XRProjectionLayerInit init = {});
  XRQuadLayer createQuadLayer(optional XRQuadLayerInit init = {});
  XRCylinderLayer createCylinderLayer(optional XRCylinderLayerInit init = {});
  XREquirectLayer createEquirectLayer(optional XREquirectLayerInit init = {});
  XRCubeLayer createCubeLayer(optional XRCubeLayerInit init = {});

  XRWebGLSubImage getSubImage(XRCompositionLayer layer, XRFrame frame, optional XREye eye = "none");
  XRWebGLSubImage getViewSubImage(XRProjectionLayer layer, XRView view);

  undefined foveateBoundTexture(GLenum target, float fixed_foveation);
};

dictionary XRMediaLayerInit {
  required XRSpace space;
  XRLayerLayout layout = "mono";
  boolean invertStereo = false;
};

dictionary XRMediaQuadLayerInit : XRMediaLayerInit {
  XRRigidTransform? transform;
  float? width;
  float? height;
};

dictionary XRMediaCylinderLayerInit : XRMediaLayerInit {
  XRRigidTransform? transform;
  float radius = 2.0;
  float centralAngle = 0.78539;
  float? aspectRatio;
};

dictionary XRMediaEquirectLayerInit : XRMediaLayerInit {
  XRRigidTransform? transform;
  float radius = 0.0;
  float centralHorizontalAngle = 6.28318;
  float upperVerticalAngle = 1.570795;
  float lowerVerticalAngle = -1.570795;
};

[Exposed=Window] interface XRMediaBinding {
  constructor(XRSession session);

  XRQuadLayer createQuadLayer(HTMLVideoElement video, optional XRMediaQuadLayerInit init = {});
  XRCylinderLayer createCylinderLayer(HTMLVideoElement video, optional XRMediaCylinderLayerInit init = {});
  XREquirectLayer createEquirectLayer(HTMLVideoElement video, optional XRMediaEquirectLayerInit init = {});
};

[SecureContext, Exposed=Window] interface XRLayerEvent : Event {
  constructor(DOMString type, XRLayerEventInit eventInitDict);
  [SameObject] readonly attribute XRLayer layer;
};

dictionary XRLayerEventInit : EventInit {
  required XRLayer layer;
};

[SecureContext, Exposed=Window] partial interface XRRenderState {
  readonly attribute FrozenArray<XRLayer> layers;
};

[SecureContext, Exposed=Window] partial interface XRSession {
  readonly attribute unsigned long maxRenderLayers;
};

议题索引

本节需要澄清 ↵
本节需要澄清 ↵
init 字典不应是可选的。这是 bikeshed 议题 1566。 ↵
如果尺寸导致布局变化,则需要特殊处理 UA 行为(即,如果请求的宽度 超过 "stereo-left-right" 的限制) ↵
需要为辅助视图重新计算 scaleFactor。 ↵
定义立方体贴图尺寸如何确定。 ↵
应如何处理 space。能否走到立方体贴图的边缘? ↵
确定 orientation 的初始状态。 ↵
init 字典不应是可选的。这是 bikeshed 议题 1566。 ↵
需要进一步说明如何将视频 blit 到层中。 ↵
添加一个更好的算法来描述绘制。 ↵
定义 XREquirectLayer 的参数 如何影响视频显示。 ↵