Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 11 additions & 59 deletions examples/jsm/webxr/WebGLXRFallback.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,23 @@
/**
* Sets up a construction-time WebGL fallback for WebGPU XR examples.
*
* @param {WebGPURenderer} renderer - The initial renderer.
* @param {Function} createFallbackRenderer - A function that returns a new renderer with a WebGL backend.
* @param {Function} onFallback - A function that installs the new renderer in the app.
* WebGPU XR requires the browser to expose `XRGPUBinding`. If the API is not
* available, this helper mutates the renderer parameters to use the existing
* WebGL fallback backend.
*
* @param {Object} parameters - The parameters passed to `WebGPURenderer`.
* @return {Object} The same parameters object.
*/
function setupWebGLXRFallback( renderer, createFallbackRenderer, onFallback = () => {} ) {

let currentRenderer = renderer;
const patchedRenderers = new WeakSet();

function patchRenderer( renderer ) {

if ( patchedRenderers.has( renderer ) ) return;

patchedRenderers.add( renderer );

const setSession = renderer.xr.setSession.bind( renderer.xr );

renderer.xr.setSession = async function ( session ) {

if ( renderer !== currentRenderer ) {

return currentRenderer.xr.setSession( session );

}

try {

return await setSession( session );

} catch ( error ) {

if ( session === null || renderer.backend.isWebGPUBackend !== true ) {

throw error;

}

const fallbackRenderer = createFallbackRenderer( renderer );

if ( fallbackRenderer.backend.isWebGLBackend !== true ) {

throw new Error( 'WebGLXRFallback: createFallbackRenderer() must return a renderer with a WebGL backend.' );

}

fallbackRenderer.xr.enabled = renderer.xr.enabled;
fallbackRenderer.xr.cameraAutoUpdate = renderer.xr.cameraAutoUpdate;
fallbackRenderer.xr.setFramebufferScaleFactor( renderer.xr.getFramebufferScaleFactor() );
fallbackRenderer.xr.setReferenceSpaceType( renderer.xr.getReferenceSpaceType() );

await onFallback( fallbackRenderer, renderer );

currentRenderer = fallbackRenderer;
patchRenderer( fallbackRenderer );

return fallbackRenderer.xr.setSession( session );
function setWebGLXRFallback( parameters ) {

}
if ( ! ( 'XRGPUBinding' in window ) ) {

};
parameters.forceWebGL = true;

}

patchRenderer( renderer );
return parameters;

}

export { setupWebGLXRFallback };
export { setWebGLXRFallback };
49 changes: 9 additions & 40 deletions examples/webgpu_xr_cubes.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
import { BoxLineGeometry } from 'three/addons/geometries/BoxLineGeometry.js';
import { XRButton } from 'three/addons/webxr/XRButton.js';
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
import { setupWebGLXRFallback } from 'three/addons/webxr/WebGLXRFallback.js';
import { setWebGLXRFallback } from 'three/addons/webxr/WebGLXRFallback.js';

const timer = new THREE.Timer();
timer.connect( document );

const rendererParameters = { antialias: true, outputBufferType: THREE.UnsignedByteType, multiview: true };
setWebGLXRFallback( rendererParameters );
const controllerModelFactory = new XRControllerModelFactory();

let container;
Expand Down Expand Up @@ -105,54 +106,22 @@

raycaster = new THREE.Raycaster();

renderer = createRenderer();
setRenderer( renderer );
setupWebGLXRFallback( renderer, () => createRenderer( true ), setRenderer );

//

window.addEventListener( 'resize', onWindowResize );

//

document.body.appendChild( XRButton.createButton( renderer ) );

}

function createRenderer( forceWebGL = false ) {

const parameters = { ...rendererParameters };

if ( forceWebGL === true ) parameters.forceWebGL = true;

const renderer = new THREE.WebGPURenderer( parameters );
renderer = new THREE.WebGPURenderer( rendererParameters );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
renderer.xr.enabled = true;
container.appendChild( renderer.domElement );

return renderer;

}

function setRenderer( newRenderer, oldRenderer = null ) {

if ( controller !== undefined ) scene.remove( controller );
if ( controllerGrip !== undefined ) scene.remove( controllerGrip );

if ( oldRenderer === null ) {

container.appendChild( newRenderer.domElement );
setupControllers();

} else {
//

container.replaceChild( newRenderer.domElement, oldRenderer.domElement );
oldRenderer.dispose();
window.addEventListener( 'resize', onWindowResize );

}
//

renderer = newRenderer;
setupControllers();
document.body.appendChild( XRButton.createButton( renderer ) );

}

Expand Down
6 changes: 5 additions & 1 deletion examples/webgpu_xr_native_layers.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
} from 'three/addons/misc/RollerCoaster.js';
import { HTMLMesh } from 'three/addons/interactive/HTMLMesh.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { setWebGLXRFallback } from 'three/addons/webxr/WebGLXRFallback.js';

let camera, scene, renderer;
let controller1, controller2;
Expand Down Expand Up @@ -185,7 +186,10 @@

//

renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL: true, outputBufferType: THREE.UnsignedByteType, multiview: true } );
const rendererParameters = { antialias: true, outputBufferType: THREE.UnsignedByteType, multiview: true };
setWebGLXRFallback( rendererParameters );

renderer = new THREE.WebGPURenderer( rendererParameters );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
Expand Down
48 changes: 9 additions & 39 deletions examples/webgpu_xr_rollercoaster.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,55 +33,25 @@
SkyGeometry
} from 'three/addons/misc/RollerCoaster.js';
import { VRButton } from 'three/addons/webxr/VRButton.js';
import { setupWebGLXRFallback } from 'three/addons/webxr/WebGLXRFallback.js';
import { setWebGLXRFallback } from 'three/addons/webxr/WebGLXRFallback.js';

let mesh, material, geometry;
let renderer;

const rendererParameters = { antialias: true, outputBufferType: THREE.UnsignedByteType, multiview: false };
setWebGLXRFallback( rendererParameters );

renderer = createRenderer();
setRenderer( renderer );
setupWebGLXRFallback( renderer, () => createRenderer( true ), setRenderer );
const renderer = new THREE.WebGPURenderer( rendererParameters );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
renderer.xr.enabled = true;
renderer.xr.setReferenceSpaceType( 'local' );
document.body.appendChild( renderer.domElement );

document.body.appendChild( VRButton.createButton( renderer ) );

//

function createRenderer( forceWebGL = false ) {

const parameters = { ...rendererParameters };

if ( forceWebGL === true ) parameters.forceWebGL = true;

const renderer = new THREE.WebGPURenderer( parameters );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
renderer.xr.enabled = true;
renderer.xr.setReferenceSpaceType( 'local' );

return renderer;

}

function setRenderer( newRenderer, oldRenderer = null ) {

if ( oldRenderer === null ) {

document.body.appendChild( newRenderer.domElement );

} else {

document.body.replaceChild( newRenderer.domElement, oldRenderer.domElement );
oldRenderer.dispose();

}

renderer = newRenderer;

}

const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0ff );

Expand Down
Loading