Thực tế ảo xuất hiện trên web

Một số kiến thức cơ bản để chuẩn bị cho bạn trải nghiệm sống động: thực tế ảo, thực tế tăng cường và mọi thứ ở giữa.

Joe Medley
Joe Medley

Chrome 79 đã mang trải nghiệm sống động đến với web. WebXR Device API mang đến tính năng thực tế ảo, trong khi tính năng hỗ trợ thực tế tăng cường sẽ có trong Chrome 81. Trong khi bản cập nhật cho API Tay điều khiển trò chơi mở rộng việc sử dụng các chế độ điều khiển nâng cao cho VR. Các trình duyệt khác sẽ sớm hỗ trợ các thông số kỹ thuật này, bao gồm Firefox Reality, Oculus Browser, Edge và trình duyệt Helio của Magic Leap, v.v.

Bài viết này mở đầu cho một loạt bài viết về web sống động. Phần này trình bày cách thiết lập một ứng dụng WebXR cơ bản cũng như cách vào và thoát khỏi phiên XR. Các bài viết sau sẽ đề cập đến vòng lặp khung (công cụ chính của trải nghiệm WebXR), thông tin chi tiết về thực tế tăng cường và API kiểm thử lượt nhấn WebXR, một phương thức phát hiện bề mặt trong phiên AR. Trừ khi có quy định khác, mọi nội dung tôi đề cập trong bài viết này và các bài viết tiếp theo đều áp dụng như nhau cho cả AR và VR.

Web sống động là gì?

Mặc dù chúng ta sử dụng hai thuật ngữ để mô tả trải nghiệm sống động – thực tế tăng cường và thực tế ảo – nhưng nhiều người coi chúng là một phổ từ thực tế hoàn toàn đến ảo hoàn toàn, với mức độ sống động ở giữa. Chữ "X" trong XR nhằm phản ánh suy nghĩ đó bằng cách trở thành một loại biến đại số đại diện cho bất kỳ nội dung nào trong phổ trải nghiệm sống động.

Biểu đồ minh hoạ quang phổ của trải nghiệm hình ảnh từ thực tế hoàn toàn đến hoàn toàn sống động.
Phạm vi trải nghiệm sống động

Sau đây là một số ví dụ về trải nghiệm sống động:

  • Trò chơi
  • Video 360°
  • Video 2D (hoặc 3D) truyền thống được trình bày trong môi trường sống động
  • Mua nhà
  • Xem sản phẩm trong nhà trước khi mua
  • Nghệ thuật sống động
  • Một điều gì đó thú vị mà chưa ai nghĩ đến

Khái niệm và cách sử dụng

Tôi sẽ giải thích một số thông tin cơ bản về cách sử dụng API thiết bị WebXR. Nếu bạn cần tìm hiểu sâu hơn những nội dung mà tôi đã cung cấp, hãy xem mẫu WebXR của Nhóm làm việc về web sống động hoặc các tài liệu tham khảo ngày càng phong phú của MDN. Nếu đã quen thuộc với các phiên bản đầu của WebXR Device API, bạn nên xem qua tất cả tài liệu này. Có thay đổi.

Mã trong bài viết này dựa trên mẫu cơ bản của Nhóm làm việc về web sống động (bản minh hoạ, nguồn), nhưng được chỉnh sửa để rõ ràng và đơn giản.

Một phần của việc tạo thông số kỹ thuật WebXR là triển khai các biện pháp bảo mật và quyền riêng tư để bảo vệ người dùng. Do đó, quá trình triển khai phải tuân thủ một số yêu cầu nhất định. Một trang web hoặc ứng dụng phải đang hoạt động và được lấy làm tâm điểm trước khi có thể yêu cầu người xem cung cấp thông tin nhạy cảm. Trang web hoặc ứng dụng phải được phân phát qua HTTPS. Bản thân API được thiết kế để bảo vệ thông tin thu được từ các cảm biến và máy ảnh mà API cần để hoạt động.

Yêu cầu một phiên

Để chuyển sang phiên XR, người dùng cần thực hiện một cử chỉ. Để làm được điều đó, hãy sử dụng tính năng phát hiện tính năng để kiểm thử XRSystem (thông qua navigator.xr) và thực hiện lệnh gọi đến XRSystem.isSessionSupported(). Xin lưu ý rằng trong Chrome phiên bản 79 và 80, đối tượng XRSystem được gọi là XR.

Trong ví dụ bên dưới, tôi đã cho biết rằng tôi muốn có một phiên thực tế ảo với loại phiên 'immersive-vr'. Các loại phiên khác'immersive-ar''inline'. Phiên nội tuyến dùng để trình bày nội dung trong HTML và chủ yếu dùng cho nội dung giới thiệu. Mẫu Phiên AR sống động minh hoạ điều này. Tôi sẽ giải thích điều đó trong một bài viết sau.

Khi biết rằng các phiên thực tế ảo được hỗ trợ, tôi sẽ bật một nút cho phép tôi thu thập cử chỉ của người dùng.

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
 
}
}

Sau khi bật nút này, tôi đợi một sự kiện nhấp rồi yêu cầu một phiên.

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();
 
}
}

Hãy chú ý đến hệ phân cấp đối tượng trong mã này. Lớp này di chuyển từ navigator đến xr đến một thực thể XRSession. Trong các phiên bản API ban đầu, tập lệnh phải yêu cầu một thiết bị trước khi yêu cầu một phiên. Giờ đây, thiết bị được thu nạp ngầm.

Nhập phiên

Sau khi nhận được một phiên, tôi cần bắt đầu và nhập phiên đó. Nhưng trước tiên, tôi cần thiết lập một vài thứ. Một phiên hoạt động cần có trình xử lý sự kiện onend để có thể đặt lại ứng dụng hoặc trang web khi người dùng thoát.

Tôi cũng cần một phần tử <canvas> để vẽ cảnh. Đó phải là WebGLRenderingContext hoặc WebGL2RenderingContext tương thích với XR. Tất cả các bản vẽ đều được thực hiện bằng cách sử dụng các lớp này hoặc một khung dựa trên WebGL như Three.js.

Bây giờ, tôi đã có một nơi để vẽ, tôi cần một nguồn nội dung để vẽ trên đó. Để làm việc đó, tôi tạo một thực thể của XRWebGLLayer. Tôi liên kết lớp này với canvas bằng cách gọi XRSession.updateRenderState().

Khi đang ở trong một phiên, tôi cần có cách xác định vị trí của các đối tượng trong thực tế ảo. Tôi cần một không gian tham khảo. Không gian tham chiếu 'local-floor' là không gian mà gốc toạ độ nằm gần người xem và trục y là 0 ở cấp sàn và không dự kiến sẽ di chuyển. Có các loại không gian tham chiếu khác, nhưng đó là một chủ đề phức tạp hơn mà tôi không thể đề cập ở đây. Tôi lưu không gian tham chiếu vào một biến vì tôi sẽ cần không gian này khi vẽ lên màn hình.

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);
 
});
}

Sau khi nhận được không gian tham chiếu, tôi gọi XRSession.requestAnimationFrame(). Đây là bước bắt đầu trình bày nội dung ảo, được thực hiện trong vòng lặp khung.

Chạy vòng lặp khung

Vòng lặp khung là một vòng lặp vô hạn do tác nhân người dùng kiểm soát, trong đó nội dung được vẽ lặp lại trên màn hình. Nội dung được vẽ trong các khối riêng biệt gọi là khung. Sự kế tiếp của các khung hình tạo ra ảo giác chuyển động. Đối với các ứng dụng VR, số khung hình/giây có thể dao động từ 60 đến 144. AR cho Android chạy ở tốc độ 30 khung hình/giây. Mã của bạn không được giả định bất kỳ tốc độ khung hình cụ thể nào.

Quy trình cơ bản cho vòng lặp khung là:

  1. Gọi cho XRSession.requestAnimationFrame(). Để phản hồi, tác nhân người dùng sẽ gọi XRFrameRequestCallback do bạn xác định.
  2. Bên trong hàm callback:
    1. Gọi lại XRSession.requestAnimationFrame().
    2. Nhận tư thế của người xem.
    3. Truyền ('liên kết') WebGLFramebuffer từ XRWebGLLayer đến WebGLRenderingContext.
    4. Lặp lại trên từng đối tượng XRView, truy xuất XRViewport của đối tượng đó từ XRWebGLLayer và truyền đối tượng đó đến WebGLRenderingContext.
    5. Vẽ nội dung nào đó vào vùng đệm khung hình.

Phần còn lại của bài viết này mô tả bước 1 và một phần bước 2, thiết lập và gọi XRFrameRequestCallback. Các mục còn lại của bước 2 sẽ được đề cập trong phần II.

XRFrameRequestCallback

XRFrameRequestCallback do bạn xác định. Phương thức này có hai tham số: một DOMHighResTimeStamp và một thực thể XRFrame. Đối tượng XRFrame cung cấp thông tin cần thiết để kết xuất một khung hình duy nhất cho màn hình. Đối số DOMHighResTimeStamp dùng để sử dụng sau này.

Trước khi làm gì khác, tôi sẽ yêu cầu khung ảnh động tiếp theo. Như đã nêu trước đó, thời gian của các khung hình do tác nhân người dùng xác định dựa trên phần cứng cơ bản. Việc yêu cầu khung hình tiếp theo trước tiên sẽ đảm bảo rằng vòng lặp khung hình sẽ tiếp tục nếu có lỗi xảy ra trong lệnh gọi lại.

function onXRFrame(hrTime, xrFrame) {
  let xrSession
= xrFrame.session;
  xrSession
.requestAnimationFrame(onXRFrame);
 
// Render a frame.
}

Bây giờ, đã đến lúc vẽ một cái gì đó cho người xem. Đó là nội dung thảo luận cho phần II. Trước khi chuyển sang phần đó, hãy để tôi hướng dẫn bạn cách kết thúc một phiên.

Kết thúc phiên

Một phiên có chế độ chìm có thể kết thúc vì một số lý do, bao gồm cả việc kết thúc bằng mã của riêng bạn thông qua lệnh gọi đến XRSession.end(). Các nguyên nhân khác bao gồm tai nghe bị ngắt kết nối hoặc một ứng dụng khác đang kiểm soát tai nghe. Đây là lý do tại sao một ứng dụng hoạt động tốt phải theo dõi sự kiện end. Khi lỗi này xảy ra, hãy loại bỏ phiên và các đối tượng kết xuất liên quan. Không thể tiếp tục phiên sống động đã kết thúc. Để quay lại trải nghiệm sống động, ứng dụng của tôi cần bắt đầu một phiên mới.

Hãy nhớ lại phần Bắt đầu phiên, trong quá trình thiết lập, tôi đã thêm một trình xử lý sự kiện onend.

function onSessionStarted(xrSession) {
  xrSession
.addEventListener('end', onSessionEnded);
 
// More setup…
}

Bên trong trình xử lý sự kiện, hãy khôi phục trạng thái của ứng dụng trước khi người dùng bắt đầu một phiên.

function onSessionEnded(event) {
  xrSession
= null;
  xrButton
.textContent = 'Enter VR';
}

Kết luận

Tôi chưa giải thích mọi thứ bạn cần để viết ứng dụng Web XR hoặc AR. Hy vọng rằng tôi đã cung cấp cho bạn đủ thông tin để bắt đầu hiểu rõ mã và đủ để bắt đầu thử nghiệm. Trong bài viết tiếp theo, tôi sẽ giải thích về vòng lặp khung hình, nơi nội dung được vẽ lên màn hình.

Ảnh của JESHOOTS.COM trên Unsplash