WebGL context must be marked as XR compatible in order to use with an immersive XRSession
See original GitHub issueWhen calling WebXRManager.setSession( value )
you sometimes might get this message:
Uncaught (in promise) DOMException: Failed to construct 'XRWebGLLayer': WebGL context must be marked as XR compatible in order to use with an immersive XRSession
To Reproduce
I am able to reproduce the issue only on my localhost environment. When serving my viewer from the server it’s working fine.
The reason for this issue is a racing condition.
when creating an instance of XRWebGLLayer
the WebGL context (gl)
should already be XR compatible enabled.
The gl.makeXRCompatible()
function returns a Promise
.
Current setSession Code
this.setSession = function ( value ) {
session = value;
if ( session !== null ) {
session.addEventListener( 'select', onSessionEvent );
session.addEventListener( 'selectstart', onSessionEvent );
session.addEventListener( 'selectend', onSessionEvent );
session.addEventListener( 'squeeze', onSessionEvent );
session.addEventListener( 'squeezestart', onSessionEvent );
session.addEventListener( 'squeezeend', onSessionEvent );
session.addEventListener( 'end', onSessionEnd );
const attributes = gl.getContextAttributes();
if ( attributes.xrCompatible !== true ) {
gl.makeXRCompatible();
}
const layerInit = {
antialias: attributes.antialias,
alpha: attributes.alpha,
depth: attributes.depth,
stencil: attributes.stencil,
framebufferScaleFactor: framebufferScaleFactor
};
// eslint-disable-next-line no-undef
const baseLayer = new XRWebGLLayer( session, gl, layerInit );
session.updateRenderState( { baseLayer: baseLayer } );
session.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );
//
session.addEventListener( 'inputsourceschange', updateInputSources );
}
};
Suggested setSession Code
this.setSession = function ( value ) {
session = value;
if ( session !== null ) {
session.addEventListener( 'select', onSessionEvent );
session.addEventListener( 'selectstart', onSessionEvent );
session.addEventListener( 'selectend', onSessionEvent );
session.addEventListener( 'squeeze', onSessionEvent );
session.addEventListener( 'squeezestart', onSessionEvent );
session.addEventListener( 'squeezeend', onSessionEvent );
session.addEventListener( 'end', onSessionEnd );
const attributes = gl.getContextAttributes();
const setSession = function() {
const layerInit = {
antialias: attributes.antialias,
alpha: attributes.alpha,
depth: attributes.depth,
stencil: attributes.stencil,
framebufferScaleFactor: framebufferScaleFactor
};
// eslint-disable-next-line no-undef
const baseLayer = new XRWebGLLayer( session, gl, layerInit );
session.updateRenderState( { baseLayer: baseLayer } );
session.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );
//
session.addEventListener( 'inputsourceschange', updateInputSources );
};
if ( attributes.xrCompatible !== true ) {
gl.makeXRCompatible( setSession );
} else {
setSession();
}
}
};
Screenshots
Platform:
- Device: Mobile (Samsung Galaxy S20 Ultra - Exynos variant)
- OS: Android 11
- Browser: Chrome Canary 89.0.4329.2
- Three.js version: dev, r122
I can create a pull request myself, I just remember that the way to do is on this repo isn’t so straghtfarward.
Fork dev?
Build and then push?
If someone wants to do it be my guest. If not, please provide a link or explains how to do it right.
Thanks.
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (5 by maintainers)
Top GitHub Comments
@jpryne Please read #21126 for more details.
Just upgraded to Chrome 88.0.4324.96 & I’m facing this issue starting a WebXR session in 𝚕̶𝚘̶𝚌̶𝚊̶𝚕̶𝚑̶𝚘̶𝚜̶𝚝̶ testing. Windows 10 64, Oculus Rift CV1
Correction: This is broken when loading the examples from the server too. As of updating to Chrome 88, I can no longer view ThreeJS-VR in Chrome. I can however still enter WebXR at https://immersive-web.github.io/webxr-samples/
ThreeJS Examples are working fine in Microsoft Edge.