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. API 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 thực tế ảo 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 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, đã được cung cấp 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 bạn cần tiếp tục.

Thời gian 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 WebXR Device API và 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ổ 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 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 giúp triển khai đơn giản hơn và cải thiện đáng kể hiệu suất. Đồng thời, các trường hợp sử dụ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à API phải có thể mở rộng để hỗ trợ những trường hợp đó trong tương lai.

WebXR Device API được thiết kế và đặt tên theo các trường hợp sử dụng mở rộng này và cung cấp một đường dẫ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à 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ó mặt trên 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.

Có nhiều thông tin về API mới này hơn 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 rõ về mẫu WebXR. Bạn có thể tìm thêm thông tin trong cả nội dung 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.

Những gì tôi sẽ không đề cập đến là cách vẽ nội dung thực tế tăng cường/thực tế ảo 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 là 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 xem xét 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ừ nội dung tôi sắp trình bày cho bạn. 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 hàm này trong một hàm được gọi là 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. Để gỡ rối vấn đề này, tôi chuẩn bị đưa ra một loạt từ vào bạn. Nếu bạn muốn xem nhanh mã hoàn chỉnh, hãy chuyển tới trước để xem nhanh rồi quay lại để xem phần giải thích đầy đủ. Có khá nhiều nội dung 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 như sau:

  1. Yêu cầu khung ảnh động.
  2. Truy vấn vị trí của thiết bị.
  3. Vẽ nội dung theo 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 tính điểm gốc của hệ toạ độ và điều gì xảy ra với điểm 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 một đố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 thực tế tăng cường/thực tế ảo cho thiết bị. Điều này hơi khó hiểu vì khung bản trình bày được truy xuất bằng cách gọi requestAnimationFrame(). Điều này làm cho thư viện này 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 thấy 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/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ó thể lấy 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 bạn vẽ được gọi là khung hiển thị (XRView). Đây là nơi loại phiên đóng vai trò 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, mảng đó sẽ có một khung hiển thị. 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à 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 qua một khung hiển thị có vẻ là vô nghĩa, nhưng làm như vậy sẽ giú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 điều này, tôi sẽ có mã dưới đây. Tôi đã để lại một phần giữ chỗ cho các thiết bị đầu vào, tôi sẽ đề cập đến điều này trong 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, 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ỏ xác định để cho biết vị trí một thiết bị đầu vào trỏ đến và các sự kiện để cho biết thời điểm một đối tượng nào đó đượ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 một cách 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 đó gần như sẽ diễn ra 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 bất cứ điều gì hữu ích, người dùng cần có khả năng chọn nội dung. 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. Chúng sẽ không cho bạn biết mục nào trong môi trường đã được nhấp vào. Các trình xử lý sự kiện được thêm vào đối tượng XRSession và cần được thêm vào ngay khi có.

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 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, tôi khuyến khích bạn thử những gì chúng tôi đã đạt đượ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ế.