Witamy w rzeczywistości wirtualnej

Immersyjny internet oznacza wirtualny świat dostępny w przeglądarce. Cała rzeczywistość wirtualna jest wyświetlana w przeglądarce lub w goglach do VR.

Joe Medley
Joe Medley

Wciągający internet to wirtualne światy hostowane w przeglądarce. Dotyczy to całej rzeczywistości wirtualnej (VR) wyświetlanej w przeglądarce oraz gogli obsługujących VR, takich jak Google Daydream, Oculus Rift, Samsung Gear VR, HTC Vive i zestawy do rzeczywistości mieszanej Windows, a także środowiska rzeczywistości rozszerzonej opracowane na potrzeby urządzeń mobilnych z obsługą AR.

Chociaż do opisania wciągających doświadczeń używamy 2 określeń, należy je rozpatrywać jako spektrum od pełnej rzeczywistości do w pełni wciągającej rzeczywistości wirtualnej, z różnymi poziomami rzeczywistości rozszerzonej pośrodku.

Przykłady wciągających doświadczeń:

  • Niesamowite filmy 360°
  • tradycyjne filmy 2D (lub 3D) prezentowane w realistycznym otoczeniu;
  • Wizualizacje danych
  • Zakupy w domu
  • Sztuka
  • Coś fajnego, o czym jeszcze nikt nie pomyślał

Jak się tam dostać?

Wirtualna sieć jest dostępna od prawie roku w formie embrionalnej. Udało się to dzięki interfejsowi WebVR 1.1 API, który od wersji 62 Chrome jest dostępny w ramach testowania origin. Interfejs API jest też obsługiwany przez przeglądarki Firefox i Edge, a także przez polyfilla w Safari.

Ale czas przejść dalej.

Testowanie origin zakończyło się 24 lipca 2018 roku, a specyfikacja została zastąpiona przez interfejs WebXR Device API oraz nową wersję testowania origin.

Co się stało z WebVR 1.1?

Wiele nauczyliśmy się na podstawie WebVR 1.1, ale z czasem stało się jasne, że potrzebne są poważne zmiany, aby obsługiwać typy aplikacji, które chcą tworzyć deweloperzy. Pełna lista wyciągniętych wniosków jest zbyt długa, aby ją tu przedstawić. Obejmuje ona takie problemy, jak bezpośrednie powiązanie interfejsu API z głównym wątkiem JavaScriptu, zbyt wiele możliwości skonfigurowania ewidentnie niewłaściwych konfiguracji oraz typowe zastosowania, takie jak magiczne okno, to efekt uboczny, a nie celowa funkcja. (Magiczne okno to technika umożliwiająca wyświetlanie treści w trybie panoramicznym bez użycia zestawu słuchawkowego. Aplikacja renderuje jeden widok na podstawie czujnika orientacji urządzenia).

Nowy układ ułatwia wdrażanie i znacznie poprawia skuteczność. W tym samym czasie pojawiły się nowe przypadki użycia, takie jak rzeczywistość rozszerzona, i stało się ważne, aby interfejs API można było rozszerzać, aby obsługiwał je w przyszłości.

Interfejs WebXR Device API został zaprojektowany i nazwany z myślą o tych rozszerzonych przypadkach użycia oraz zapewnia lepszą drogę. Implementatorzy WebVR zobowiązali się do przeniesienia się na interfejs WebXR Device API.

Czym jest interfejs WebXR Device API?

Podobnie jak specyfikacja WebVR, interfejs WebXR Device API jest produktem grupy społecznościowej Immersive Web, w której skład wchodzą m.in. Google, Microsoft i Mozilla. „X” w XR oznacza pewien rodzaj zmiennej algebraicznej, która może oznaczać dowolne z doświadczeń w zakresie rzeczywistości rozszerzonej. Jest ona dostępna w wymienionej wcześniej wersji próbnej origin, a także za pomocą polyfill.

Gdy ten artykuł został pierwotnie opublikowany w okresie testów beta przeglądarki Chrome 67, włączone były tylko funkcje VR. Rzeczywistość rozszerzona pojawiła się w Chrome 69. Więcej informacji znajdziesz w artykule Rzeczywistość rozszerzona na potrzeby internetu.

Ten nowy interfejs API jest bardziej rozbudowany niż można to opisać w takim artykule. Chcę Ci przekazać wystarczającą ilość informacji, abyś mógł zacząć analizować próbki WebXR. Więcej informacji znajdziesz w pierwotnym objaśnieniu i naszym przewodniku dla użytkowników wczesnej wersji Immmersive Web Web Adopters Guide (w języku angielskim). W miarę trwania testu pochodzenia będę rozszerzać tę ostatnią grupę. Możesz zgłaszać problemy lub przesyłać żądania pull.

W tym artykule omówię rozpoczynanie, zatrzymywanie i uruchamianie sesji XR oraz podstawowe informacje o przetwarzaniu danych wejściowych.

Nie będę omawiać rysowania treści AR/VR na ekranie. Interfejs WebXR Device API nie udostępnia funkcji renderowania obrazu. Ty decydujesz. Rysowanie odbywa się przy użyciu interfejsów API WebGL. Możesz to zrobić, jeśli masz ambitne plany. Zalecamy jednak użycie frameworka. Przykłady aplikacji w rozszerzonej rzeczywistości wykorzystują jedną witrynę stworzoną specjalnie na potrzeby demonstracji o nazwie Cottontail. Three.js obsługuje WebXR od maja. Nie słyszałem nic o A-Frame.

Uruchamianie i uruchamianie aplikacji

Podstawowy proces wygląda tak:

  1. Poproś o urządzenie XR.
  2. Jeśli taka możliwość jest dostępna, poproś o sesję XR. Jeśli chcesz, aby użytkownik podłączył telefon do zestawu słuchawkowego, jest to sesja w trybie pełnoekranowym, do której można wejść za pomocą gestu.
  3. Użyj sesji do uruchomienia pętli renderowania, która zapewnia 60 ramek obrazu na sekundę. W każdym ujęciu wyświetlaj na ekranie odpowiednie treści.
  4. Wykonywanie pętli renderowania do momentu, gdy użytkownik zdecyduje się zamknąć aplikację.
  5. Zakończ sesję XR.

Przyjrzyjmy się temu zagadnieniu bardziej szczegółowo i zapoznajmy się z kodem. Nie będziesz mieć możliwości uruchomienia aplikacji, którą zaraz Ci pokażę. To tylko przykład.

Poproś o urządzenie XR

Tutaj zobaczysz standardowy kod wykrywania funkcji. Możesz to ująć w funkcję o nazwie np. checkForXR().

Jeśli nie korzystasz z sesji w trybie pełnoekranowym, możesz pominąć reklamowanie funkcji i uzyskiwanie gestów użytkownika, a następnie przejść bezpośrednio do żądania sesji. Sesja w pełni angażująca użytkownika to taka, która wymaga założenia słuchawek. W sesji niepełnej treści wyświetlają się tylko na ekranie urządzenia. Większość osób myśli o wirtualnej lub rozszerzonej rzeczywistości, gdy mówimy o pierwszej z nich. Ten ostatni jest czasami nazywany „magicznym oknem”.

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

Prośba o sesję XR

Mamy już urządzenie i gest użytkownika, czas więc na sesję. Aby utworzyć sesję, przeglądarka potrzebuje przestrzeni roboczej do rysowania.

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

Uruchamianie pętli renderowania

Kod potrzebny do wykonania tego kroku wymaga trochę pracy. Aby to wyjaśnić, powiem Ci kilka słów. Jeśli chcesz zobaczyć kod końcowy, przejdź do następnego kroku, aby go szybko sprawdzić, a potem wróć do tego artykułu, aby przeczytać pełne wyjaśnienie. Jest wiele rzeczy, których nie da się wywnioskować.

Podstawowy proces pętli renderowania wygląda tak:

  1. Żądanie ramki animacji.
  2. Zapytanie o pozycję urządzenia.
  3. Rysowanie treści w miejscu, w którym znajduje się urządzenie.
  4. Czynności związane z urządzeniami wejściowymi.
  5. Powtarzaj 60 razy na sekundę, aż użytkownik zdecyduje się zakończyć.

Żądanie ramki prezentacji

Słowo „ramka” ma w kontekście WebXR kilka znaczeń. Pierwszą z nich jest ramka odniesienia, która określa miejsce pochodzenia układu współrzędnych i co dzieje się z tym punktem początkowym, gdy urządzenie się porusza. Czy widok pozostaje taki sam, gdy użytkownik się porusza, czy zmienia się tak jak w rzeczywistości?

Drugim typem ramki jest ramka prezentacji reprezentowana przez obiekt XRFrame. Ten obiekt zawiera informacje potrzebne do renderowania pojedynczego obrazu sceny AR/VR na urządzeniu. To trochę mylące, ponieważ ramka prezentacji jest pobierana przez wywołanie metody requestAnimationFrame(). Dzięki temu jest ona zgodna z window.requestAnimationFrame().

Zanim podam Ci więcej informacji, pokażę Ci kod. Przykład poniżej pokazuje, jak uruchamia się i utrzymuje pętla renderowania. Zwróć uwagę na podwójne użycie ramki słów. Zwróć uwagę na rekurencyjne wywołanie funkcji requestAnimationFrame(). Ta funkcja będzie wywoływana 60 razy na sekundę.

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

Pozycje

Zanim rysujesz coś na ekranie, musisz wiedzieć, dokąd jest skierowany ekran, i musisz mieć dostęp do ekranu. Ogólnie pozycja i orientacja obiektu w AR/VR to postawa. Zarówno widzowie, jak i urządzenia wejściowe mają pozę. (Urządzenia wejściowe omówię później). Zarówno pozy widza, jak i urządzenia wejściowego są zdefiniowane jako macierz 4 × 4 przechowywana w kolumnie Float32Array w kolejności głównej. Aby uzyskać pozę widza, wywołaj funkcję XRFrame.getDevicePose() w ramach bieżącego obiektu ramki animacji. Zawsze sprawdzaj, czy otrzymasz odpowiedź. Jeśli coś pójdzie nie tak, nie chcesz rysować na ekranie.

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

Wyświetlenia

Po sprawdzeniu pozy czas na narysowanie czegoś. Obiekt, do którego rysujesz, nazywa się widokiem (XRView). Właśnie w tym miejscu staje się istotny typ sesji. Wyświetlenia są pobierane z obiektu XRFrame jako tablica. Jeśli jesteś w sesji nie-immersyjnej, tablica ma jeden widok. Jeśli korzystasz z sesji w trybie immersyjnym, tablica ma 2 elementy – po jednym dla każdego oka.

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

To ważna różnica między systemem WebXR a innymi systemami immersyjnymi. Choć może się wydawać bezcelowe, że powtarzanie go za pomocą jednego widoku może wydawać się bezcelowe, pozwala to korzystać z jednej ścieżki renderowania na różne urządzenia.

Cała pętla renderowania.

Po połączeniu tych wszystkich elementów otrzymuję kod widoczny poniżej. W przypadku urządzeń wejściowych pozostawiłem miejsce na zastąpienie ich w późniejszej sekcji.

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

Zakończ sesję XR

Sesja XR może się zakończyć z różnych powodów, m.in. przez wywołanie funkcji XRSession.end() w Twoim kodzie. Inne przyczyny to odłączanie zestawu słuchawkowego lub inna aplikacja przejmująca kontrolę nad nim. Dlatego dobrze działająca aplikacja powinna monitorować zdarzenie końcowe, a gdy do niego dojdzie, odrzucać obiekty sesji i mechanizmu renderowania. Zakończonej sesji XR nie można wznowić.

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

Jak działa interakcja?

Podobnie jak w przypadku czasu trwania aplikacji, pokażę Ci tylko, jak można wchodzić w interakcje z obiektami w rzeczywistości rozszerzonej lub wirtualnej.

Interfejs WebXR Device API stosuje podejście „wskaż i kliknij” do danych wejściowych użytkownika. W ramach tego podejścia każde źródło danych ma zdefiniowany promień wskaźnika, który wskazuje, na co wskazuje urządzenie wejściowe, oraz zdarzenia wskazujące, kiedy coś zostało wybrane. Aplikacja przyciąga promień wskaźnika i pokazuje, gdzie jest skierowany. Gdy użytkownik kliknie urządzenie wejściowe, uruchomione są zdarzenia, w szczególności select, selectStart i selectEnd. Aplikacja określa, co zostało kliknięte, i odpowiednio na to reaguje.

Urządzenie wejściowe i promień wskaźnika

Dla użytkowników promienie kursora to tylko słaba linia między kontrolerem a tym, na co użytkownik wskazuje. Aplikacja musi jednak ją narysować. Oznacza to, że musisz określić pozycję urządzenia wejściowego i narysować linię od jego lokalizacji do obiektu w przestrzeni AR/VR. Proces ten wygląda mniej więcej tak:

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

To jest okrojona wersja przykładu śledzenia danych wejściowych z Immersive Web Community Group. Podobnie jak w przypadku renderowania klatek, rysowanie promienia kursora i urządzenia zależy od Ciebie. Jak już wspomnieliśmy, ten kod musi być wykonywany w ramach pętli renderowania.

Wybieranie elementów w wirtualnym środowisku

Wskazywanie rzeczy w AR/VR jest dość bezużyteczne. Aby robić coś przydatnego, użytkownicy muszą mieć możliwość wyboru. Interfejs WebXR Device API udostępnia 3 zdarzenia, które umożliwiają reagowanie na interakcje użytkownika: select, selectStartselectEnd. Jest to nieoczekiwana osobliwość: aplikacja informuje tylko, że kliknięto urządzenie wejściowe. Nie wskazują, który element w otoczeniu został kliknięty. Moduły obsługi zdarzeń są dodawane do obiektu XRSession i należy je dodać, gdy tylko będzie dostępne.

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

Ten kod jest oparty na przykładzie funkcji Input Selection, jeśli chcesz uzyskać więcej informacji.

Aby dowiedzieć się, co zostało kliknięte, musisz użyć pozycji. (Zaskoczony? Nie sądzę.) Szczegóły są specyficzne dla Twojej aplikacji lub używanego przez Ciebie frameworku i poza zakresem tego artykułu. Metoda Cottontail jest opisana w sekcji Wybór danych wejściowych.

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

Wnioski i perspektywy

Jak już wspomniałem, rzeczywistość rozszerzona ma zostać udostępniona w Chrome 69 (w wersji Canary w czerwcu 2018 r.). Zachęcam jednak do wypróbowania tego, co mamy do tej pory. Potrzebujemy opinii, aby go ulepszyć. Aby śledzić postępy, odwiedź stronę ChromeStatus.com i sprawdź WebXR HitTest. Możesz też śledzić ankiety WebXR, co poprawi śledzenie postawy.