Skip to main content




All about the frame loop

Recientemente, publiqué la virtual reality llega a la Web, a post que presenta conceptos básicos detrás de la WebXR Device API. Además proporcioné instrucciones para solicitar, acceder y culminar una sesión de XR.

Este post describe el bucle de tramas, que es un bucle infinito controlado por el usuario-agente en el que el contents se dibuja repetidamente en la pantalla. El contenido se dibuja en bloques discretos llamados marcos. La sucesión de fotogramas crea la ilusión de movimiento.

What is this article not?

WebGL y WebGL2 son los únicos medios para representar contenido durante un bucle de cuadro en una aplicación WebXR. Por suerte, muchos marcos proporcionan una capa de abstracción al mismo tiempo de WebGL y WebGL2. Dichos marcos incluyen three.js,
babylonjsand
Playcanvas, while A frame and
Reaccionar 360 están diseñados para interactuar con WebXR.

Este post no es un tutorial de WebGL ni de framework. Explica los conceptos básicos de un bucle de fotogramas usando la muestra de sesión de realidad virtual inmersiva del Grupo de trabajo web inmersivo (manifestation,
source). Si desea sumergirse en WebGL o en uno de los marcos, Internet proporciona una lista creciente de posts.

The players and the game

Cuando trataba de comprender el bucle de cuadros, seguía perdiéndome en los detalles. Hay muchos objetos en juego, y algunos de ellos solo se nombran por propiedades de referencia en otros objetos. Para ayudarte a mantenerlo claro, describiré los objetos, a los que llamo «jugadores». Posteriormente describiré cómo interactúan, a lo que llamo «el juego».

Players

XRViewerPose

Una pose es la posición y orientación de algo en el espacio 3D. Tanto los espectadores como los dispositivos de entrada disponen una pose, pero lo que nos preocupa aquí es la pose del espectador. Ambas poses de visor y dispositivo de entrada disponen transform attribute que describe su posición como vector y su orientación como un cuaternión relativo al origen. El origen se especifica en función del tipo de espacio de referencia solicitado al llamar XRSession.requestReferenceSpace ().

Los espacios de referencia tardan un poco en explicarse. Los cubro en profundidad en realidad aumentada. La muestra que estoy utilizando como base para este post utiliza un 'local' reference space, which means that the origin is in the viewer's position at the time of the session creation without a well-defined floor, and its precise position may vary depending on the platform.

XRView

Una vista corresponde a una cámara que visualiza la escena virtual. Una vista además cuenta con una
transform atributo que describe su posición como vector y su orientación. Estos se proporcionan como un par de vector / cuaternión y como una matriz idéntico, puede utilizar cualquiera de las representaciones dependiendo de cuál se ajuste mejor a su código. Cada vista corresponde a una pantalla o una parte de una pantalla utilizada por un dispositivo para presentar imágenes al espectador. XRView objects are returned in an array from the XRViewerPose objeto. El número de vistas de la matriz varía. En los dispositivos móviles, una escena de RA cuenta con una vista, que puede o no cubrir la pantalla del dispositivo. Los auriculares suelen tener dos vistas, una para cada ojo.

XRWebGLLayer

Layers provide a source for bitmap images and descriptions of how those images should be rendered on the device. This description does not capture what this player does. I have come to think of it as an intermediary between a device and a
WebGLRenderingContext. MDN takes the same point of view, stating that it "provides a link" between the two. As such, it provides access to the other players.

In general, WebGL objects store state information for rendering 2D and 3D graphics.

WebGLFramebuffer

A framebuffer provides image data to the WebGLRenderingContext. Posteriormente de recuperarlo del XRWebGLLayer, básicamente pásalo a la corriente
WebGLRenderingContext. Apart from calling bindFramebuffer () (más sobre eso más adelante) nunca accederá a este objeto de forma directa. Básicamente lo pasará del XRWebGLLayer to the WebGLRenderingContext.

XRViewport

A graphics window provides the coordinates and dimensions of a rectangular region in the WebGLFramebuffer.

WebGLRenderingContext

Un contexto de representación es un punto de acceso programático para un lienzo (el espacio en el que estamos dibujando). Para hacer esto, requiere un WebGLFramebuffer and an XRViewport.

Note la vinculación entre XRWebGLLayer and WebGLRenderingContext. One corresponds to the viewer's device and the other corresponds to the web page.
WebGLFramebuffer and XRViewport they go from the first to the second.

players-2246022

La vinculación entre XRWebGLLayer and WebGLRenderingContext

The game

Ahora que sabemos quiénes son los jugadores, veamos el juego que juegan. Es un juego que comienza de nuevo con cada fotograma. Recuerde que los fotogramas son parte de un bucle de fotogramas que surge a una velocidad que depende del hardware subyacente. Para las aplicaciones de realidad virtual, los fps pueden oscilar entre 60 y 144. AR para Android se ejecuta a 30 fps. Su código no debe hacerse cargo ninguna velocidad de fotogramas en particular.

El procedimiento básico para el bucle de cuadro se ve así:

  1. Call XRSession.requestAnimationFrame (). En respuesta, el user agent invoca el XRFrameRequestCallback, que usted establece.
  2. Inside your callback function:
    1. Call XRSession.requestAnimationFrame () again.
    2. Get the pose of the viewer.
    3. Pass ('link') the WebGLFramebuffer from the XRWebGLLayer to the WebGLRenderingContext.
    4. Iterate over each XRView object, retrieving its XRViewport from the XRWebGLLayer and pass it on to WebGLRenderingContext.
    5. Draw something in the framebuffer.

Como los pasos 1 y 2a se trataron en el post anterior, comenzaré en el paso 2b.

Get the pose of the spectator

Probablemente no es necesario decirlo. Para dibujar cualquier cosa en AR o VR, necesito saber dónde está el espectador y hacia dónde está mirando. La posición y la orientación del espectador son proporcionadas por un XRViewerPose object. I get the pose of the spectator calling XRFrame.getViewerPose () in the current animation frame. I pass you the reference space that I acquired when I set up the session. The values returned by this object are always relative to the reference space that I requested when I entered the current session. As you may recall, I have to pass the current reference space when requesting the pose.

function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {

}
}

Hay una pose del espectador que representa la posición general del Username, dicho de otra forma, la cabeza del espectador o la cámara del teléfono en el caso de un teléfono inteligente. La pose le dice a su aplicación dónde está el espectador. Usos reales de renderizado de imágenes
XRView objects, which I'll get to in a moment.

Antes de continuar, pruebo si la pose del espectador fue devuelta en caso de que el sistema pierda el seguimiento o bloquee la pose por razones de privacidad. El seguimiento es la capacidad del dispositivo XR para comprender dónde está y / o sus dispositivos de entrada en vinculación con el entorno. El seguimiento se puede perder de varias formas y varía según el método utilizado para realizar el seguimiento. A modo de ejemplo, si se usan cámaras en los auriculares o en el teléfono para rastrear, el dispositivo puede perder su capacidad para establecer dónde se encuentra en situaciones con poca luz o sin luz, o si las cámaras están cubiertas.

Un ejemplo de bloqueo de la pose por motivos de privacidad es que si el auricular muestra un cuadro de diálogo de seguridad, como una solicitud de permiso, el browser puede dejar de proporcionar poses a la aplicación mientras esto ocurre. Pero ya llamé
XRSession.requestAnimationFrame () de modo que si el sistema puede recuperarse, el bucle de tramas continuará. Caso contrario, el agente de usuario finalizará la sesión y llamará al
end event handler.

A little detour

El paso siguiente necesita objetos creados durante la configuración de la sesión. Recuerde que creé un lienzo y le indiqué que creara un contexto de representación Web GL compatible con XR, que obtuve llamando canvas.getContext (). Todo el dibujo se realiza a través de la API de WebGL, la API de WebGL2 o un marco basado en WebGL como Three.js. Este contexto se pasó al objeto de sesión a través de updateRenderState (), along with a new instance of XRWebGLLayer.

let canvas = document.createElement('canvas');
let webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
});

Pass ('bind') the WebGLFramebuffer

the XRWebGLLayer provides a framebuffer for the WebGLRenderingContext
provided specifically for use with WebXR and overriding the default framebuffer for rendering contexts. This is called "binding" in the language of WebGL.

function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
let glLayer = xrSession.renderState.baseLayer;
webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);

}
}

Iterate over each XRView object

Posteriormente de conseguir la pose y vincular el framebuffer, es hora de conseguir las ventanas gráficas. los XRViewerPose contains an array of XRView interfaces, each of which represents a screen or part of a screen. They contain information necessary to represent content that is correctly positioned for the device and the viewer, such as field of view, eye movement, and other optical properties. As a two-eye drawing, I have two views, which I loop through and draw a separate image for each.

Al poner en práctica para la realidad aumentada basada en teléfonos, solo tendría una vista, pero todavía usaría un bucle. Aún cuando puede parecer inútil iterar a través de una vista, hacerlo le posibilita tener una única ruta de renderizado para un espectro de experiencias inmersivas. Esta es una diferencia importante entre WebXR y otros sistemas inmersivos.

function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
let glLayer = xrSession.renderState.baseLayer;
webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);
for (let xrView of xrViewerPose.views) {

}
}
}

Pass the XRViewport object to the WebGLRenderingContext

A XRView objeto se refiere a lo que se puede observar en una pantalla. Pero para dibujar en esa vista, necesito coordenadas y dimensiones que sean específicas de mi dispositivo. Del mismo modo que con el framebuffer, los solicito al XRWebGLLayer and pass them to
WebGLRenderingContext.

function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
let glLayer = xrSession.renderState.baseLayer;
webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);
for (let xrView of xrViewerPose.views) {
let viewport = glLayer.getViewport(xrView);
webGLRenContext.viewport(viewport.x, viewport.and, viewport.width, viewport.height);

}
}
}

The webGLRenContext

Al escribir este post, tuve un debate con algunos colegas sobre el nombre del webGLRenContext objeto. Los scripts de muestra y la mayoría del código WebXR básicamente llaman a esta variable gl. Cuando estaba trabajando para saber las muestras, seguía olvidando lo que gl referred to. I called it webGLRenContext to remind you as you learn that this is an example of WebGLRenderingContext.

La razón es que utilizar gl posibilita que los nombres de los métodos se parezcan a sus contrapartes en la API de OpenGL ES 2.0, que se usa para crear realidad virtual en lenguajes compilados. Este hecho es obvio si ha escrito aplicaciones de realidad virtual utilizando OpenGL, pero confuso si es absolutamente nuevo en esta tecnología.

Draw something in the framebuffer

Si se siente verdaderamente ambicioso, puede utilizar WebGL de forma directa, pero no lo recomiendo. Es mucho más sencillo usar uno de los marcos enumerados en la parte superior.

conclusion

Este no es el final de las actualizaciones o posts de WebXR. Puedes hallar un reference for all interfaces and members of WebXR
in MDN. For upcoming interface enhancements, follow the individual features at Chrome Status.

Photo by JESHOOTS.COM in Unsplash