Course outline
WebXR in One Topic
In one line
WebXR lets a page show the scene in a headset or on a phone camera. It needs HTTPS, a user gesture and a supported device. three.js provides the button and the per-eye drawing; this preview blocks it, and the example shows exactly what that looks like.
Think of it like this
A cinema lets you in only with a ticket, through the front door, to seats set up for the film. WebXR needs a secure page (the ticket), a click (the door) and a device that shows two pictures, one per eye (the seats).
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- WebXR
- The browser API for virtual (VR) and augmented (AR) reality sessions.
- session
- One run of immersive mode. It starts with a click, ends when the user exits, and gives your page the device's pose every frame.
- secure context
- A page served over HTTPS (or from localhost). Many powerful APIs only exist there.
- user gesture
- A real click, tap or key press. Some APIs refuse to start without one.
Step by step
01Ask what is possible
The example prints the secure-context flag, whether navigator.xr exists, and what isSessionSupported("immersive-vr") answers. Here it is error: SecurityError: a caught rejection, not a crash.
02Let three.js add the button
VRButton.createButton(renderer) returns an ordinary <button>. After 200 ms it says VR NOT ALLOWED (and, in this frame, is not disabled).
03Know what the call needs
requestSession needs a click on a secure page, and the frame must allow xr-spatial-tracking. VRButton calls it when pressed.
04Turn XR on and use setAnimationLoop
renderer.xr.enabled = true makes the renderer draw once per eye when a session starts, and setAnimationLoop gives the headset its own timing. The scene is a cube at eye height (1.6 m).
Try it yourself
- 1
Ask for AR instead
Change
"immersive-vr"to"immersive-ar"in theisSessionSupportedcall. The answer is the sameerror: SecurityError: the frame's policy blocks all of WebXR, not just VR. - 2
Ask for a mode that does not exist
Change
"immersive-vr"to"immersive-x". The line now printsimmersive-vr supported: error: TypeError(the label is fixed text): the browser rejects an unknown mode before it looks at permissions. The button still saysVR NOT ALLOWED, from its own check.
Code & diagrams
Measured in this preview. On your own HTTPS page with a headset, the support line says true and the button ENTER VR.
Console
Run the scene to see its console.Expected console output
secure context (HTTPS or localhost): true
navigator.xr exists: true
immersive-vr supported: error: SecurityError
Exception when trying to call xr.isSessionSupported SecurityError: Failed to execute 'isSessionSupported' on 'XRSystem': Access to the feature "xr" is disallowed by permissions policy.
button text: VR NOT ALLOWED | disabled: falseBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Start a session without a click
At the end of the example add navigator.xr.requestSession("immersive-vr").catch((e) => console.log("requestSession:", e.name));.
Myth vs fact
Myth
WebXR is just a different camera.
Fact
It changes the frame loop, the camera's source, the inputs and the units. Plan for metres, eye height and controllers.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Test with the browser's WebXR emulator extension on your computer, then on a real headset. We could not run a real headset here, so everything beyond the permissions behaviour above is from three.js's source, not from a measurement.
- ▸
A failed
requestSessionis normal (no headset, permission refused): handle the promise and return the visitor to the normal view. - ▸
MDN marks WebXR "limited availability" and not Baseline: it does not work in some of the most widely used browsers. Always detect it, and for AR use
ARButtonwith"immersive-ar". Check MDN's compatibility table for the browsers your visitors use.
Remember this
- 1
The problem this solves: headsets and AR phones are real, and showing the bike at life size in a room is a strong demo. But the browser guards a headset carefully: a page cannot grab it silently.
- 2
What a session is.
navigator.xr.requestSession("immersive-vr")starts a session;"immersive-ar"puts the scene over the camera. You can only call it from a user gesture such as a click, on a secure context (HTTPS or localhost).navigator.xr.isSessionSupported(mode)tells you in advance whether the device could. - 3
What three.js does. Set
renderer.xr.enabled = true, run your loop withrenderer.setAnimationLoop(the headset has its own frame clock), and addVRButton.createButton(renderer)fromthree/addons/webxr/VRButton.js. The button text tells the visitor what is possible: "ENTER VR", "VR NOT SUPPORTED" or, as measured here, "VR NOT ALLOWED". - 4
What the preview does. This page lives in a sandboxed frame. The example prints
immersive-vr supported: error: SecurityErrorand the browser's warningAccess to the feature "xr" is disallowed by permissions policy.A frame needsallow="xr-spatial-tracking"for WebXR; this one lacks it. Your own HTTPS page has no such frame.
Explain it without notes
What three things does a page need before it can enter immersive VR?
Why must you use renderer.setAnimationLoop and not requestAnimationFrame for XR?
Practice
Write the lines that show an "Enter VR" button only when VR is supported, and otherwise nothing.
Write the click handler that starts an immersive VR session and handles a refusal.
Done when you can
You can list what WebXR needs: secure page, user gesture, supported device.
You can set up
VRButtonandrenderer.xr.enabled, and usesetAnimationLoop.You handle a blocked or failed session without breaking the page.