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

Web sống động là 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 xuất hiện trong trình duyệt hoặc trong tai nghe hỗ trợ VR.

Joe Medley
Joe Medley

Web sống động là trải nghiệm thế giới ảo được lưu trữ thông qua trình duyệt. Điều này bao gồm toàn bộ trải nghiệm thực tế ảo (VR) xuất hiện trong trình duyệt hoặc trong tai nghe hỗ trợ VR như Daydream của Google, Oculus Rift, Samsung Gear VR, HTC Vive và Tai nghe Windows Mixed Reality, 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 ta sử dụng hai thuật ngữ để mô tả trải nghiệm sống động, nhưng bạn nên coi chúng là một phổ 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
  • Một điều gì đó thú vị mà chưa ai nghĩ đến

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

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

Nhưng đã đến lúc chuyển sang việc khá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 này đã được thay thế bằng WebXR Device API 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 nhiều điều từ WebVR 1.1, nhưng theo thời gian, chúng tôi nhận thấy rõ ràng rằng cần phải có một số thay đổi lớn để 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 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à sai và các trường hợp sử dụng phổ biến như cửa sổ ma thuật là một hiệu ứng phụ thay vì một tính năng có chủ ý. (Cửa sổ ảo là một kỹ thuật để xem nội dung sống động mà không cần tai nghe, trong đó ứng dụng hiển thị một chế độ xem dựa trên cảm biến hướng của thiết bị.)

Thiết kế mới giúp triển khai đơn giản hơn và cải thiện đáng kể hiệu suất. Đồng thời, AR và các trường hợp sử dụng khác đang xuất hiện, vì vậy, API cần phải có khả năng mở rộng để hỗ trợ các trường hợp sử dụng đó trong tương lai.

WebXR Device API được thiết kế và đặt tên dựa trên những trường hợp sử dụng mở rộng này, đồng thời cung cấp một lộ trình 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à sản phẩm của Nhóm cộng đồng Web sống động, trong đó có các cộng tác viên từ Google, Microsoft, Mozilla và các công ty khác. "X trong XR" được coi là 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. Tính năng này có trong thử nghiệm nguồ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 tiên trong giai đoạn thử nghiệm của Chrome 67, chỉ có các tính năng VR được bật. Công nghệ thực tế tăng cường đã có trong Chrome 69. Hãy đọc về tính năng này trong bài viết Thực tế tăng cường cho web.

API mới này còn có nhiều tính năng khác mà tôi không 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 rõ về mẫu WebXR. Bạn có thể tìm thêm thông tin trong cả video giải thích ban đầuHướng dẫn dành cho người dùng sớm Web sống động. Tôi sẽ mở rộng phần sau khi quá trình thử nghiệm nguồn gốc diễn ra. Vui lòng mở vấn đề hoặc gửi yêu cầu lấy dữ liệu.

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

Tôi sẽ không đề cập đến cách vẽ nội dung AR/VR lên màn hình. API Thiết bị WebXR không cung cấp các tính năng kết xuất hình ảnh. Tuỳ vào bạn cả đấy. Quá trình vẽ được thực hiện bằng các API WebGL. Bạn có thể làm việc đó nếu thực sự có 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 Cottontail. Three.js đã hỗ trợ WebXR kể từ tháng 5. Tôi chưa nghe thấy gì về A-Frame.

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

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

  1. Yêu cầu thiết bị XR.
  2. Yêu cầu một phiên XR (nếu có). Nếu bạn muốn người dùng đặt điện thoại vào tai nghe, thì đó được gọi là phiên sống động và yêu cầu người dùng thực hiện một cử chỉ để truy cập.
  3. Sử dụng phiên để chạy một vòng lặp kết xuất cung cấp 60 khung hình hình ảnh mỗi giây. Vẽ nội dung thích 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 cùng tìm hiểu chi tiết hơn về vấn đề này và thêm 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 xin nhắc lại, đây chỉ là để bạn hiểu rõ hơn về vấn đề này.

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 nội dung này trong một hàm có tên như checkForXR().

Nếu không sử dụng phiên chìm, 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, đồng thời chuyển thẳng đến yêu cầu phiên. Phiên sống động là phiên cần có tai nghe. Phiên không sống động chỉ hiển thị nội dung trên màn hình thiết bị. Thực tế ảo là điều mà hầu hết mọi người nghĩ đến khi bạn đề cập đến thực tế ảo hoặc thực tế tăng cường. Loại 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 chúng ta bắt đầu một phiên. Để tạo một phiên, trình duyệt cần có một canvas để vẽ.

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ần được gỡ rối một chút. Để giải thích rõ hơn, tôi sẽ đưa ra một số từ. Nếu bạn muốn xem trước mã hoàn chỉnh, hãy chuyển sang phần sau để xem nhanh rồi quay lại để xem nội dung giải thích đầy đủ. Có khá nhiều thông tin mà bạn có thể không thể suy luận được.

Quy trình cơ bản cho một 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í của thiết bị.
  4. Thực hiện công việc cần thiết cho các 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 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 nơi gốc của hệ toạ độ được tính toán và điều gì xảy ra với gốc đó khi thiết bị di chuyển. (Chế độ xem có giữ nguyên khi người dùng di chuyển hay thay đổi như trong thực tế không?)

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 hình của cảnh AR/VR cho thiết bị. Điều này hơi khó hiểu vì khung trình bày được truy xuất bằng cách gọi requestAnimationFrame(). Điều này giúp tương thích với window.requestAnimationFrame().

Trước khi cung cấp thêm thông tin cho bạn, tôi sẽ cung cấp một số mã. Mẫu bên dưới cho biết cách bắt đầu và duy trì vòng lặp kết xuất. Lưu ý cách sử dụng kép của khung từ. Và hãy lưu ý lệnh gọi đệ quy đến requestAnimationFrame(). Hàm này sẽ được gọi 60 lần mỗi 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ỏ vào đâu và bạn cần có quyền truy cập vào màn hình. Nhìn chung, vị trí và hướng của một vật trong AR/VR được gọi là tư thế. Cả trình xem và thiết bị đầu vào đều có tư thế. (Tôi sẽ đề cập đến thiết bị đầu vào sau.) Cả tư thế của người xem và thiết bị đầu vào đều được xác định là một ma trận 4x4 được lưu trữ trong Float32Array theo thứ tự chính của cột. Bạn có được 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ó nhận được tư thế không. Nếu có lỗi xảy ra, bạn không nê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 thứ gì đó. Đối tượng mà 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 sống động, mảng sẽ có một chế độ xem. Nếu bạn đang ở trong một phiên sống động, mảng sẽ có hai, một cho mỗi mắt.

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

Đây là điểm khác biệt quan trọng giữa WebXR và các hệ thống sống động khác. Mặc dù có vẻ như việc lặp lại một thành phần hiển thị là vô ích, nhưng việc này 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 kết hợp tất cả những nội dung này, tôi sẽ có mã dưới đây. Tôi đã để lại 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

Một phiên XR 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 kết thúc và khi sự kiện đó xảy ra, hãy loại bỏ phiên và đối tượng trình kết xuất. Bạn không thể tiếp tục phiên XR sau khi phiên đó 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?

Cũng như thời gian hoạt động của ứng dụng, tôi chỉ giới thiệu cho bạn cách tương tác với các đối tượng trong AR hoặc VR.

WebXR Device API sử dụng phương pháp "trỏ và nhấp" cho dữ liệu đầ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í thiết bị đầu vào đang trỏ đến và các sự kiện để cho biết thời điểm một mục được chọn. Ứng dụng của bạn sẽ vẽ tia con trỏ và cho biết vị trí con trỏ trỏ đến. 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 tay điều khiển và bất kỳ đối tượng nào mà họ đang trỏ vào. Nhưng ứng dụng của bạn phải vẽ nó. Điều đó có nghĩa là lấy 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 đầu vào từ Nhóm cộng đồng Web sống động. Cũng như khi kết xuất khung hình, bạn có thể vẽ tia con trỏ và thiết bị. 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ỉ trỏ vào các vật thể trong AR/VR là khá vô ích. Để làm được việc gì đó hữu ích, người dùng cần có khả năng chọn. API Thiết bị WebXR cung cấp 3 sự kiện để phản hồi các hoạt động tương tác của người dùng: select, selectStartselectEnd. Các sự kiện này có một điểm 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. Các sự kiện này không cho bạn biết mục nào trong môi trường đã được nhấp vào. Trình xử lý sự kiện được thêm vào đối tượng XRSession và nên được thêm ngay khi có sẵn.

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 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 nội dung được nhấp vào, bạn sử dụng một tư thế. (Bạn có ngạc nhiên không? Tôi không nghĩ vậy.) Thông tin chi tiết về việc đó là dành riêng cho ứng dụng của bạn hoặc bất kỳ khung nào bạn đang sử dụng, do đó nằm ngoài phạm vi của bài viết này. Phương pháp của Cottontail có 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: hướng đến tương lai

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