歡迎使用沉浸式網路體驗

身歷其境的網路是指透過瀏覽器代管的虛擬世界體驗。無論在瀏覽器或支援 VR 的頭戴式裝置上,都能享有這項體驗完整的虛擬實境體驗。

Joe Medley
Joe Medley

沉浸式網路是指透過瀏覽器代管的虛擬世界體驗。這項體驗涵蓋瀏覽器或支援 VR 功能的頭戴式裝置所呈現的完整虛擬實境 (VR) 體驗,例如 Google 的 Daydream、Oculus Rift、Samsung Gear VR、HTC Vive 和 Windows 混合實境頭戴式裝置,以及針對支援 AR 的行動裝置所開發的擴增實境體驗。

雖然我們使用兩個字詞來描述沉浸式體驗,但應視為從完全現實到完全沉浸式 VR 環境的一流體驗,且兩者之間具有不同等級的 AR。

沉浸式體驗的例子包括:

  • 沉浸式 360 度影片
  • 在沉浸式環境中播放的傳統 2D (或 3D) 影片
  • 資料示意圖
  • 居家購物
  • 藝術
  • 眾所期盼的酷炫功能

該怎麼到那裡?

沉浸式網路環境已有將近一年的時間,如今已採用創新形式。 這是透過 WebVR 1.1 API 完成的。自 Chrome 62 起,該 API 已在來源試用中提供。Firefox 和 Edge 也支援這個 API,以及 Safari 的 polyfill。

該繼續努力了。

來源試用已於 2018 年 7 月 24 日結束,規格已由 WebXR Device API 和新的來源試用取代。

WebVR 1.1 怎麼了?

我們從 WebVR 1.1 學到了許多,但逐漸瞭解到,必須進行一些重大變更,才能支援想建構的應用程式開發人員類型。所學課程的完整清單內容太長,不在此限,但包括 API 明確與主要 JavaScript 執行緒連結、開發人員有太多機會設定明顯錯誤的設定,以及常見的用途 (例如魔術視窗造成的副作用而非刻意的功能)。(魔術視窗是一項一項技術,可用來查看沉浸式內容,而無需頭戴式耳機即可根據裝置的螢幕方向感應器轉譯單一檢視畫面)。

新的設計有助於簡化實作程序,並大幅改善效能。同時,AR 和其他用途也持續增加,因此 API 必須進一步擴充,以便在未來支援這些功能。

WebXR Device API 設計和命名這些延伸用途已有基礎,提供更好的發展路徑。WebVR 的實作者已承諾遷移至 WebXR Device API。

什麼是 WebXR Device API?

如同之前的 WebVR 規格,WebXR Device API 是 Immersive Web Community Group 的產品,這個群組是由 Google、Microsoft、Mozilla 等 的貢獻者所組成。XR 中的「X」就像是某一種代數變數,適用於各種沉浸式體驗。這項功能在先前提及的來源試用,以及透過 polyfill 中取得。

本文最初是在 Chrome 67 Beta 版發布期間發布,因此只有 VR 功能會啟用。Chrome 69 版已推出擴增實境技術。詳情請參閱網頁的擴增實境技術

這篇新 API 的功能還有更多內容,詳情請參閱以下文章。我想讓您有足夠的時間瞭解 WebXR 範例。詳情請參閱原始說明Immersive Web Early Adopters 指南。隨著來源試用的進展,我會擴充後者您可以隨時解決問題或提交提取要求。

在本文中,我將探討如何啟動、停止和執行 XR 工作階段,以及處理輸入的幾項基本概念。

我不會談到如何在螢幕上繪製 AR/VR 內容。WebXR Device API 不提供圖片轉譯功能。由你決定。 繪圖作業需使用 WebGL API 來進行。如果真的很遠,就可以這麼做。不過,我們建議使用架構沉浸式網路範例使用專為名為 Cottontail 的示範建立而成。從 5 月開始,Three.js 就開始支援 WebXR,我完全聽說過 A-Frame。

啟動並執行應用程式

基本流程如下:

  1. 要求 XR 裝置。
  2. 如果可以,請申請 XR 工作階段。如果您希望使用者將手機放入頭戴式裝置中,這稱為沉浸式工作階段,並且需要使用者用手勢進入。
  3. 請使用工作階段執行轉譯迴圈,以每秒提供 60 個圖片影格。在每個頁框中在螢幕上繪製適當內容。
  4. 執行算繪迴圈,直到使用者決定結束為止。
  5. 結束 XR 工作階段。

讓我們更深入地瞭解這個部分,並加入一些程式碼。您無法透過我正在顯示的資訊執行應用程式。但這只是為了讓你瞭解

要求 XR 裝置

您可以在這裡辨識標準功能偵測程式碼。您可以將此包裝在名為 checkForXR() 的函式中。

如果您不使用沉浸式工作階段,則可略過廣告功能,取得使用者手勢並直接要求工作階段。沉浸式工作階段需要使用頭戴式耳機。非沉浸式工作階段只會在裝置螢幕上顯示內容。大多數人提到虛擬實境或擴增實境時,都會想到前者。後者有時也稱為「魔術視窗」。

if (navigator.xr) {
    navigator.xr.requestDevice()
    .then(xrDevice => {
    // Advertise the AR/VR functionality to get a user gesture.
    })
    .catch(err => {
    if (err.name === 'NotFoundError') {
        // No XRDevices available.
        console.error('No XR devices available:', err);
    } else {
        // An error occurred while requesting an XRDevice.
        console.error('Requesting XR device failed:', err);
    }
    })
} else{
    console.log("This browser does not support the WebXR API.");
}

要求 XR 工作階段

我們現在已取得裝置和使用者手勢,接下來是準備一個工作階段了。 如要建立工作階段,瀏覽器需要用畫布繪圖。

xrPresentationContext = htmlCanvasElement.getContext('xrpresent');
let sessionOptions = {
    // The immersive option is optional for non-immersive sessions; the value
    //   defaults to false.
    immersive: false,
    outputContext: xrPresentationContext
}
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Use a WebGL context as a base layer.
    xrSession.baseLayer = new XRWebGLLayer(session, gl);
    // Start the render loop
})

執行算繪迴圈

這個步驟的程式碼有點驚喜。為瞭解答這個疑問 我會丟一些字如果您想先看看最終程式碼,請提前查看,再回來查看完整的說明。您可能無法推論出很多事情。

轉譯迴圈的基本程序如下:

  1. 要求動畫影格。
  2. 查詢裝置位置。
  3. 根據裝置位置將內容繪製在裝置的位置。
  4. 執行輸入裝置的必要工作。
  5. 每秒重複 60 次,直到使用者決定結束為止。

要求顯示畫面

在 Web XR 環境中,「frame」這個字有多種意義。其一是「參考框架」,定義座標系統起點的計算位置,以及裝置移動時對該起點的影響。(檢視畫面是否在使用者移動或實際轉換時保持不變?)

第二種影格是呈現影格,以 XRFrame 物件表示。這個物件包含將 AR/VR 場景單一影格轉譯至裝置所需的資訊。這可能會令人感到困惑,因為呼叫 requestAnimationFrame() 即可擷取簡報影格。這個物件與 window.requestAnimationFrame() 相容。

在向你說明之前,我們會提供一些代碼。以下範例說明如何啟動及維護算繪迴圈。請注意字詞框架的雙重用法。請留意對 requestAnimationFrame() 的週期性呼叫。這個函式每秒會呼叫 60 次。

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    // Process the frame.
    xrFrame.session.requestAnimationFrame(onFrame);
    }
});

姿勢

在畫面上繪製任何內容前,您必須先知道顯示裝置指向的位置,而且需要存取螢幕。一般來說,AR/VR 物體的位置和方向都稱為姿勢。檢視器和輸入裝置都有姿勢。(稍後會介紹輸入裝置)。檢視器和輸入裝置姿勢都會定義為 4 x 4 矩陣,以資料欄主要順序儲存在 Float32Array 中。針對目前的動畫影格物件呼叫 XRFrame.getDevicePose(),即可取得檢視器姿勢。務必進行測試,看看自己是否做出姿勢。如果有發生錯誤,您不想繪製到螢幕上

let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
    // Draw something to the screen.
}

View

確認姿勢後,接下來要開始畫一些東西。您繪製的物件稱為檢視畫面 (XRView),這正是工作階段類型的重要性。系統會以陣列的形式,從 XRFrame 物件擷取檢視畫面。假如您在非沉浸式工作階段中,陣列只會有 1 個檢視區塊。如果處於沉浸式工作階段中,陣列有兩個,並分別代表兩眼。

for (let view of xrFrame.views) {
    // Draw something to the screen.
}

這是 WebXR 與其他沉浸式系統的重要差異。 雖然疊代一個檢視畫面可能毫無意義,但這樣做可讓您為各種裝置建立單一轉譯路徑。

整個轉譯迴圈

如果我全部準備好,我會收到以下程式碼。我留下了輸入裝置的預留位置,我們稍後會再說明。

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    let pose = xrFrame.getDevicePose(xrFrameOfRef);
    if (pose) {
        for (let view of xrFrame.views) {
        // Draw something to the screen.
        }
    }
    // Input device code will go here.
    frame.session.requestAnimationFrame(onFrame);
    }
}

結束 XR 工作階段

XR 工作階段可能會因為許多原因而結束,包括透過呼叫 XRSession.end() 以您自己的程式碼結束。其他原因包括耳機連線中斷,或是其他可控制該裝置的應用程式。這就是為什麼運作良好的應用程式應監控結束事件,並在事件發生時捨棄工作階段和轉譯器物件。XR 工作階段一旦結束就無法恢復。

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('end', onSessionEnd);
});

// Restore the page to normal after immersive access has been released.
function onSessionEnd() {
    xrSession = null;

    // Ending the session stops executing callbacks passed to the XRSession's
    // requestAnimationFrame(). To continue rendering, use the window's
    // requestAnimationFrame() function.
    window.requestAnimationFrame(onDrawFrame);
}

互動如何運作?

如同應用程式生命週期,我先簡單說明 如何在 AR 或 VR 中與物件互動。

WebXR Device API 採用「點及點選」法令使用者輸入輸入內容。使用這個方法時,每個輸入來源都會有定義的「指標光」,用來指出輸入裝置指向的位置,以及指出內容已選取時間的事件。應用程式會繪製指標光線,並顯示其指向的位置。使用者按一下輸入裝置時,就會觸發事件,具體而言就是 selectselectStartselectEnd。您的應用程式會判斷使用者點選了哪些內容,並適當做出回應。

輸入裝置和指標匣

對使用者而言,指標灰色只是控制器與其指向目標之間的模糊線條。但您的應用程式必須繪圖。這表示必須取得輸入裝置的姿勢,並從位置繪製一條線到 AR/VR 空間中的物件。這項程序大致如下:

let inputSources = xrSession.getInputSources();
for (let xrInputSource of inputSources) {
    let inputPose = frame.getInputPose(inputSource, xrFrameOfRef);
    if (!inputPose) {
    continue;
    }
    if (inputPose.gripMatrix) {
    // Render a virtual version of the input device
    //   at the correct position and orientation.
    }
    if (inputPose.pointerMatrix) {
    // Draw a ray from the gripMatrix to the pointerMatrix.
    }
}

這是沉浸式網路社群群組輸入追蹤範例的精簡版本。與影格轉譯一樣,您可以自由繪製指標遊標,而裝置則可由您決定。如前文所述,此程式碼必須做為轉譯迴圈的一部分執行。

選取虛擬空間中的項目

而只是 AR/VR 上的物體根本實在不好用。要做到任何實用的動作 使用者必須能選取項目WebXR Device API 提供三個用於回應使用者互動的事件:selectselectStartselectEnd。它們有我原本預期的不到:他們只說有人點選了輸入裝置。但不會指出使用者點選了環境中的哪個項目。事件處理常式會新增至 XRSession 物件,並應盡快新增。

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('selectstart', onSelectStart);
    xrSession.addEventListener('selectend', onSelectEnd);
    xrSession.addEventListener('select', onSelect);
});

這個程式碼是以輸入選擇範例為基礎,以便您掌握更多背景資訊。

為判斷你點選了某個姿勢。(例如,我沒想到...)您應用程式或其任何架構的特定細節,因此這不在本文的討論範圍內。Cottontail 的做法 就在「輸入選擇」範例中

function onSelect(ev) {
    let inputPose = ev.frame.getInputPose(ev.inputSource, xrFrameOfRef);
    if (!inputPose) {
    return;
    }
    if (inputPose.pointerMatrix) {
    // Figure out what was clicked and respond.
    }
}

結論:展望未來

我稍早提到,Chrome 69 預計會推出擴增實境技術 (2018 年 6 月的初期測試版本)。儘管如此,我還是鼓勵您試試我們目前推出的功能。我們需要您的寶貴意見才能加以改善。追蹤 ChromeStatus.com 的 WebXR Hit Test,即可追蹤進度。您也可以依循 WebXR 錨點,改善姿勢追蹤。