diff --git a/examples/files.json b/examples/files.json
index 1f99ba5930ce4..2e136d4c9dc12 100644
--- a/examples/files.json
+++ b/examples/files.json
@@ -357,14 +357,9 @@
],
"webxr": [
"webxr_ar_cones",
- "webxr_ar_dragging",
"webxr_ar_hittest",
"webxr_ar_lighting",
- "webxr_ar_paint",
"webxr_ar_plane_detection",
- "webxr_vr_ballshooter",
- "webxr_vr_cubes",
- "webxr_vr_dragging",
"webxr_vr_handinput",
"webxr_vr_handinput_cubes",
"webxr_vr_handinput_profiles",
@@ -375,12 +370,15 @@
"webxr_vr_layers",
"webxr_vr_panorama",
"webxr_vr_panorama_depth",
- "webxr_vr_paint",
"webxr_vr_rollercoaster",
"webxr_vr_sandbox",
- "webxr_vr_sculpt",
"webxr_vr_teleport",
- "webxr_vr_video"
+ "webxr_vr_video",
+ "webxr_xr_ballshooter",
+ "webxr_xr_cubes",
+ "webxr_xr_dragging",
+ "webxr_xr_paint",
+ "webxr_xr_sculpt"
],
"games": [
"games_fps"
diff --git a/examples/jsm/webxr/XRButton.js b/examples/jsm/webxr/XRButton.js
new file mode 100644
index 0000000000000..f33cbbea25111
--- /dev/null
+++ b/examples/jsm/webxr/XRButton.js
@@ -0,0 +1,198 @@
+class XRButton {
+
+ static createButton( renderer ) {
+
+ const button = document.createElement( 'button' );
+
+ function showStartXR( mode ) {
+
+ let currentSession = null;
+
+ async function onSessionStarted( session ) {
+
+ session.addEventListener( 'end', onSessionEnded );
+
+ await renderer.xr.setSession( session );
+
+ button.textContent = 'STOP XR';
+
+ currentSession = session;
+
+ }
+
+ function onSessionEnded( /*event*/ ) {
+
+ currentSession.removeEventListener( 'end', onSessionEnded );
+
+ button.textContent = 'START XR';
+
+ currentSession = null;
+
+ }
+
+ //
+
+ button.style.display = '';
+
+ button.style.cursor = 'pointer';
+ button.style.left = 'calc(50% - 50px)';
+ button.style.width = '100px';
+
+ button.textContent = 'START XR';
+
+ button.onmouseenter = function () {
+
+ button.style.opacity = '1.0';
+
+ };
+
+ button.onmouseleave = function () {
+
+ button.style.opacity = '0.5';
+
+ };
+
+ button.onclick = function () {
+
+ if ( currentSession === null ) {
+
+ const sessionInit = {
+ optionalFeatures: [
+ 'local-floor',
+ 'bounded-floor',
+ 'hand-tracking',
+ 'layers'
+ ]
+ };
+
+ navigator.xr.requestSession( mode, sessionInit )
+ .then( onSessionStarted );
+
+ } else {
+
+ currentSession.end();
+
+ }
+
+ };
+
+ }
+
+ function disableButton() {
+
+ button.style.display = '';
+
+ button.style.cursor = 'auto';
+ button.style.left = 'calc(50% - 75px)';
+ button.style.width = '150px';
+
+ button.onmouseenter = null;
+ button.onmouseleave = null;
+
+ button.onclick = null;
+
+ }
+
+ function showXRNotSupported() {
+
+ disableButton();
+
+ button.textContent = 'XR NOT SUPPORTED';
+
+ }
+
+ function showXRNotAllowed( exception ) {
+
+ disableButton();
+
+ console.warn( 'Exception when trying to call xr.isSessionSupported', exception );
+
+ button.textContent = 'XR NOT ALLOWED';
+
+ }
+
+ function stylizeElement( element ) {
+
+ element.style.position = 'absolute';
+ element.style.bottom = '20px';
+ element.style.padding = '12px 6px';
+ element.style.border = '1px solid #fff';
+ element.style.borderRadius = '4px';
+ element.style.background = 'rgba(0,0,0,0.1)';
+ element.style.color = '#fff';
+ element.style.font = 'normal 13px sans-serif';
+ element.style.textAlign = 'center';
+ element.style.opacity = '0.5';
+ element.style.outline = 'none';
+ element.style.zIndex = '999';
+
+ }
+
+ if ( 'xr' in navigator ) {
+
+ button.id = 'XRButton';
+ button.style.display = 'none';
+
+ stylizeElement( button );
+
+ navigator.xr.isSessionSupported( 'immersive-ar' )
+ .then( function ( supported ) {
+
+ if ( supported ) {
+
+ showStartXR( 'immersive-ar' );
+
+ } else {
+
+ navigator.xr.isSessionSupported( 'immersive-vr' )
+ .then( function ( supported ) {
+
+ if ( supported ) {
+
+ showStartXR( 'immersive-vr' );
+
+ } else {
+
+ showXRNotSupported();
+
+ }
+
+ } ).catch( showXRNotAllowed );
+
+ }
+
+ } ).catch( showXRNotAllowed );
+
+ return button;
+
+ } else {
+
+ const message = document.createElement( 'a' );
+
+ if ( window.isSecureContext === false ) {
+
+ message.href = document.location.href.replace( /^http:/, 'https:' );
+ message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message
+
+ } else {
+
+ message.href = 'https://immersiveweb.dev/';
+ message.innerHTML = 'WEBXR NOT AVAILABLE';
+
+ }
+
+ message.style.left = 'calc(50% - 90px)';
+ message.style.width = '180px';
+ message.style.textDecoration = 'none';
+
+ stylizeElement( message );
+
+ return message;
+
+ }
+
+ }
+
+}
+
+export { XRButton };
diff --git a/examples/screenshots/webxr_ar_dragging.jpg b/examples/screenshots/webxr_ar_dragging.jpg
deleted file mode 100644
index 4714c68168456..0000000000000
Binary files a/examples/screenshots/webxr_ar_dragging.jpg and /dev/null differ
diff --git a/examples/screenshots/webxr_ar_paint.jpg b/examples/screenshots/webxr_ar_paint.jpg
deleted file mode 100644
index 001fe203e0b94..0000000000000
Binary files a/examples/screenshots/webxr_ar_paint.jpg and /dev/null differ
diff --git a/examples/screenshots/webxr_vr_ballshooter.jpg b/examples/screenshots/webxr_xr_ballshooter.jpg
similarity index 100%
rename from examples/screenshots/webxr_vr_ballshooter.jpg
rename to examples/screenshots/webxr_xr_ballshooter.jpg
diff --git a/examples/screenshots/webxr_vr_cubes.jpg b/examples/screenshots/webxr_xr_cubes.jpg
similarity index 100%
rename from examples/screenshots/webxr_vr_cubes.jpg
rename to examples/screenshots/webxr_xr_cubes.jpg
diff --git a/examples/screenshots/webxr_vr_dragging.jpg b/examples/screenshots/webxr_xr_dragging.jpg
similarity index 100%
rename from examples/screenshots/webxr_vr_dragging.jpg
rename to examples/screenshots/webxr_xr_dragging.jpg
diff --git a/examples/screenshots/webxr_vr_paint.jpg b/examples/screenshots/webxr_xr_paint.jpg
similarity index 100%
rename from examples/screenshots/webxr_vr_paint.jpg
rename to examples/screenshots/webxr_xr_paint.jpg
diff --git a/examples/screenshots/webxr_vr_sculpt.jpg b/examples/screenshots/webxr_xr_sculpt.jpg
similarity index 100%
rename from examples/screenshots/webxr_vr_sculpt.jpg
rename to examples/screenshots/webxr_xr_sculpt.jpg
diff --git a/examples/webxr_ar_dragging.html b/examples/webxr_ar_dragging.html
deleted file mode 100644
index 0805df407d1aa..0000000000000
--- a/examples/webxr_ar_dragging.html
+++ /dev/null
@@ -1,244 +0,0 @@
-
-
-
- three.js ar - dragging
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/webxr_ar_paint.html b/examples/webxr_ar_paint.html
deleted file mode 100644
index 6a26076f5b755..0000000000000
--- a/examples/webxr_ar_paint.html
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
-
- three.js ar - paint
-
-
-
-
-
-
-
-
three.js ar - paint
(Chrome Android 81+)
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/webxr_vr_ballshooter.html b/examples/webxr_xr_ballshooter.html
similarity index 98%
rename from examples/webxr_vr_ballshooter.html
rename to examples/webxr_xr_ballshooter.html
index 15f8ea178362f..0e0b006efef01 100644
--- a/examples/webxr_vr_ballshooter.html
+++ b/examples/webxr_xr_ballshooter.html
@@ -1,7 +1,7 @@
- three.js vr - ball shooter
+ three.js xr - ball shooter
@@ -30,7 +30,7 @@
import * as THREE from 'three';
import { BoxLineGeometry } from 'three/addons/geometries/BoxLineGeometry.js';
- import { VRButton } from 'three/addons/webxr/VRButton.js';
+ import { XRButton } from 'three/addons/webxr/XRButton.js';
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
let camera, scene, renderer;
@@ -100,7 +100,7 @@
//
- document.body.appendChild( VRButton.createButton( renderer ) );
+ document.body.appendChild( XRButton.createButton( renderer ) );
// controllers
diff --git a/examples/webxr_vr_cubes.html b/examples/webxr_xr_cubes.html
similarity index 97%
rename from examples/webxr_vr_cubes.html
rename to examples/webxr_xr_cubes.html
index 2672bffcfcea8..0040bd6fb4d1e 100644
--- a/examples/webxr_vr_cubes.html
+++ b/examples/webxr_xr_cubes.html
@@ -1,7 +1,7 @@
- three.js vr - cubes
+ three.js xr - cubes
@@ -30,7 +30,7 @@
import * as THREE from 'three';
import { BoxLineGeometry } from 'three/addons/geometries/BoxLineGeometry.js';
- import { VRButton } from 'three/addons/webxr/VRButton.js';
+ import { XRButton } from 'three/addons/webxr/XRButton.js';
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
const clock = new THREE.Clock();
@@ -146,7 +146,7 @@
//
- document.body.appendChild( VRButton.createButton( renderer ) );
+ document.body.appendChild( XRButton.createButton( renderer ) );
}
diff --git a/examples/webxr_vr_dragging.html b/examples/webxr_xr_dragging.html
similarity index 97%
rename from examples/webxr_vr_dragging.html
rename to examples/webxr_xr_dragging.html
index d52e246395306..601d160be8030 100644
--- a/examples/webxr_vr_dragging.html
+++ b/examples/webxr_xr_dragging.html
@@ -1,7 +1,7 @@
- three.js vr - dragging
+ three.js xr - dragging
@@ -29,7 +29,7 @@
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
- import { VRButton } from 'three/addons/webxr/VRButton.js';
+ import { XRButton } from 'three/addons/webxr/XRButton.js';
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
let container;
@@ -134,7 +134,7 @@
renderer.xr.enabled = true;
container.appendChild( renderer.domElement );
- document.body.appendChild( VRButton.createButton( renderer ) );
+ document.body.appendChild( XRButton.createButton( renderer ) );
// controllers
diff --git a/examples/webxr_vr_paint.html b/examples/webxr_xr_paint.html
similarity index 97%
rename from examples/webxr_vr_paint.html
rename to examples/webxr_xr_paint.html
index 5ff2ee8546889..ad07b9ccb35a2 100644
--- a/examples/webxr_vr_paint.html
+++ b/examples/webxr_xr_paint.html
@@ -1,7 +1,7 @@
- three.js vr - paint
+ three.js xr - paint
@@ -30,7 +30,7 @@
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { TubePainter } from 'three/addons/misc/TubePainter.js';
- import { VRButton } from 'three/addons/webxr/VRButton.js';
+ import { XRButton } from 'three/addons/webxr/XRButton.js';
let camera, scene, renderer;
let controller1, controller2;
@@ -105,7 +105,7 @@
renderer.xr.enabled = true;
container.appendChild( renderer.domElement );
- document.body.appendChild( VRButton.createButton( renderer ) );
+ document.body.appendChild( XRButton.createButton( renderer ) );
// controllers
diff --git a/examples/webxr_vr_sculpt.html b/examples/webxr_xr_sculpt.html
similarity index 97%
rename from examples/webxr_vr_sculpt.html
rename to examples/webxr_xr_sculpt.html
index ccff83a8aa0a1..83ddf7526fbdf 100644
--- a/examples/webxr_vr_sculpt.html
+++ b/examples/webxr_xr_sculpt.html
@@ -1,7 +1,7 @@
- three.js vr - sculpt
+ three.js xr - sculpt
@@ -30,7 +30,7 @@
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { MarchingCubes } from 'three/addons/objects/MarchingCubes.js';
- import { VRButton } from 'three/addons/webxr/VRButton.js';
+ import { XRButton } from 'three/addons/webxr/XRButton.js';
let container;
let camera, scene, renderer;
@@ -99,7 +99,7 @@
renderer.xr.enabled = true;
container.appendChild( renderer.domElement );
- document.body.appendChild( VRButton.createButton( renderer ) );
+ document.body.appendChild( XRButton.createButton( renderer ) );
// controllers
diff --git a/src/renderers/webgl/WebGLBackground.js b/src/renderers/webgl/WebGLBackground.js
index 70cbf8fd0fa4a..6d0ff5b8334c1 100644
--- a/src/renderers/webgl/WebGLBackground.js
+++ b/src/renderers/webgl/WebGLBackground.js
@@ -33,25 +33,38 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha,
}
- // Ignore background in AR
- // TODO: Reconsider this.
+ if ( background === null ) {
- const xr = renderer.xr;
- const session = xr.getSession && xr.getSession();
+ setClear( clearColor, clearAlpha );
- if ( session && session.environmentBlendMode === 'additive' ) {
+ } else if ( background && background.isColor ) {
- background = null;
+ setClear( background, 1 );
+ forceClear = true;
}
- if ( background === null ) {
+ const xr = renderer.xr;
+ const session = xr.getSession();
- setClear( clearColor, clearAlpha );
+ if ( session !== null ) {
- } else if ( background && background.isColor ) {
+ switch ( session.environmentBlendMode ) {
+
+ case 'additive':
+
+ state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha );
+
+ break;
+
+ case 'alpha-blend':
+
+ state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha );
+
+ break;
+
+ }
- setClear( background, 1 );
forceClear = true;
}
diff --git a/src/renderers/webxr/WebXRManager.js b/src/renderers/webxr/WebXRManager.js
index 3fddddf1e888c..5193987a20a76 100644
--- a/src/renderers/webxr/WebXRManager.js
+++ b/src/renderers/webxr/WebXRManager.js
@@ -19,6 +19,7 @@ class WebXRManager extends EventDispatcher {
const scope = this;
let session = null;
+
let framebufferScaleFactor = 1.0;
let referenceSpace = null;
@@ -268,7 +269,7 @@ class WebXRManager extends EventDispatcher {
const layerInit = {
antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true,
- alpha: attributes.alpha,
+ alpha: true,
depth: attributes.depth,
stencil: attributes.stencil,
framebufferScaleFactor: framebufferScaleFactor