La realtà virtuale arriva sul Web

Ecco alcuni concetti di base per prepararti a una varietà di esperienze immersive: realtà virtuale, realtà aumentata e molto altro ancora.

Joe Medley
Joe Medley

Le esperienze immersive sono apparse sul web con Chrome 79. L'API WebXR Device introduce la realtà virtuale come realtà virtuale, mentre il supporto per la realtà aumentata arriva in Chrome 81. Mentre un aggiornamento dell'API GamePad estende l'uso avanzato dei controlli alla VR. A breve altri browser supporteranno queste specifiche, tra cui Firefox Reality, Oculus Browser, Edge e il browser Helio di Magic Leap, tra gli altri.

Questo articolo inizia una serie sul web immersivo. Questa parte descrive la configurazione di un'applicazione WebXR di base e l'accesso e l'uscita da una sessione XR. Gli articoli successivi tratteranno il loop dei frame (il cavallo di battaglia dell'esperienza WebXR), le specifiche della realtà aumentata e l'API WebXR Hit Test, un mezzo di rilevamento delle superfici in una sessione AR. Se non diversamente indicato, tutto ciò che tratterò in questo articolo e negli articoli successivi si applica sia all'AR che alla VR.

Che cos'è il web immersivo?

Sebbene vengano utilizzati due termini per descrivere esperienze immersive, realtà aumentata e realtà virtuale, molti pensano a queste esperienze, che vanno dalla realtà completa a completamente virtuale, con vari gradi di immersività intermedie. La "X" in XR ha lo scopo di riflettere questo pensiero, in quanto è una sorta di variabile algebrica che rappresenta qualsiasi cosa nello spettro delle esperienze immersive.

Un grafico che illustra lo spettro delle esperienze visive, dalla realtà completa a quella completamente immersiva.
Lo spettro delle esperienze immersive

Esempi di esperienze immersive includono:

  • Giochi
  • Video a 360°
  • Video tradizionali in 2D (o 3D) presentati in un ambiente immersivo.
  • Acquisto di case
  • Visualizzare i prodotti in casa prima dell'acquisto
  • Arte immersiva
  • Qualcosa di interessante a cui non ha ancora pensato nessuno

Concetti e utilizzo

Ti spiegherò alcune nozioni di base sull'utilizzo dell'API WebXR Device. Se hai bisogno di informazioni più approfondite di quanto ti ho fornito, dai un'occhiata agli esempi di WebXR di Immersive Web Working Group o ai materiali di riferimento in crescita di MDN. Se hai familiarità con le prime versioni dell'API WebXR Device, dovresti dare un'occhiata a tutto questo materiale. Sono state apportate modifiche.

Il codice in questo articolo si basa sull'esempio essenziale di Immersive Web Working Group (demo, fonte), ma è modificato per chiarezza e semplicità.

Parte della creazione della specifica WebXR è stata arricchita con misure di sicurezza e privacy per proteggere gli utenti. Di conseguenza, le implementazioni devono soddisfare determinati requisiti. Una pagina web o un'app deve essere attiva e attiva prima di poter richiedere qualcosa di sensibile allo spettatore. Le pagine web o le app devono essere pubblicate tramite HTTPS. L'API è progettata per proteggere le informazioni ottenute da sensori e fotocamere, di cui ha bisogno per il funzionamento.

Richiedi una sessione

Per accedere a una sessione XR è necessario un gesto dell'utente. A tale scopo, utilizza il rilevamento delle funzionalità per testare XRSystem (tramite navigator.xr) ed effettua una chiamata al numero XRSystem.isSessionSupported(). Tieni presente che nelle versioni 79 e 80 di Chrome l'oggetto XRSystem era chiamato XR.

Nell'esempio seguente, ho indicato di voler una sessione di realtà virtuale con il tipo di sessione 'immersive-vr'. Gli altri tipi di sessioni sono 'immersive-ar' e 'inline'. Una sessione in linea consente di presentare contenuti in HTML e viene usata principalmente per i contenuti teaser. Lo dimostra il esempio di sessione AR immersiva. Lo spiegherò in un altro articolo.

Quando ho capito che le sessioni di realtà virtuale sono supportate, abilito un pulsante che mi consente di acquisire un gesto dell'utente.

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  if (supported) {
    xrButton.addEventListener('click', onButtonClicked);
    xrButton.textContent = 'Enter VR';
    xrButton.enabled = supported; // supported is Boolean
  }
}

Dopo aver attivato il pulsante, attendo un evento di clic e poi chiedo una sessione.

let xrSession = null;
function onButtonClicked() {
  if (!xrSession) {
    navigator.xr.requestSession('immersive-vr')
    .then((session) => {
      xrSession = session;
      xrButton.textContent = 'Exit XR';
      onSessionStarted(xrSession);
    });
  } else {
    xrSession.end();
  }
}

Osserva la gerarchia degli oggetti in questo codice. Si sposta da navigator a xr in un'istanza XRSession. Nelle prime versioni dell'API, uno script doveva richiedere un dispositivo prima di richiedere una sessione. Ora il dispositivo viene acquisito in modo implicito.

Inserisci una sessione

Dopo aver ottenuto una sessione, devo avviarla e inserirla. Ma prima devo configurare alcune cose. Una sessione richiede un gestore di eventi onend affinché l'app o la pagina web possa essere reimpostata all'uscita dell'utente.

Avrò anche bisogno di un elemento <canvas> su cui disegnare la scena. Deve essere un WebGLRenderingContext o WebGL2RenderingContext compatibile con XR. Tutti i disegni vengono eseguiti utilizzandoli o un framework basato su WebGL come Three.js.

Ora che ho un luogo da disegnare, ho bisogno di una fonte di contenuti su cui attingere. Per farlo, creo un'istanza di XRWebGLLayer. Lo associo alla tela chiamando XRSession.updateRenderState().

Durante una sessione, ho bisogno di un modo per determinare dove si trovano le cose nella realtà virtuale. Mi serve uno spazio di riferimento. Uno spazio di riferimento 'local-floor' è quello in cui l'origine si trova vicino al visualizzatore e l'asse y è 0 a livello del piano e non è previsto che si sposti. Esistono altri tipi di spazi di riferimento, ma si tratta di un argomento più complicato di quanto non possa approfondire qui. Salvo lo spazio di riferimento in una variabile perché ne ho bisogno quando cerco sullo schermo.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  let canvas = document.createElement('canvas');
  webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
  });

  xrSession.requestReferenceSpace('local-floor')
  .then((refSpace) => {
    xrRefSpace = refSpace;
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

Dopo aver ottenuto uno spazio di riferimento, chiamo XRSession.requestAnimationFrame(). Questo è l'inizio della presentazione di contenuti virtuali, che avviene nel loop di frame.

Esegui un loop di frame

Il loop di frame è un loop infinito controllato da user agent in cui il contenuto viene ripetutamente attirato sullo schermo. I contenuti vengono tracciati in blocchi discreti chiamati frame. La successione di fotogrammi crea l'illusione di movimento. Per le applicazioni VR, i frame al secondo possono essere compresi tra 60 e 144. AR per Android viene eseguita a 30 frame al secondo. Il tuo codice non deve assumere una frequenza fotogrammi particolare.

La procedura di base per il loop di frame è la seguente:

  1. Chiama XRSession.requestAnimationFrame(). In risposta, lo user agent richiama XRFrameRequestCallback, che è definito da te.
  2. All'interno della funzione di callback:
    1. Chiama di nuovo XRSession.requestAnimationFrame().
    2. Scegli la posa dello spettatore.
    3. Supera ('bind') il WebGLFramebuffer dal XRWebGLLayer al WebGLRenderingContext.
    4. Esegui l'iterazione su ogni oggetto XRView, recuperando il relativo XRViewport da XRWebGLLayer e passandolo a WebGLRenderingContext.
    5. Disegna qualcosa sul framebuffer.

La parte restante di questo articolo descrive il passaggio 1 e parte del passaggio 2, relativo alla configurazione e alla chiamata di XRFrameRequestCallback. Gli altri punti del passaggio 2 sono trattati nella Parte II.

Callback XRFrameRequest

XRFrameRequestCallback è definito da te. Prevede due parametri: un'istanza DOMHighResTimeStamp e un'istanza XRFrame. L'oggetto XRFrame fornisce le informazioni necessarie per il rendering di un singolo frame sul display. L'argomento DOMHighResTimeStamp è per uso futuro.

Prima di fare qualsiasi altra cosa, richiederò il frame dell'animazione successivo. Come indicato in precedenza, la tempistica dei frame è determinata dallo user agent in base all'hardware sottostante. Richiedere prima il frame successivo garantisce che il loop di frame continui se qualcosa durante il callback genera un errore.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  // Render a frame.
}

A questo punto, è il momento di disegnare qualcosa per lo spettatore. Questa è una discussione per la parte II. Prima di andarci, ti mostro come terminare una sessione.

Terminare la sessione

Una sessione immersiva può terminare per diversi motivi, ad esempio per terminare con il tuo codice tramite una chiamata al numero XRSession.end(). Altre cause sono lo scollegamento delle cuffie o un'altra applicazione che ne prende il controllo. Ecco perché un'applicazione che funziona bene dovrebbe monitorare l'evento end. In questo caso, ignora la sessione e gli oggetti di rendering correlati. Impossibile riprendere una sessione immersiva terminata. Per accedere nuovamente all'esperienza immersiva, la mia app deve avviare una nuova sessione.

Come detto in Accesso in una sessione, ho aggiunto un gestore di eventi onend durante la configurazione.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);
  // More setup…
}

All'interno del gestore di eventi, ripristina lo stato dell'app prima che l'utente entrasse in una sessione.

function onSessionEnded(event) {
  xrSession = null;
  xrButton.textContent = 'Enter VR';
}

Conclusione

Non ho spiegato tutto il necessario per scrivere un'applicazione Web XR o AR. Spero di averti dato abbastanza per iniziare a comprendere il codice e a sperimentare. Nel prossimo articolo illustrerò il loop di frame, ovvero il punto in cui i contenuti vengono attirati sullo schermo.

Foto di JESHOOTS.COM su Unsplash