WEBGL_multiview WebGL working group (public_webgl 'at' khronos.org) Olli Etuaho, NVIDIA Members of the WebGL working group 36 Calling framebufferTextureMultiviewWEBGL with a non-null texture parameter that does not identify a 2D array texture generates an INVALID_OPERATION error. The values of baseViewIndex and numViews can result in an error only if the texture parameter is non-null. If baseViewIndex is not the same for all framebuffer attachment points where the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is not NONE the framebuffer is considered incomplete. Calling getFramebufferStatus for a framebuffer in this state returns FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR. Other rules for framebuffer completeness from the OVR_multiview specification also apply. Other web APIs may expose opaque multiview framebuffers. Opaque multiview framebuffers are WebGLFramebuffer objects that act as if they have multi-view attachments, but their attachments are not exposed as textures or renderbuffers and can not be changed. Opaque multiview framebuffers may have any combination of color, depth and stencil attachments. Calling framebufferRenderbuffer, framebufferTexture2D, framebufferTextureLayer, framebufferTextureMultiviewWEBGL, or any other call that could change framebuffer attachments with an opaque multiview framebuffer bound to target generates an INVALID_OPERATION error. If an opaque framebuffer is bound to target when calling getFramebufferAttachmentParameter, then attachment must be BACK, DEPTH, or STENCIL. If an opaque framebuffer is bound to target when calling getFramebufferAttachmentParameter, then pname must not be FRAMEBUFFER_ATTACHMENT_OBJECT_NAME. Querying FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR on an opaque multiview framebuffer attachment point that has attachments must return the number of views in the opaque multiview framebuffer. Querying FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR on an opaque multiview framebuffer must return 0. Querying FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE on an opaque multiview framebuffer must return FRAMEBUFFER_DEFAULT. The number of views in an opaque multiview framebuffer may be greater than the maximum number of texture array views (the value of MAX_VIEWS_OVR). Passing an opaque multiview framebuffer to deleteFramebuffer generates an INVALID_OPERATION error. Although the extension name is prefixed with WEBGL the extension must be enabled with the #extension GL_OVR_multiview directive, as shown in the sample code, to use the extension in a shader. Likewise the shading language preprocessor #define GL_OVR_multiview, will be defined to 1 if the extension is supported. This extension relaxes the restriction in OVR_multiview that only gl_Position can depend on ViewID in the vertex shader. With this change, view-dependent outputs like reflection vectors and similar are allowed. When the number of views specified in the active program is one, gl_ViewID_OVR will always evaluate to zero. When a shader written in OpenGL ES shading language version 1.00 enables or requires GL_OVR_multiview with an extension directive, layout is treated as a keyword rather than an identifier, and using a layout qualifier to specify num_views is allowed. Other uses of layout qualifiers are not allowed in OpenGL ES shading language 1.00. In OpenGL ES shading language version 1.00 gl_ViewID_OVR has the type int as opposed to uint. When a timer query is active and the number of views in the current draw framebuffer is greater than one, attempting to draw or calling clear generates an INVALID_OPERATION error. When the number of views in the current draw framebuffer is greater than one and the active program does not declare a number of views, attempting to draw generates an INVALID_OPERATION error. Adds support for rendering into multiple views simultaneously. This is supported for opaque multiview framebuffers starting from WebGL 1.0, and 2D texture arrays starting from WebGL 2.0. When a shader enables, requires, or warns GL_OVR_multiview with an extension directive:
  • gl_ViewID_OVR is a built-in input of the type uint.
The GLSL macro GL_OVR_multiview is defined as 1.
[NoInterfaceObject] interface WEBGL_multiview { const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR = 0x9630; const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR = 0x9632; const GLenum MAX_VIEWS_OVR = 0x9631; const GLenum FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR = 0x9633; void framebufferTextureMultiviewWEBGL(GLenum target, GLenum attachment, WebGLTexture? texture, GLint level, GLint baseViewIndex, GLsizei numViews); }; Calling with the pname set to MAX_VIEWS_OVR returns the maximum number of views. The implementation must support at least 2 views.
The return type depends on the parameter queried:
pnamereturned type
MAX_VIEWS_OVRGLint
Calling with the pname parameter set to FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR returns the number of views of the framebuffer object attachment. Calling with the pname parameter set to FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR returns the base view index of the framebuffer object attachment.
The return type depends on the parameter queried:
pnamereturned type
FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVRGLsizei
FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVRGLint
The error INVALID_OPERATION is generated by calling framebufferTextureMultiviewWEBGL with a texture parameter that does not identify a 2D array texture. The error INVALID_OPERATION is generated by calling framebufferRenderbuffer, framebufferTexture2D, framebufferTextureLayer, or framebufferTextureMultiviewWEBGL with a target parameter that identifies an opaque multiview framebuffer. The error INVALID_OPERATION is generated by calling deleteFramebuffer with a buffer parameter that identifies an opaque multiview framebuffer. The error INVALID_ENUM is generated by calling getFramebufferAttachmentParameter with an attachment parameter other than BACK, DEPTH or STENCIL when the target parameter identifies an opaque multiview framebuffer. The error INVALID_ENUM is generated by calling getFramebufferAttachmentParameter with the pname parameter set to FRAMEBUFFER_ATTACHMENT_OBJECT_NAME when the target parameter identifies an opaque multiview framebuffer. The error INVALID_VALUE is generated by calling framebufferTextureMultiviewWEBGL with a non-null texture in the following cases:
  • if numViews is less than one
  • if numViews is more than MAX_VIEWS_OVR
  • with the parameters set so that baseViewIndex + numViews is larger than the value of MAX_ARRAY_TEXTURE_LAYERS
  • if baseViewIndex is negative
The error INVALID_FRAMEBUFFER_OPERATION is generated by commands that read from the framebuffer such as BlitFramebuffer, ReadPixels, CopyTexImage*, and CopyTexSubImage*, if the number of views in the current read framebuffer is greater than one. The error INVALID_OPERATION is generated by attempting to draw if the active program declares a number of views and the number of views in the draw framebuffer does not match the number of views declared in the active program. The error INVALID_OPERATION is generated by attempting to draw if the number of views in the current draw framebuffer is greater than one and the active program does not declare a number of views. The error INVALID_OPERATION is generated by attempting to draw if the number of views in the current draw framebuffer is greater than one and transform feedback is active. The error INVALID_OPERATION is generated by attempting to draw or calling clear if the number of views in the current draw framebuffer is greater than one and a timer query is active.
    var gl = document.createElement('canvas').getContext('webgl2');
    var ext = gl.getExtension('WEBGL_multiview');
    var fb = gl.createFramebuffer();
    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
    var colorTex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D_ARRAY, colorTex);
    gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 512, 512, 2);
    ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
    var depthStencilTex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D_ARRAY, depthStencilTex);
    gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.DEPTH32F_STENCIL8, 512, 512, 2);
    ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilTex, 0, 0, 2);
    gl.drawElements(...);  // draw will be broadcasted to the layers of colorTex and depthStencilTex.
    
    var gl = document.createElement('canvas').getContext('webgl');
    var ext = gl.getExtension('WEBGL_multiview');
    // ... obtain opaque multiview framebuffer "fb" from another web API here ...
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.drawElements(...);  // draw will be broadcasted to the views of the opaque multiview framebuffer.
    // You can not call framebufferTextureMultiviewWEBGL to change the attachments of "fb", only draw to it.
    
    #version 300 es
    #extension GL_OVR_multiview : require
    precision mediump float;
    layout (num_views = 2) in;
    in vec4 inPos;
    uniform mat4 u_viewMatrix0;
    uniform mat4 u_viewMatrix1;
    void main() {
      if (gl_ViewID_OVR == 0u) {
        gl_Position = u_viewMatrix0 * inPos;
      } else {
        gl_Position = u_viewMatrix1 * inPos;
      }
    }
    
Initial revision. Specified what happens when the number of views doesn't match or if the number of views is one. ยด Specified what happens on invalid num_views declarations and if assignment to gl_Position.x is inside a larger expression. Filled in getFramebufferAttachmentParameter and extension macro specs, formatted the documentation better, and added a simple API usage example. Removed the core spec changes and made the specification follow the OVR_multiview specification more closely. Introduced the concept of an opaque multiview framebuffer and fixed example code. Made the extension compatible with WebGL 1.0 and fixed example shader code. Specified some errors to be generated at draw time and made the extension compatible with emscripten. Rolled back shader restrictions. Required a multiview program to draw to a multiview framebuffer. Took changes in the native OVR_multiview specification into account, added a more elaborate example including a depth/stencil texture, and an explicit mention that texture arrays are only supported in WebGL 2.0. Moved to draft status. Fixed off-by-one issue in validating baseViewIndex + numViews.