Chào mừng bạn đến với môi trường web sống động

Web sống động là những trải nghiệm thế giới ảo được lưu trữ thông qua trình duyệt. Toàn bộ trải nghiệm thực tế ảo này hiển thị trên trình duyệt hoặc trong tai nghe hỗ trợ thực tế ảo (VR).

Joe Medley
Joe Medley

Web sống động là những trải nghiệm thế giới ảo được lưu trữ thông qua trình duyệt. Phần này bao gồm toàn bộ trải nghiệm thực tế ảo (VR) xuất hiện trên trình duyệt hoặc trong các tai nghe hỗ trợ thực tế ảo như Daydream, Oculus Rift, Samsung Gear VR, HTC Vive và Tai nghe thực tế hỗn hợp của Windows, cũng như trải nghiệm thực tế tăng cường được phát triển cho các thiết bị di động hỗ trợ AR.

Mặc dù chúng tôi sử dụng hai thuật ngữ để mô tả trải nghiệm sống động, nhưng chúng tôi nên coi đó là một phạm vi từ thực tế hoàn chỉnh đến môi trường thực tế ảo hoàn toàn sống động, với nhiều cấp độ AR ở giữa.

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

  • Video 360° sống động
  • Video 2D (hoặc 3D) truyền thống được trình bày trong môi trường sống động
  • Hình ảnh dữ liệu
  • Mua sắm tại nhà
  • Nghệ thuật
  • Nội dung thú vị chưa ai nghĩ đến

Tôi đến đó bằng cách nào?

Web sống động đã có mặt gần một năm nay ở dạng phôi thai. Bạn có thể thực hiện việc này thông qua API WebVR 1.1, đã có trong bản dùng thử theo nguyên gốc kể từ Chrome 62. API đó cũng được Firefox và Edge hỗ trợ, cũng như một polyfill cho Safari.

Nhưng đã đến lúc tiếp tục.

Bản dùng thử theo nguyên gốc kết thúc vào ngày 24 tháng 7 năm 2018 và thông số kỹ thuật đã được thay thế bằng API thiết bị WebXR và một bản dùng thử theo nguyên gốc mới.

Điều gì đã xảy ra với WebVR 1.1?

Chúng tôi đã học được rất nhiều từ WebVR 1.1, nhưng theo thời gian, rõ ràng là cần phải có một số thay đổi quan trọng để hỗ trợ các loại ứng dụng mà nhà phát triển muốn xây dựng. Danh sách đầy đủ các bài học rút ra được là quá dài để trình bày ở đây, nhưng bao gồm các vấn đề như API được liên kết rõ ràng với luồng JavaScript chính, quá nhiều cơ hội để nhà phát triển thiết lập cấu hình rõ ràng là không chính xác, và các trường hợp sử dụng phổ biến như Cửa sổ ma thuật là tác dụng phụ thay vì tính năng có chủ đích. (Cửa sổ thần kỳ là một kỹ thuật để xem nội dung sống động mà không cần tai nghe, trong đó ứng dụng sẽ hiển thị một khung hiển thị dựa trên cảm biến hướng của thiết bị.)

Thiết kế mới tạo điều kiện cho việc triển khai đơn giản hơn và cải thiện lớn về hiệu suất. Đồng thời, thực tế tăng cường (AR) và các trường hợp sử dụng khác cũng đang xuất hiện và điều quan trọng là có thể mở rộng API này để hỗ trợ những trường hợp đó trong tương lai.

WebXR Device API được thiết kế và đặt tên dựa trên các trường hợp sử dụng mở rộng này, đồng thời cung cấp một lộ trình phát triển tốt hơn. Những người triển khai WebVR đã cam kết di chuyển sang WebXR Device API.

WebXR Device API là gì?

Giống như thông số kỹ thuật WebVR trước đó, WebXR Device API là một sản phẩm của Immersive Web Community Group (Nhóm cộng đồng web sống động), có các cộng tác viên của Google, Microsoft, Mozilla và nhiều bên khác. Chữ "X trong XR" được dùng như một 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. Tính năng này có sẵn trong bản dùng thử theo nguyên gốc đã đề cập trước đó cũng như thông qua polyfill.

Khi bài viết này được xuất bản lần đầu trong giai đoạn thử nghiệm beta của Chrome 67, chỉ các tính năng thực tế ảo được bật. Tính năng thực tế tăng cường đã có trên Chrome 69. Hãy đọc về tính năng này trong Thực tế tăng cường cho web.

Có nhiều điều về API mới này hơn so với những gì tôi có thể đề cập trong một bài viết như thế này. Tôi muốn cung cấp đủ cho bạn đủ thông tin để bắt đầu hiểu được mẫu WebXR. Bạn có thể tìm thêm thông tin trong cả nội dung giải thích gốcHướng dẫn sử dụng sớm quảng cáo web trực quan của chúng tôi. Tôi sẽ mở rộng giai đoạn sau khi bản dùng thử theo nguyên gốc tiến triển. Bạn có thể thoải mái mở các vấn đề hoặc gửi yêu cầu lấy dữ liệu.

Đối với bài viết này, tôi sẽ thảo luận về việc bắt đầu, dừng và chạy phiên XR, cùng với một vài thông tin cơ bản về quá trình xử lý dữ liệu đầu vào.

Tôi không trình bày cách vẽ nội dung thực tế tăng cường/thực tế ảo lên màn hình. WebXR Device API không cung cấp các tính năng kết xuất hình ảnh. Điều đó tùy thuộc vào bạn. Quá trình vẽ được thực hiện bằng API WebGL. Bạn có thể thực hiện điều đó nếu bạn thực sự tham vọng. Tuy nhiên, bạn nên sử dụng một khung. Các mẫu web sống động sử dụng một mẫu được tạo riêng cho các bản minh hoạ có tên là Cottontail. Three.js đã hỗ trợ WebXR kể từ tháng 5. Tôi chưa biết gì về A-Frame.

Khởi động và chạy ứng dụng

Quy trình cơ bản là như sau:

  1. Yêu cầu thiết bị XR.
  2. Nếu có, hãy yêu cầu một phiên XR. Nếu bạn muốn người dùng đặt điện thoại vào tai nghe, thì phiên này được gọi là phiên sống động và yêu cầu người dùng dùng cử chỉ để tham gia.
  3. Hãy sử dụng phiên này để chạy vòng lặp kết xuất hình ảnh có tốc độ 60 khung hình/giây. Vẽ nội dung phù hợp lên màn hình trong mỗi khung hình.
  4. Chạy vòng lặp kết xuất cho đến khi người dùng quyết định thoát.
  5. Kết thúc phiên XR.

Hãy xem xét điều này chi tiết hơn một chút và đưa vào một số mã. Bạn sẽ không thể chạy ứng dụng từ những gì tôi sắp cho bạn thấy. Nhưng một lần nữa, đây chỉ là để giúp bạn hiểu thêm về nó.

Yêu cầu thiết bị XR

Tại đây, bạn sẽ nhận ra mã phát hiện tính năng tiêu chuẩn. Bạn có thể gói hàm này trong một hàm có tên là checkForXR().

Nếu không sử dụng một phiên sống động, bạn có thể bỏ qua việc quảng cáo chức năng và nhận cử chỉ của người dùng, cũng như chuyển thẳng đến bước yêu cầu một phiên. Phiên sống động là phiên yêu cầu tai nghe. Phiên không chìm chỉ hiển thị nội dung trên màn hình thiết bị. Cách thứ nhất là suy nghĩ của hầu hết mọi người khi đề cập đến thực tế ảo hoặc thực tế tăng cường. Vết sau đôi khi được gọi là "cửa sổ ma thuật".

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

Yêu cầu phiên XR

Giờ đây, khi đã có thiết bị và cử chỉ của người dùng, đã đến lúc thực hiện một phiên. Để tạo phiên, trình duyệt cần có canvas để vẽ trên đó.

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

Chạy vòng lặp kết xuất

Mã cho bước này có chút khó khăn. Để giải quyết vấn đề này, tôi sẽ ném nhiều từ vào bạn. Nếu bạn muốn xem nhanh mã hoàn chỉnh, hãy chuyển lên trước để xem nhanh rồi quay lại để xem nội dung giải thích đầy đủ. Có khá nhiều điều mà bạn có thể không dự đoán được.

Quy trình cơ bản cho vòng lặp kết xuất là:

  1. Yêu cầu khung ảnh động.
  2. Truy vấn vị trí của thiết bị.
  3. Vẽ nội dung vào vị trí của thiết bị dựa trên vị trí đó.
  4. Thực hiện công việc cần thiết cho thiết bị đầu vào.
  5. Lặp lại 60 lần mỗi giây cho đến khi người dùng quyết định thoát.

Yêu cầu khung bản trình bày

Từ 'khung' có một số nghĩa trong ngữ cảnh Web XR. Đầu tiên là khung tham chiếu, xác định vị trí tính toán gốc của hệ toạ độ và điều gì xảy ra với gốc đó khi thiết bị di chuyển. (Khung hiển thị vẫn giữ nguyên khi người dùng di chuyển hay thay đổi như trong thực tế?)

Loại khung thứ hai là khung trình bày, được biểu thị bằng đối tượng XRFrame. Đối tượng này chứa thông tin cần thiết để kết xuất một khung duy nhất của cảnh AR/VR cho thiết bị. Điều này hơi khó hiểu vì một khung bản trình bày được truy xuất bằng cách gọi requestAnimationFrame(). Điều này giúp ứng dụng tương thích với window.requestAnimationFrame().

Trước khi tôi cung cấp cho bạn thêm thông tin, tôi sẽ cho bạn một vài mã. Mẫu dưới đây cho thấy cách vòng lặp kết xuất bắt đầu và duy trì. Hãy lưu ý đến cách sử dụng kép của khung từ. Đồng thời, hãy chú ý đến lệnh gọi đệ quy đến requestAnimationFrame(). Hàm này sẽ được gọi 60 lần trong một giây.

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

Tư thế

Trước khi vẽ bất kỳ nội dung nào lên màn hình, bạn cần biết thiết bị hiển thị đang trỏ đến đâu và bạn cần quyền truy cập vào màn hình. Nhìn chung, vị trí và hướng của một đối tượng trong AR/VR được gọi là tư thế. Cả người xem và thiết bị đầu vào đều có tư thế. (Tôi bao gồm thiết bị đầu vào sau.) Cả tư thế người xem và thiết bị đầu vào đều được xác định là ma trận 4 x 4, được lưu trữ trong Float32Array theo thứ tự chính của cột. Bạn có thể biết tư thế của người xem bằng cách gọi XRFrame.getDevicePose() trên đối tượng khung ảnh động hiện tại. Luôn kiểm tra xem bạn có tạo tư thế nào không. Nếu đã xảy ra lỗi, bạn không muốn vẽ lên màn hình.

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

Số lượt xem

Sau khi kiểm tra tư thế, đã đến lúc vẽ một vật gì đó. Đối tượng bạn vẽ vào được gọi là thành phần hiển thị (XRView). Đây là nơi loại phiên trở nên quan trọng. Khung hiển thị được truy xuất từ đối tượng XRFrame dưới dạng một mảng. Nếu bạn đang ở trong một phiên không chìm, thì mảng này sẽ có một khung hiển thị. Nếu bạn đang ở trong một phiên sống động, thì mảng này có 2, một cho mỗi mắt.

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

Đây là một điểm khác biệt quan trọng giữa WebXR và các hệ thống toàn màn hình khác. Mặc dù việc lặp lại một khung hiển thị nghe có vẻ vô nghĩa, nhưng làm như vậy sẽ cho phép bạn có một đường dẫn kết xuất duy nhất cho nhiều thiết bị.

Toàn bộ vòng lặp kết xuất

Nếu gộp tất cả những thông tin này lại với nhau, tôi sẽ nhận được mã như bên dưới. Tôi đã giữ lại một phần giữ chỗ cho các thiết bị đầu vào. Tôi sẽ đề cập đến phần này ở phần sau.

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

Kết thúc phiên XR

Phiên XR có thể kết thúc vì một số lý do, trong đó 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 nên theo dõi sự kiện kết thúc và khi sự kiện đó xảy ra, hãy loại bỏ các đối tượng phiên và đối tượng kết xuất đồ hoạ. Không thể tiếp tục phiên XR sau khi kết thúc.

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

Hoạt động tương tác hoạt động như thế nào?

Tương tự như với vòng đời của ứng dụng, tôi sẽ cho bạn biết cách tương tác với các đối tượng trong Thực tế tăng cường (AR) hoặc Thực tế ảo (VR).

WebXR Device API sử dụng phương pháp "điểm và nhấp" cho hoạt động đầu vào của người dùng. Với phương pháp này, mọi nguồn đầu vào đều có một tia con trỏ được xác định để cho biết vị trí mà thiết bị đầu vào đang trỏ đến và các sự kiện để cho biết thời điểm có mục nào đó được chọn. Ứng dụng của bạn vẽ tia con trỏ và cho thấy nơi nó trỏ tới. Khi người dùng nhấp vào thiết bị đầu vào, các sự kiện sẽ được kích hoạt – cụ thể là select, selectStartselectEnd. Ứng dụng của bạn xác định nội dung được nhấp và phản hồi phù hợp.

Thiết bị đầu vào và tia con trỏ

Đối với người dùng, tia con trỏ chỉ là một đường mờ giữa bộ điều khiển và bất kỳ nội dung nào mà họ đang trỏ vào. Tuy nhiên, ứng dụng của bạn phải vẽ hình ảnh đó. Điều đó có nghĩa là bạn sẽ nhận được tư thế của thiết bị đầu vào và vẽ một đường từ vị trí của thiết bị đó đến một đối tượng trong không gian AR/VR. Quy trình đó có dạng như sau:

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

Đây là phiên bản rút gọn của mẫu Theo dõi dữ liệu đầu vào từ Nhóm cộng đồng web sống động. Tương tự như với kết xuất khung hình, bạn có thể vẽ tia con trỏ và thiết bị là tuỳ thuộc vào bạn. Như đã đề cập trước đó, mã này phải được chạy trong vòng lặp kết xuất.

Chọn các mục trong không gian ảo

Việc chỉ xem các nội dung trong công nghệ thực tế tăng cường (AR/VR) là rất vô ích. Để làm bất cứ việc gì hữu ích, người dùng cần có khả năng chọn nội dung. WebXR Device API cung cấp 3 sự kiện để phản hồi các tương tác của người dùng: select, selectStartselectEnd. Chúng có một điều kỳ lạ mà tôi không ngờ tới: chúng chỉ cho bạn biết rằng một thiết bị đầu vào đã được nhấp vào. Chúng không cho bạn biết mục nào trong môi trường đã được nhấp. Trình xử lý sự kiện được thêm vào đối tượng XRSession và bạn nên thêm ngay khi có thể.

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

Mã này dựa trên một ví dụ về Lựa chọn đầu vào, trong trường hợp bạn muốn biết thêm ngữ cảnh.

Để tìm hiểu xem nội dung nào được nhấp vào, bạn hãy sử dụng tư thế. (Bạn có ngạc nhiên không? Tôi không nghĩ như vậy.) Thông tin chi tiết về API đó dành riêng cho ứng dụng của bạn hoặc bất kỳ khung nào mà bạn đang sử dụng, nên nằm ngoài phạm vi của bài viết này. Cách tiếp cận của Cottontail là trong ví dụ về Lựa chọn đầu vào.

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

Kết luận: nhìn về phía trước

Như tôi đã nói trước đó, tính năng thực tế tăng cường sẽ có trong Chrome 69 (Canary vào khoảng tháng 6 năm 2018). Dù vậy, tôi vẫn khuyến khích bạn thử những gì chúng tôi đã làm. Chúng tôi cần ý kiến phản hồi để cải thiện tính năng này. Hãy theo dõi tiến trình bằng cách xem ChromeStatus.com để biết tính năng Kiểm thử lượt truy cập WebXR. Bạn cũng có thể làm theo WebXR Anchors (Neo WebXR) để cải thiện tính năng theo dõi tư thế.