Witamy w rzeczywistości wirtualnej

Internet to wirtualny świat dostępny w przeglądarce. Wszystkie doświadczenia rzeczywistości wirtualnej dostępne w przeglądarce lub goglach z obsługą VR.

Joe Medley
Joe Medley

Internet wirtualny toczy się w wirtualnym świecie hostowanym w przeglądarce. Obejmuje to całe doznania rzeczywistości wirtualnej (VR) oferowane w przeglądarce lub w zestawach słuchawkowych Google z obsługą rzeczywistości wirtualnej, np. Google Daydream, Oculus Rift, Samsung Gear VR, HTC Vive i zestawy słuchawkowe z systemem Windows, oraz zestawy słuchawkowe mieszanej rzeczywistości z systemem Windows, opracowane na urządzenia mobilne z obsługą AR.

Choć do opisywania wrażeń angażujących używamy 2 terminów, należy je traktować jako spektrum od pełnej rzeczywistości po całkowicie wciągające środowisko VR, z różnymi poziomami AR.

Przykłady doświadczeń immersyjnych to:

  • Niesamowite filmy 360°
  • tradycyjne filmy 2D (lub 3D) prezentowane w rzeczywistym otoczeniu;
  • Wizualizacje danych
  • Zakupy domowe
  • Sztuka
  • Czego jeszcze nikt nie pomyślał

Jak się tam dostać?

Internet jest dostępny od niemal roku w formie embrionalnej. Zrobiliśmy to za pomocą interfejsu WebVR 1.1 API, który jest dostępny w okresie próbnym od Chrome 62. Ten interfejs API jest też obsługiwany przez przeglądarki Firefox i Edge, a w przeglądarce Safari także kod polyfill.

Czas przejść dalej.

Testowanie origin zakończyło się 24 lipca 2018 r. Specyfikacja została zastąpiona przez WebXR Device API i nową wersję próbną origin.

Co się stało z WebVR 1.1?

Wiele się dowiedzieliśmy o WebVR 1.1, ale z czasem stało się jasne, że trzeba wprowadzić kilka istotnych zmian, aby można było tworzyć konkretne typy aplikacji, które chcą tworzyć. Pełna lista zdobytych informacji jest za długa, aby ją tu opisywać. Obejmuje ona jednak takie kwestie jak wyraźny związek interfejsu API z głównym wątkiem JavaScriptu, zbyt wiele możliwości skonfigurowania wyraźnie błędnych konfiguracji dla programistów oraz typowe zastosowania, np. magiczne okno jako efekt uboczny, a nie celową funkcję. (Magiczne okno to technika oglądania wciągających treści bez gogli, w której aplikacja renderuje pojedynczy widok na podstawie czujnika orientacji urządzenia).

Nowy wygląd ułatwia implementację i znacznie poprawia wydajność. Jednocześnie pojawiły się nowe przypadki użycia, w tym AR i dlatego zaistniało ważne, aby interfejs API był rozszerzalny, 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 i zapewnia lepszą drogę naprzód. Użytkownicy korzystający z WebVR zobowiązali się do przejścia na interfejs WebXR Device API.

Co to jest WebXR Device API?

Podobnie jak poprzednia specyfikacja WebVR, interfejs WebXR Device API jest usługą należącą do Immersive Web Community Group, do której należą m.in. Google, Microsoft, Mozilla i inne firmy. „X w XR” to zmienna algebraiczna, która reprezentuje wszystko w spektrum doświadczeń immersyjnych. Jest dostępny we wspomnianym wcześniej okresie próbnym źródła oraz za pomocą polyfill.

Podczas publikacji tego artykułu w okresie testów beta Chrome 67 włączone były tylko funkcje rzeczywistości wirtualnej. Rzeczywistość rozszerzona jest już dostępna w Chrome 69. Więcej informacji na ten temat można znaleźć w artykule Rzeczywistość rozszerzona w internecie.

W nowym interfejsie API nie mogę znaleźć informacji, które opisaliśmy w tym artykule. Chcę Ci przekazać wystarczająco dużo, by zacząć analizować próbki z WebXR. Więcej informacji znajdziesz w pierwotnej instrukcji oraz w przewodniku dla użytkowników wczesnej wersji Immersive Web. Wraz z postępem testowania origin rozwijam tę drugą część. Możesz zgłaszać problemy lub przesyłać prośby „push”.

W tym artykule omówię uruchamianie, zatrzymywanie i uruchamianie sesji XR, a także podstawowe informacje o przetwarzaniu danych wejściowych.

Nie będę omawiać sposobu umieszczania na ekranie treści AR/VR. Interfejs WebXR Device API nie udostępnia funkcji renderowania obrazów. To zależy od Ciebie. Rysowanie odbywa się za pomocą interfejsów API WebGL. Możesz to osiągnąć, jeśli masz ambitne cele. Zalecamy jednak korzystanie z platformy. Wykorzystują one model Cottontail, który został utworzony na potrzeby prezentacji. Three.js obsługuje WebXR od maja. Nie słyszałem nic o A-Frame.

Uruchamianie i uruchamianie aplikacji

Podstawowy proces ten wygląda tak:

  1. Poproś o urządzenie XR.
  2. Jeśli jest dostępna, poproś o sesję XR. Jeśli chcesz, aby użytkownik wkładał telefon w zestaw słuchawkowy, nazywamy to sesją immersyjnego, w której użytkownik musi wykonać gest.
  3. Użyj sesji, by uruchomić pętlę renderowania obejmującą 60 klatek na sekundę. W każdej klatce rysuj odpowiednią treść na ekranie.
  4. Uruchom pętlę renderowania, dopóki użytkownik nie zdecyduje się na jej zamknięcie.
  5. Zakończ sesję XR.

Przyjrzyjmy się temu nieco bardziej szczegółowo i dodajmy kod. Nie będzie można uruchomić aplikacji z tego, co za chwilę Ci pokażę. Trzeba to jednak podkreślić, aby pokazać te zjawiska.

Prośba o urządzenie XR

Tutaj możesz rozpoznać standardowy kod wykrywania cech. Możesz go umieścić w funkcji podobnej do checkForXR().

Jeśli nie korzystasz z sesji interaktywnej, możesz pominąć reklamowanie funkcji i wykonywać gest użytkownika, a od razu przejść do żądania sesji. Sesja wciągająca to taka, która wymaga zestawu słuchawkowego. Sesja nie jest wciągająca, czyli po prostu wyświetla treść na ekranie urządzenia. Pierwszy z nich jest czymś, co większość ludzi myśli, kiedy odnosi się do rzeczywistości wirtualnej. To ostatnie jest czasem nazywane „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.");
}

Poproś o sesję XR

Skoro znamy już urządzenie i gest użytkownika, czas na sesję. Aby utworzyć sesję, przeglądarka potrzebuje obszaru roboczego, w którym będzie rysowana.

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

Uruchom pętlę renderowania

Kod tego kroku wymaga nieco pracy z kodem. Aby rozwiązać ten problem, rzucę Ci masę słów. Jeśli chcesz zobaczyć ostateczny kod, przejdź tutaj, a potem wróć, aby zobaczyć wszystkie szczegóły. Zdecydowanie nie wszystko jest w stanie wywnioskować.

Podstawowy proces pętli renderowania wygląda tak:

  1. Żądanie klatki animacji.
  2. Zapytanie o pozycję urządzenia.
  3. Narysuj treść w zależności od pozycji urządzenia.
  4. Wykonaj wymagane czynności w przypadku urządzeń wejściowych.
  5. Powtarzaj te czynności 60 razy na sekundę, aż użytkownik zdecyduje się na zakończenie.

Wysyłanie prośby o ramkę prezentacji

Słowo „ramka” ma kilka znaczeń w kontekście Web XR. Pierwsza to rama odniesienia, która określa, skąd ustalany jest początek układu współrzędnych oraz co dzieje się z tym punktem początkowym podczas przesuwania urządzenia. (Czy widok pozostaje taki sam, gdy użytkownik się rusza, czy zmienia się, jak w rzeczywistości?)

Drugim typem ramki jest ramka prezentacji, reprezentowana przez obiekt XRFrame. Ten obiekt zawiera informacje potrzebne do wyrenderowania na urządzeniu pojedynczej klatki sceny AR/VR. Jest to trochę mylące, ponieważ ramka prezentacji jest pobierana przez wywołanie requestAnimationFrame(). Dzięki temu jest ona zgodna z usługą window.requestAnimationFrame().

Zanim przejdziemy dalej, przekażę Ci kod. Przykład poniżej pokazuje, jak uruchamia się i utrzymuje pętlę renderowania. Zwróćcie uwagę na podwójne zastosowanie ramki słowa. Zwróć uwagę na wywołanie cykliczne do 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 zaczniesz coś narysować na ekranie, musisz wiedzieć, w którą stronę wskazuje wyświetlacz i potrzebujesz dostępu do ekranu. Pozycja i orientacja przedmiotu w rzeczywistości rozszerzonej i rzeczywistości wirtualnej nazywa się pozycją. Zarówno gogle, jak i urządzenia wejściowe znajdują się w odpowiedniej pozycji. (Urządzenia wejściowe omówię później). Pozycje przeglądającego i urządzenia wejściowego są zdefiniowane jako macierz 4 na 4 zapisane w Float32Array w dużej kolejności w kolumnie. Pozycja widza jest ustalana w pozycji użytkownika, wywołując XRFrame.getDevicePose() w bieżącym obiekcie klatki animacji. Zawsze sprawdzaj, czy udało Ci się ustalić pozycję. Jeśli coś poszło nie tak, nie chcesz już rysować na ekranie.

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

Widoki

Po sprawdzeniu pozycji czas coś narysować. Obiekt, do którego rysujesz, nazywany jest widokiem (XRView). W tym przypadku ważny jest typ sesji. Widoki są pobierane z obiektu XRFrame w postaci tablicy. Jeśli nie korzystasz z sesji niepełnej, tablica ma jeden widok. Jeśli uczestniczymy w sesji interaktywnej, tablica zawiera 2 elementy, po jednym dla każdego oka.

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

Jest to ważna różnica między WebXR a innymi systemami realistycznymi. Chociaż powtarzanie tego samego widoku w jednym widoku może wydawać się bezsensowne, taki sposób pozwala uzyskać 1 ścieżkę renderowania dla różnych urządzeń.

Cała pętla renderowania

Jeśli to wszystko połączę, uzyskam kod poniżej. Zostawiłem obiekt zastępczy urządzeń wejściowych, który omówię w dalszej części.

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 zakończyć się z kilku powodów, np. przez wywołanie Twojego kodu przez wywołanie XRSession.end(). Inne przyczyny to odłączenie zestawu lub inna aplikacja przejmująca nad nim kontrolę. W związku z tym w dobrej aplikacji powinna monitorować zdarzenie końcowe, a gdy zaistnieć, 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?

Tak jak w przypadku fazy eksploatacji aplikacji, przekazuję Wam tylko przedsmak interakcji z obiektami w AR lub VR.

Interfejs WebXR Device API przyjmuje dane wejściowe użytkownika metodą „wskaż i kliknij”. W ramach tego podejścia każde źródło danych wejściowych ma zdefiniowany promień wskaźnika, który wskazuje, gdzie wskazuje urządzenie wejściowe, oraz zdarzenia sygnalizujące, kiedy coś zostało wybrane. Aplikacja rysuje promień i pokazuje, w jaki sposób jest on skierowany. Gdy użytkownik kliknie urządzenie wejściowe, wywoływane są zdarzenia, w szczególności select, selectStart i selectEnd. Aplikacja określa, co zostało kliknięte, i odpowiednio reaguje.

Urządzenie wejściowe i promień wskazujący

Dla użytkowników promień wskaźnika to po prostu cienka linia między kontrolerem a obiektem, na który kierują urządzenie. Ale aplikacja musi to przedstawiać. Chodzi o ustalenie pozycji urządzenia wejściowego i rysowanie linii 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 skrócona wersja przykładu śledzenia danych wejściowych z grupy Immersive Web Community Group. Tak jak w przypadku renderowania ramek, ciągniemy promienię, a urządzenie stoi przed Tobą. Jak już wspomnieliśmy, kod ten musi być uruchamiany w ramach pętli renderowania.

Wybieranie elementów w przestrzeni wirtualnej

Samo wskazywanie obiektów w rzeczywistości rozszerzonej lub wirtualnej jest całkowicie bezużyteczne. Aby można było wykonywać działania, użytkownicy muszą mieć możliwość zaznaczania różnych elementów. Interfejs WebXR Device API udostępnia 3 zdarzenia reagowania na interakcje użytkowników: select, selectStart i selectEnd. Jest dziwna, nie spodziewała się, że informuje tylko o kliknięciu urządzenia wejściowego. Nie informują one, który element w środowisku został kliknięty. Moduły obsługi zdarzeń są dodawane do obiektu XRSession i powinny być dodane, gdy tylko są 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 wyboru danych wejściowych na wypadek, gdyby potrzebowali Państwo więcej informacji.

Aby dowiedzieć się, co zostało kliknięte, użyj ujęcia. (Jesteście zaskoczeni? Nie sądzę). Te szczegółowe informacje są specyficzne dla aplikacji lub platformy, z której korzystasz i dlatego nie są uwzględnione w tym artykule. Jej podejście jest przykładem wyboru 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.
    }
}

Wniosek: spojrzenie w przyszłość

Jak już wspomnieliśmy, rzeczywistość rozszerzona będzie dostępna w Chrome 69 (niekiedy w wersji Canary – w czerwcu 2018 r.). Mimo to zachęcamy do wypróbowania tego, co już udało nam się osiągnąć. Potrzebujemy opinii, aby ulepszyć tę usługę. Śledź postępy na stronie ChromeStatus.com na stronie WebXR Hit Test. Możesz też skorzystać z kotwic z WebXR, które poprawią śledzenie pozycji.