La realtà virtuale arriva sul Web

Ecco alcune nozioni di base per prepararti a un ampio spettro di esperienze immersive: realtà virtuale, realtà aumentata e tutto ciò che c'è in mezzo.

Joe Medley
Joe Medley

Le esperienze immersive sono arrivate sul web in Chrome 79. L'API WebXR Device consente di usufruire della realtà virtuale, mentre il supporto della realtà aumentata è disponibile in Chrome 81. mentre un aggiornamento dell'API GamePad estende l'uso avanzato dei controlli alla VR. A breve anche altri browser supporteranno queste specifiche, tra cui Firefox Reality, Oculus Browser, il browser Helio di Edge e Magic Leap.

Questo articolo inaugura una serie sul web immersivo. Questa puntata illustra come configurare un'applicazione WebXR di base, nonché come accedere e uscire da una sessione XR. Gli articoli successivi riguarderanno il loop dei frame (la base dell'esperienza WebXR), le specifiche della realtà aumentata e l'API WebXR Hit Test, un mezzo per rilevare le superfici in una sessione AR. Se non diversamente indicato, tutto ciò che tratto in questo e negli articoli successivi si applica allo stesso modo sia all'AR che alla VR.

Che cos'è il web immersivo?

Anche se usiamo due termini per descrivere le esperienze immersive, realtà aumentata e realtà virtuale, molti le considerano in uno spettro che spazia dalla realtà completa a quella completamente virtuale, con vari gradi di immersione. La "X" in VR è pensata per 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 alla completamente immersiva.
Lo spettro delle esperienze immersive

Ecco alcuni esempi di esperienze immersive:

  • Videogiochi
  • Video a 360°
  • Video tradizionali 2D (o 3D) presentati in ambienti immersivi
  • Acquisto di una casa
  • Visualizzare i prodotti a casa prima di acquistarli
  • Arte immersiva
  • Qualcosa di interessante a cui nessuno ha ancora pensato

Concetti e utilizzo

Ti spiegherò alcune nozioni di base sull'utilizzo dell'API WebXR Device. Se hai bisogno di una maggiore profondità rispetto a quella fornita da me, dai un'occhiata agli esempi di WebXR di Immersive Web Working Group o ai materiali di riferimento in crescita di MDN. Se hai dimestichezza con le versioni precedenti dell'API WebXR Device, ti consigliamo di dare un'occhiata a tutto questo materiale. Sono state apportate modifiche.

Il codice in questo articolo si basa sull'esempio di base del gruppo di lavoro Immersive Web (demo, source), ma è modificato per chiarezza e semplicità.

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

Richiedere una sessione

Per accedere a una sessione XR è necessario un gesto dell'utente. Per farlo, utilizza il rilevamento delle funzionalità per verificare la presenza di XRSystem (tramite navigator.xr) ed effettua una chiamata a XRSystem.isSessionSupported(). Tieni presente che nelle versioni 79 e 80 di Chrome l'oggetto XRSystem si chiamava XR.

Nell'esempio seguente, ho indicato che voglio una sessione di realtà virtuale con il tipo di sessione 'immersive-vr'. Gli altri tipi di sessione sono 'immersive-ar' e 'inline'. Una sessione in linea è destinata alla presentazione di contenuti all'interno di HTML e viene utilizzata principalmente per i contenuti teaser. L'esempio della sessione AR immersiva lo dimostra. Lo spiegherò in un articolo successivo.

Una volta che so che le sessioni di realtà virtuale sono supportate, attivo 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 richiedo 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();
  }
}

Tieni presente la gerarchia degli oggetti in questo codice. Passa da navigator a xr a un'istanza XRSession. Nelle prime versioni dell'API, uno script doveva richiedere un dispositivo prima di richiedere una sessione. Ora il dispositivo viene acquisito implicitamente.

Accedere a una sessione

Dopo aver ottenuto una sessione, devo avviarla ed entrarci. Prima, però, devo configurare alcune cose. Una sessione ha bisogno di un gestore eventi onend per poter reimpostare l'app o la pagina web quando l'utente esce.

Mi servirà anche un elemento <canvas> su cui disegnare la scena. Deve essere un WebGLRenderingContext o WebGL2RenderingContext compatibile con XR. Tutto il disegno viene eseguito utilizzando questi elementi o un framework basato su WebGL come Three.js.

Ora che ho un posto dove disegnare, mi serve una fonte di contenuti da cui attingere. Per farlo, creo un'istanza di XRWebGLLayer. Lo associo al canvas chiamando XRSession.updateRenderState().

Una volta avviata la sessione, ho bisogno di un modo per determinare dove si trovano gli oggetti nella realtà virtuale. Mi serve uno spazio di riferimento. Uno spazio di riferimento 'local-floor' è uno in cui l'origine si trova vicino allo spettatore, l'asse y è 0 al livello del pavimento e non dovrebbe muoversi. Esistono altri tipi di spazi di riferimento, ma si tratta di un argomento più complicato di quanto non possa essere trattato qui. Salvo lo spazio di riferimento in una variabile perché mi servirà quando disegno 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 del frame.

Esegui un ciclo di frame

Il loop del frame è un loop infinito controllato dallo user agent in cui i contenuti vengono ripetutamente riportati sullo schermo. I contenuti vengono disegnati in blocchi distinti chiamati frame. La successione di frame crea l'illusione del movimento. Per le applicazioni VR, i frame al secondo possono essere compresi tra 60 e 144. La realtà aumentata per Android viene eseguita a 30 fotogrammi al secondo. Il codice non deve presupporre alcuna frequenza di frame.

La procedura di base per il loop del frame è:

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

La parte restante di questo articolo descrive il passaggio 1 e parte del passaggio 2, ovvero la configurazione e la chiamata di XRFrameRequestCallback. Gli elementi rimanenti del passaggio 2 sono trattati nella parte II.

XRFrameRequestCallback

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

Prima di fare qualsiasi altra cosa, richiede il frame di animazione successivo. Come affermato in precedenza, la temporizzazione dei frame è determinata dall'agente utente in base all'hardware sottostante. Richiedere prima il frame successivo garantisce che il loop del 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. Questo è un argomento per la parte II. Prima di andare lì, ti mostro come terminare una sessione.

Termina la sessione

Una sessione immersiva può terminare per diversi motivi, tra cui la fine con il tuo codice tramite una chiamata al numero XRSession.end(). Altre cause includono la disconnessione delle cuffie o un'altra applicazione che ne prende il controllo. Ecco perché un'applicazione di buon comportamento deve monitorare l'evento end. In questo caso, elimina la sessione e gli oggetti di rendering correlati. Una sessione immersiva terminata non può essere ripresa. Per rientrare nell'esperienza immersiva, la mia app deve avviare una nuova sessione.

Come ricorderai da Ho inserito una sessione, durante la configurazione ho aggiunto un gestore di eventi onend.

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

All'interno del gestore eventi, ripristina lo stato dell'app prima che l'utente abbia avviato una sessione.

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

Conclusione

Non ti ho spiegato tutto ciò che ti serve per scrivere un'applicazione Web XR o AR. Spero di averti fornito informazioni sufficienti per iniziare a comprendere il codice e per iniziare a fare esperimenti. Nel prossimo articolo spiegherò il loop dell'inquadratura, ovvero il momento in cui i contenuti vengono visualizzati sullo schermo.

Foto di JESHOOTS.COM su Unsplash