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

瀏覽器相容性