Configure Three.js VRButton for WebXR
This article provides a straightforward, step-by-step guide on how to
configure and use the VRButton utility in Three.js to
initiate a WebXR session. You will learn how to import the module,
enable XR on the renderer, append the button to your webpage, and set up
the compatible animation loop required for an immersive virtual reality
experience.
1. Import Three.js and the VRButton
To use the WebXR capabilities in Three.js, you must import the core
library along with the official VRButton addon.
import * as THREE from 'three';
import { VRButton } from 'three/addons/webxr/VRButton.js';2. Enable WebXR on the WebGLRenderer
You must explicitly tell your Three.js renderer to support XR content. Without this setting, the renderer will not transition into the VR headset when the session starts.
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
// This line is required for WebXR
renderer.xr.enabled = true;
document.body.appendChild(renderer.domElement);3. Append the VRButton to the DOM
The VRButton.createButton() method creates an HTML
button that automatically detects VR capabilities. It displays “ENTER
VR” if a headset is connected, “VR NOT SUPPORTED” if unavailable, or
“LIMITATIONS” depending on the device state.
Append this button to your document’s body:
document.body.appendChild(VRButton.createButton(renderer));4. Set Up the WebXR Animation Loop
Standard browser-based rendering uses
window.requestAnimationFrame(). However, WebXR requires the
VR headset to control the frame rate. You must use Three.js’s built-in
setAnimationLoop method to ensure your render loop runs
correctly inside the VR environment.
// Define your update and render logic
function animate() {
// Update your animations and physics here
renderer.render(scene, camera);
}
// Start the loop
renderer.setAnimationLoop(animate);Complete Implementation Example
Below is a complete boilerplate containing all the necessary code to get your WebXR session running:
import * as THREE from 'three';
import { VRButton } from 'three/addons/webxr/VRButton.js';
// Setup Scene, Camera, and Renderer
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x202020);
const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 10);
camera.position.set(0, 1.6, 0); // Position at typical eye height (1.6 meters)
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.xr.enabled = true; // Enable XR
document.body.appendChild(renderer.domElement);
// Add the VR Button to the page
document.body.appendChild(VRButton.createButton(renderer));
// Add a simple object to view in VR
const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 1.6, -2); // Place 2 meters in front of the camera
scene.add(cube);
// Handle window resizing
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// XR-compatible Animation Loop
function animate() {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
renderer.setAnimationLoop(animate);