WebGLRenderingContext: makeXRCompatible() 方法

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

注意:此功能在 Web Workers 中可用。

WebGLRenderingContext 方法 makeXRCompatible() 确保 WebGLRenderingContext 所描述的渲染上下文已准备好为它将要显示的沉浸式 WebXR 设备渲染场景。如有必要,WebGL 层可能会重新配置上下文,使其准备好为与原始设备不同的设备进行渲染。

这对于您希望最初在标准 2D 显示器上呈现,然后可以过渡到 3D 沉浸式系统的应用程序非常有用。

语法

js
makeXRCompatible()

参数

无。

返回值

一个 Promise,一旦 WebGL 上下文准备好用于渲染 WebXR 内容,就会成功解析。

异常

此方法不会抛出传统异常;相反,Promise 会以以下一个错误值作为参数传递给 rejection handler 来拒绝:

AbortError DOMException

如果将上下文切换到 WebXR 兼容上下文失败,则返回此错误。

InvalidStateError DOMException

如果 WebGL 上下文丢失或没有可用的 WebXR 设备,则返回此错误。

用法说明

由于 makeXRCompatible() 可能涉及用一个使用新渲染硬件的新上下文替换底层 WebGL 上下文,因此上下文的现有内容可能会丢失,因此需要重新渲染。这就是为什么使用 webglcontextlostwebglcontextrestored 事件的原因:第一个让您有机会丢弃不再需要的任何内容,而第二个让您有机会加载资源并为在新上下文中渲染场景做好准备。

虽然此方法可通过 WebGLRenderingContext 接口访问,但它实际上是由 WebXR 设备 API 定义的,而不是由 WebGL 定义的。

示例

此示例演示了您可能会在游戏中找到的代码逻辑,该游戏使用 WebGL 来显示菜单和其他 UI,并使用 WebGL 来渲染游戏玩法,但在其主菜单上有一个按钮,提供了在 WebXR 模式下启动游戏的选项。

HTML

按钮的 HTML 如下所示:

html
<button class="green button" type="button">Start Game</button>
<button class="blue button use-webxr" type="button">
  Start Game (VR mode)
</button>

第一个按钮启动游戏,继续像往常一样在屏幕上显示游戏。第二个按钮将用于以 immersive-vr 模式启动游戏。请注意,VR 模式按钮上包含 use-webxr 类。这很重要,我们稍后会进行探讨。

JavaScript

处理图形启动、切换到 VR 模式等代码如下所示:

js
const outputCanvas = document.querySelector(".output-canvas");
const gl = outputCanvas.getContext("webgl");
let xrSession = null;
let usingXR = false;
let currentScene = "scene1";
let glStartButton;
let xrStartButton;

loadSceneResources(currentScene);

glStartButton.addEventListener("click", handleStartButtonClick);
xrStartButton.addEventListener("click", handleStartButtonClick);

outputCanvas.addEventListener("webglcontextlost", (event) => {
  /* The context has been lost but can be restored */
  event.canceled = true;
});

/* When the GL context is reconnected, reload the resources for the
   current scene. */
outputCanvas.addEventListener("webglcontextrestored", (event) => {
  loadSceneResources(currentScene);
});

async function onStartedXRSession(xrSession) {
  try {
    await gl.makeXRCompatible();
  } catch (err) {
    switch (err) {
      case AbortError:
        showSimpleMessageBox(
          "Unable to transfer the game to your XR headset.",
          "Cancel",
        );
        break;
      case InvalidStateError:
        showSimpleMessageBox(
          "You don't appear to have a compatible XR headset available.",
          "Cancel",
        );
        break;
      default:
        handleFatalError(err);
        break;
    }
    xrSession.end();
  }
}

async function handleStartButtonClick(event) {
  if (event.target.classList.contains("use-webxr") && navigator.xr) {
    try {
      xrSession = await navigator.xr.requestSession("immersive-vr");
      usingXR = true;
    } catch (err) {
      xrSession = NULL;
      usingXR = false;
    }
  }
  startGame();
}

function startGame() {
  currentScene = "scene1";
  loadSceneResources(currentScene);

  /* and so on */
}

这是通过两个按钮实现的:一个按钮正常启动游戏,另一个按钮以 VR 模式启动游戏。这两个按钮都使用 handleStartButtonClick() 函数作为它们的事件处理程序。该函数通过检查按钮是否具有 use-webxr 类来确定用户点击的是请求 immersive-vr 模式的按钮。如果用户点击的按钮具有该类(并且我们已通过确保 navigator.xr 属性存在来确认 WebXR 可用),我们则使用 requestSession() 请求一个新的 WebXR 会话并将 usingXR 标志设置为 true

如果点击了另一个按钮,我们确保 xrSessionNULL 并将 usingXR 清除为 false

然后调用 startGame() 函数来触发游戏玩法开始。

webglcontextlostwebglcontextrestored 提供了处理程序;在第一种情况下,我们确保我们知道状态可以恢复,而在后一种情况下,我们实际上会重新加载场景以确保我们拥有当前屏幕或头戴设备配置的正确资源。

规范

规范
WebXR Device API
# dom-webglrenderingcontextbase-makexrcompatible

浏览器兼容性