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

Một số thông tin cơ bản để giúp bạn chuẩn bị cho nhiều trải nghiệm sống động: thực tế ảo, thực tế tăng cường và nhiều trải nghiệm khác.

Joe Medley
Joe Medley

Chrome 79 đã mang đến trải nghiệm sống động trên web. WebXR Device API mang đến trải nghiệm thực tế ảo mang đến trải nghiệm thực tế ảo, trong khi Chrome 81 hỗ trợ thực tế tăng cường. 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 bắt đầu một loạt nội dung 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 (chi tiết về trải nghiệm WebXR), thông tin cụ thể về thực tế tăng cường và WebXR Hit Test API, một phương tiện phát hiện các 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 nhập vai 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 cho rằng chúng nằm trên một quang 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.
Các trải nghiệm sống động khác nhau

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 chiếu trong không gian sống động
  • Mua nhà
  • Xem sản phẩm trong nhà trước khi mua
  • Nghệ thuật sống động
  • Nội dung 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ố kiến thức 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 với các phiên bản ban đầu của API thiết bị WebXR, bạn nên xem nhanh 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 web nhập vai (bản minh hoạ, nguồn), nhưng được chỉnh sửa để cho rõ ràng và đơn giản.

Trong quá trình tạo ra thông số kỹ thuật WebXR, chúng tôi đã chi tiết hoá 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

Để vào phiên XR, người dùng cần phải 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. Thao tác này sẽ chuyển từ navigator sang xr sang 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ả thao tác vẽ đều được thực hiện bằng cách sử dụng chúng hoặc khung dựa trên WebGL, chẳng hạn 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 được việc đó, tôi sẽ 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 được 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 dành 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. Lấy 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 mỗi đố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ẽ một nội dung 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 của 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 vào màn hình. Đối số DOMHighResTimeStamp được dùng để sử dụng trong tương lai.

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à một cuộc thảo luận trong 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 toàn cảnh 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 nó xảy ra, hãy loại bỏ phiên và các đối tượng kết xuất có liên quan của phiên đó. 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 rằng 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 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