你可以先參考幾項基本知識,準備一套身歷其境的觀影體驗:虛擬實境、擴增實境等。
Chrome 79 版現已推出沉浸式網頁體驗。WebXR Device API 提供虛擬實境帶來了虛擬實境,但 Chrome 第 81 版則支援擴增實境。更新 GamePad API 時,系統會將控制項進一步應用在 VR 中。其他瀏覽器很快就會支援這些規格,包括 Firefox Reality、Oculus Browser、Edge 和 Magic Leap 的 Helio 瀏覽器等等。
本文將介紹一系列沉浸式網路體驗。本期內容涵蓋設定基本的 WebXR 應用程式,以及進入和離開 XR 工作階段。後續文章將介紹影格迴圈 (WebXR 體驗的工作馬)、擴增實境的具體細節,以及 WebXR Hit Test API (也就是在 AR 工作階段中偵測途徑的意義)。除非另有說明,否則我介紹的一切內容和成功文章都同樣適用於 AR 和 VR。
什麼是沉浸式網路?
雖然我們會使用兩個字詞來描述沉浸式體驗 (擴增實境和虛擬實境),但許多人認為這些體驗是以完全真實到完全虛擬的方式,兩者之間具有一定程度的沉浸感。XR 中的「X」旨在反映這樣的思維,也就是是一種代數變數,適用於沉浸式體驗中各種情境。
沉浸式體驗的例子包括:
- 遊戲
- 360 度影片
- 在沉浸式環境中播放的傳統 2D (或 3D) 影片
- 購屋
- 先查看住家中的產品再購買
- 沉浸式藝術
- 眾所期盼的酷炫功能
概念和用法
我們會說明使用 WebXR Device API 的幾個基本概念。如果您需要比我提供的深入資訊,請參閱 Immersive Web Working Group 的 WebXR 範例或 MDN 不斷增加的參考資源。如果您熟悉早期版本的 WebXR Device API,應該看所有相關內容。所做的變更。
本文中的程式碼是以 Immersive Web Working Group 的基本範例 (示範和來源) 為基礎,但為了簡單明瞭而編輯。
建立 WebXR 規格的一環,就是要深入瞭解用來保護使用者的安全性和隱私權措施。因此,實作方式必須遵循特定要求。網頁或應用程式必須處於啟用狀態且焦點,才能向檢視者要求任何敏感內容。網頁或應用程式必須透過 HTTPS 提供。API 本身旨在保護從感應器和相機取得的資訊,以利運作。
要求課程
進入 XR 工作階段需要使用者手勢。如要執行此操作,請使用功能偵測以測試 XRSystem
(透過 navigator.xr
) 並呼叫 XRSystem.isSessionSupported()
。請注意,在 Chrome 79 和 80 版中,XRSystem
物件稱為 XR
。
在以下範例中,我表示想使用 'immersive-vr'
工作階段類型的虛擬實境工作階段。其他工作階段類型為 'immersive-ar'
和 'inline'
。內嵌工作階段是用來在 HTML 中顯示內容,主要用於前導內容。Immersive AR 工作階段範例示範了這一點。我們會在後續文章中說明。
知道系統支援虛擬實境工作階段後,就能啟用可以取得使用者手勢的按鈕。
if (navigator.xr) {
const supported = await navigator.xr.isSessionSupported('immersive-vr');
if (supported) {
xrButton.addEventListener('click', onButtonClicked);
xrButton.textContent = 'Enter VR';
xrButton.enabled = supported; // supported is Boolean
}
}
啟用按鈕後,我會等待點擊事件,然後要求工作階段。
let xrSession = null;
function onButtonClicked() {
if (!xrSession) {
navigator.xr.requestSession('immersive-vr')
.then((session) => {
xrSession = session;
xrButton.textContent = 'Exit XR';
onSessionStarted(xrSession);
});
} else {
xrSession.end();
}
}
請注意此程式碼中的物件階層。會從 navigator
移至 xr
至 XRSession
執行個體。在早期的 API 版本中,指令碼必須先要求裝置,才能要求工作階段。現在,系統會以隱含方式取得裝置。
進入工作階段
進入課程後,我需要啟動並進入課程。但首先,我需要設定一些項目工作階段需要 onend
事件處理常式,才能在使用者離開時重設應用程式或網頁。
我還需要 <canvas>
元素才能繪製場景。且必須是與 XR 相容的 WebGLRenderingContext 或 WebGL2RenderingContext。所有繪圖都是使用這些工具或 WebGL 式架構 (例如 Three.js) 完成的。
我現在已有繪圖的地方,還需要來源可以繪製它。然後建立 XRWebGLLayer
的執行個體。做法是呼叫 XRSession.updateRenderState()
將其與畫佈建立關聯。
開始練習後,我需要一種方法判斷虛擬實境內容在哪裡。我需要參考空間。'local-floor'
參考空間是指起點位於檢視器附近,Y 軸位於樓層的 0 軸,因此應該不會移動。有其他類型的參照空間,但這個主題比在這裡更為複雜。將參考空間儲存到變數,因為我在在螢幕上繪圖時需要用到。
function onSessionStarted(xrSession) {
xrSession.addEventListener('end', onSessionEnded);
let canvas = document.createElement('canvas');
webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
});
xrSession.requestReferenceSpace('local-floor')
.then((refSpace) => {
xrRefSpace = refSpace;
xrSession.requestAnimationFrame(onXRFrame);
});
}
取得參考空間後,我呼叫了 XRSession.requestAnimationFrame()
。這是顯示虛擬內容開始時,會在影格迴圈中完成。
執行影格迴圈
影格迴圈是由使用者代理程式控制的無限迴圈,會重複繪製內容到螢幕上。內容是由稱為「影格」的獨立區塊繪製。連續影格呈現會營造出動作的幻覺,如果是 VR 應用程式,每秒影格數可能在 60 到 144 之間。Android 版的 AR 執行速度為每秒 30 個影格。您的程式碼不應假設任何特定影格速率。
影格迴圈的基本程序如下:
- 呼叫
XRSession.requestAnimationFrame()
。做為回應,使用者代理程式會叫用由您定義的XRFrameRequestCallback
。 - 在回呼函式中:
- 再次呼叫
XRSession.requestAnimationFrame()
。 - 請擺好觀眾姿勢。
- 將
WebGLFramebuffer
從XRWebGLLayer
傳遞 (「繫結」) 至WebGLRenderingContext
。 - 對每個
XRView
物件進行疊代,從XRWebGLLayer
擷取其XRViewport
,並傳遞至WebGLRenderingContext
。 - 然後繪製內容到 framebuffer。
- 再次呼叫
本文的其餘部分將說明步驟 1 和步驟 2 的部分:設定及呼叫 XRFrameRequestCallback
。步驟 2 的其餘項目將在第二部分說明
XRFrameRequestCallback
XRFrameRequestCallback
是由您定義。該事件會採用兩個參數:DOMHighResTimeStamp
和 XRFrame
例項。XRFrame
物件會提供轉譯單一影格所需的資訊。DOMHighResTimeStamp
引數會供日後使用。
我要先要求下一個動畫影格,再執行其他操作。如前文所述,影格時間是由使用者代理程式根據基礎硬體決定。先要求下一個影格,可確保如果回呼期間發生錯誤,影格迴圈就能持續。
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
// Render a frame.
}
到時候,就可以開始為觀眾繪製一些東西了。以上是 II 的討論重點在開始之前,讓我示範如何結束練習。
結束工作階段
沉浸式工作階段可能會因許多原因而結束,包括透過呼叫 XRSession.end()
讓自己的程式碼結束。其他原因包括耳機連線中斷,或是其他可控制該裝置的應用程式。因此,運作良好的應用程式應監控 end
事件。發生這種情況時,請捨棄工作階段及其相關的轉譯物件。已結束的沉浸式工作階段無法恢復。如要重新進入沉浸式體驗,應用程式需要啟動新的工作階段。
回顧「輸入工作階段」,我在設定期間新增了 onend
事件處理常式。
function onSessionStarted(xrSession) {
xrSession.addEventListener('end', onSessionEnded);
// More setup…
}
在事件處理常式內,在使用者進入工作階段前還原應用程式狀態。
function onSessionEnded(event) {
xrSession = null;
xrButton.textContent = 'Enter VR';
}
結論
我沒告訴你撰寫 Web XR 或 AR 應用程式所需的一切。 希望您有足夠的時間可以自行瞭解程式碼,並且足以開始實驗。在下一篇文章中,我將說明影格迴圈,也就是內容繪製到畫面上的位置。
JESHOOTS.COM 在 Unsplash 上提供的相片