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 offre la realtà virtuale, mentre il supporto della realtà aumentata è disponibile in Chrome 81. Un aggiornamento dell'API GamePad estende l'uso avanzato dei controlli alla realtà virtuale. A breve altre specifiche saranno supportate da altri browser, tra cui Firefox Reality, Oculus Browser, Edge e il browser Helio di 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 del 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?

Sebbene utilizziamo due termini per descrivere le esperienze immersive, la realtà virtuale e la realtà aumentata, molti le considerano parte di uno spettro che va dalla realtà completa a quella completamente virtuale, con gradi di immersione intermedi. 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 a quella completamente immersiva.
Lo spettro delle esperienze immersive

Ecco alcuni esempi di esperienze immersive:

  • Videogiochi
  • Video a 360°
  • Video 2D (o 3D) tradizionali 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 maggiori dettagli rispetto a quanto fornito, consulta i sample WebXR del gruppo di lavoro Immersive Web o i materiali di riferimento in crescita di MDN. Se hai dimestichezza con le versioni precedenti dell'API WebXR Device, consulta 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à.

La creazione della specifica WebXR ha comportato lo sviluppo di 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 attivata prima di poter richiedere all'utente informazioni sensibili. 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 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 di 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 a 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 dei contenuti virtuali, che viene eseguita nel loop delle cornici.

Esegui un ciclo di frame

Il loop del frame è un loop infinito controllato dall'user-agent in cui i contenuti vengono disegnati ripetutamente sullo schermo. I contenuti vengono disegnati in blocchi distinti chiamati frame. La successione di frame crea l'illusione del movimento. Per le applicazioni VR, il numero di frame al secondo può variare da 60 a 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 dei frame è la seguente:

  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. Fai in modo che lo spettatore si metta in posa.
    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 è da utilizzare in futuro.

Prima di fare qualsiasi altra cosa, chiederò il frame dell'animazione successivo. Come affermato in precedenza, la temporizzazione dei frame è determinata dall'agente utente in base all'hardware sottostante. Se richiedi prima il frame successivo, il loop dei frame continua se si verifica un errore durante il callback.

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, ad esempio tramite il tuo codice tramite una chiamata a XRSession.end(). Altre cause sono la disconnessione delle cuffie o il controllo da parte di un'altra applicazione. 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.

Ricorda che in Accesso a 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 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 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