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.