To trigger rendering, invoke XRSession.requestAnimationFrame with an
animationFrameCallback. This callback is called by WebXR before next
repaint with a time stamp and an XRFrame.
The XRFrame.getViewerPose() function provides an XRViewerPose, which
contain an array of XRView objects. The XRView contains projection and
view matrices, one for each eye.
The XRSession object contains a XRRenderState object, which contains an
XRWebGLLayer in the baseLayer property. This object contains an WebGL
framebuffer to render into as well as width and height of the framebuffer.
The views are rendered as tiles into this texture, and
XRWebGLLayer.getViewport can be invoked with the corresponding XRView to
retrieve the expected viewport to use.
XRRenderState also contains a layers property (in addition to
baseLayer). This property contains an ordered array of XRWebGLLayer and
XRCompositionLayer objects.
The composition layers appear to be able to inject a WebGL texture or a HTML video playback directly into the compositor.
Cogs currently only draws into the baselayer. To support rendering to multiple layers, cogs.js must be able to supply cogs.core with a set of framebuffers to draw into per update.
The extension allows to bind a range of slices in an array texture to a FBO attachment:
void FramebufferTextureMultiviewOVR(target, attachment, tex, level, baseViewIndex, numViews)
and the new built-in vertex shader variable gl_ViewID_OVR specifiers which
of the views that are rendered to, and the shader use this to index into an
array of camera-view matrices.
So, in essence, the outer VR loop
for(eye : eyes) {
drawEntireScene(eye)
}
is replaced with
drawEntireScene(eyes)
and the outer loop is moved into the driver (which may either just replay the command stream for each view, or rasterize triangles to multiple views).
Requirements:
gl_Position can depend on gl_ViewID_OVR. OVR_multiview2 lifts this
restriction (that is what that extension does).Availability:
Example 940 in Cogs.Core sets up a fake WebXR scenario drawing eyes separately, without using multiview. WebXR provides an FBO (=rendertarget) that they eyes should call into, but this is not exposed from cogs.core. So the code hooks into the internals and provides callbacks that binds to the FBO at the right spot.
Example 941 in Cogs.Core also sets up a fake WebXR scenario, but with using multiview. Most of the WebXR specifics are kept out of Cogs.Core and considered as API glue. Cogs.Core render into textures attached to cameras, and it is the glue code that blits this to the way WebXR want the tiles laid out.