WebGLRenderingContext: makeXRCompatible() 方法

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

如果您有一个应用程序,它可以从标准 2D 显示器上开始呈现,然后过渡到 3D 沉浸式系统,则此方法很有用。

语法

js
makeXRCompatible()

参数

无。

返回值

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

异常

此方法不会抛出传统的异常;相反,该 promise 会拒绝,并将以下错误之一作为值传递到拒绝处理程序

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;

window.addEventListener("load", (event) => {
  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 设备 API
# dom-webglrenderingcontextbase-makexrcompatible

浏览器兼容性

BCD 表格仅在启用了 JavaScript 的浏览器中加载。