WebXR Device API: Initialization
Get an introduction to the WebXR Device API and learn about its prominent features.
The WebXR Device API is a set of standards that enable immersive web experiences (AR, VR, MR) on the browser. Content is considered to be “immersive” if it produces visual, audio, haptic, or other sensory output that simulates or augments various aspects of the user’s environment. This API allows us to create 3D experiences with the help of a graphics renderer library, WebGL, and web development tools such as HTML, CSS, and JavaScript. End users interact with the XR experiences in browsers running on their devices. The WebXR Device API works with most browsers that support the latest W3C web standards.
The illustration above shows the steps in an XR development cycle that uses the WebXR Device API.
Setting up WebXR
Let’s see how we can set up a simple WebXR program that calls the API functionalities in the correct order. The API’s core functionalities are to:
Detect if XR capabilities are available on the browser.
Query the XR device capabilities.
Poll the XR device and associated input device state.
Render scenes on the XR device at the appropriate frame rate.
We create a simple HTML file that checks WebXR Device API support in the following code by checking the browser’s window.navigator
object. We write the JavaScript code in a <script>
tag in the HTML file. Click the “Run” button to check for WebXR support.
Note: If your browser doesn’t support WebXR, we recommend accessing this course from one that does. Depending on your browser, you’ll see in the alert window if your browser supports XR compatibility.
The WebXR Device API can be accessed via the window.navigator.xr
object. Let’s loop over this object and store the keys and values in the xr_object_flattened
variable and print it out on the web page using the document.write()
method:
We can see the following information output on the HTML page:
ondevicechange -> [null]isSessionSupported -> [function isSessionSupported() { [native code] }]requestSession -> [function requestSession() { [native code] }]supportsSession -> [function supportsSession() { [native code] }]addEventListener -> [function addEventListener() { [native code] }]dispatchEvent -> [function dispatchEvent() { [native code] }]removeEventListener -> [function removeEventListener() { [native code] }]
ondevicechange
is an event callback to let us know if the connected device has changed. Since we haven’t set anything up right now, it’s assigned the null
value. We’ll learn about the other functions below.
Detecting and advertising XR capabilities
Next, we can see the isSessionSupported()
callback. Let’s see what this function returns:
This returns a isSessionSupported()
method expects an argument, as mentioned in the following error:
TypeError: Failed to execute 'isSessionSupported' on 'XRSystem': 1 argument required, but only 0 present.
We’ll get useful output from the isSessionSupported()
function once we specify the XRSessionMode()
function as an argument. There are three session modes supported by the WebXR Device API:
enum XRSessionMode {"inline","immersive-vr","immersive-ar"}
Let’s look at each of these modes:
inline
: This session is supported by any user agent with WebXR. It doesn’t require any special hardware. The output of the session is presented inline within the context of an element in a standard HTML document, rather than occupying the full visual space. It can be presented in ormono single output channel mode. Depending on the application, positional and rotational tracking is also available using input from a mouse, keyboard, or touch.stereo dual output channel immersive-vr
: This session is supported by immersive VR devices such as HTC Vive, Meta Quest, and Pico. As the name suggests, it produces an artificial environment that can’t be overlaid or integrated with the surrounding environment.immersive-ar
: This session is supported by immersive AR devices (e.g., smartphones). The output content is blended with the real-world environment.
Now, let’s check whether immersive-vr
session mode is supported in our browser:
As expected, our browser doesn’t support the immersive-vr
session mode. We can write our code in a way that if the device doesn’t support VR sessions, we can fall back to the inline session. Here’s how we can do that:
sessionType = 'immersive-vr';window.navigator.xr.isSessionSupported(sessionType).then((supported) => {if (supported) {document.write('Yes, this session type is supported.');}if (!supported) {document.write('Falling back to inline session mode.');sessionType = 'inline';}});
To initiate a connection with the XR device, we request the navigator.xr
object (an instance of the XRSystem
class) to provide us with an XRSession
object via the requestSession()
method. Similar to the isSessionSupported()
method, the requestSession()
method also takes an XRSessionMode
enum as an argument. Typically, after confirming the support for a particular XRSessionMode
enum via the isSessionSupported()
method, the requestSession
method is invoked with that session mode to retrieve the XRSession
object. Further interactions with the XR device can then be conducted via this XRSession
object; therefore, we store its reference in an accessible scope.
Graphical Output
To display content on the end device, there are primarily two steps involved: rendering the content and updating the state on the end device. Let’s look at rendering first.
Rendering the content
The Canvas API enables the browser to draw graphics onto an HTML element, namely the <canvas>
element. It does so by utilizing a graphics library behind the scenes, such as WebGL, WebGPU, etc. A <canvas>
element is assigned a graphics library via the getContext()
method, that also creates and returns a getContext()
method is as follows:
getContext(contextType [, contextAttributes])
contextType
is a string specifying the graphics library and contextAttributes
is an optional object specifying parameters for the said graphics library. For our purpose, we’ll be using webgl
(WebGL v1) as the contextType
option and { xrCompatible: true }
as the contextAttributes
option that will configure WebGL to render content in a mode compatible with an XR device.
Updating the state of the device
To hook our rendered content with the end device, we need an interface called the XRWebGLLayer
interface. This layer bridges an ongoing XRSession
object with a graphics library’s context object (the WebGLRenderingContext
interface in our case). This layer is then passed as an argument to the updateRenderState()
method of the XRSession
object, effectively making it the base layer (or the primary layer) for this session.
The following code snippet sums up this process:
let canvas = document.createElement('canvas');let gl = canvas.getContext('webgl', { xrCompatible: true });let xrSession = await navigator.xr.requestSession('inline');let xrLayer = new XRWebGLLayer(xrSession, gl);xrSession.updateRenderState({ baseLayer: xrLayer });
Let’s look at an executable example of the things covered so far.
Code example
The following code example amalgamates everything we’ve learned about in the lesson:
Code explanation:
Line 13: When the web page loads, we call the
initializeXR()
function.Lines 16–38: In the
initializeXR()
function, we check if WebXR capabilities are supported in the browser. Then, we check what type of session is supported. We have set it toinline
because we’re using the browser. To give the user the ability to choose theXRSessionMode
enum, we can add a drop-down menu with the three options, and on line 17, instead of using a hard-coded value, we can pick up the value from the drop-down menu. Additionally, instead of triggering theinitializeXR()
function in thewindow.onload
event, we call it upon the click of an HTML button.Line 40: When we know that the session is supported, we call the
beginXRSession()
function to set up theXRSession
object and create theXRWebGLLayer
interface.Line 61: We print the
XRSession
object in the browser’s console as well as add it to the web page via thedocument.write()
method.
Here’s the output we see in the browser’s console. Depending on different browsers, we might see different variables in the XRSession
object.
Congratulations, you’ve taken your first step toward the exciting world of WebXR development!