Skip to content

Commit

Permalink
WebXRManager: Added depth sensing support (v2). (#27586)
Browse files Browse the repository at this point in the history
* add support for depth sensing

* add support for depth sensing

* use EXT_frag_depth for depth sensing

* Create WebXRDepthSensing

* Rename WebXRDepthSensing to WebXRDepthSensing.js

* Update WebXRManager.js

* Update WebXRDepthSensing.js

* Update WebXRManager.js

* Update WebXRDepthSensing.js

* Update WebXRDepthSensing.js

* Update WebXRDepthSensing.js

* Update WebXRManager.js

* pass correct depth/far clip in non-occlusion cases

* Update WebGLRenderer.js

* Update WebXRManager.js

---------

Co-authored-by: mrdoob <info@mrdoob.com>
  • Loading branch information
cabanier and mrdoob authored Jan 31, 2024
1 parent 1b35d64 commit 6e3137a
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 4 deletions.
2 changes: 1 addition & 1 deletion examples/webxr_xr_ballshooter.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
controls.target.y = 1.6;
controls.update();

document.body.appendChild( XRButton.createButton( renderer ) );
document.body.appendChild( XRButton.createButton( renderer, { 'optionalFeatures': [ 'depth-sensing'] } ) );

// controllers

Expand Down
2 changes: 1 addition & 1 deletion examples/webxr_xr_cubes.html
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@

//

document.body.appendChild( XRButton.createButton( renderer ) );
document.body.appendChild( XRButton.createButton( renderer, { 'optionalFeatures': [ 'depth-sensing'] } ) );

}

Expand Down
2 changes: 1 addition & 1 deletion examples/webxr_xr_dragging.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
renderer.xr.enabled = true;
container.appendChild( renderer.domElement );

document.body.appendChild( XRButton.createButton( renderer ) );
document.body.appendChild( XRButton.createButton( renderer, { 'optionalFeatures': [ 'depth-sensing'] } ) );

// controllers

Expand Down
6 changes: 5 additions & 1 deletion src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,11 @@ class WebGLRenderer {

//

background.render( currentRenderList, scene );
if ( xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false ) {

background.render( currentRenderList, scene );

}

// render scene

Expand Down
105 changes: 105 additions & 0 deletions src/renderers/webxr/WebXRDepthSensing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { PlaneGeometry } from '../../geometries/PlaneGeometry.js';
import { ShaderMaterial } from '../../materials/ShaderMaterial.js';
import { Mesh } from '../../objects/Mesh.js';
import { Texture } from '../../textures/Texture.js';

const _occlusion_vertex = `
void main() {
gl_Position = vec4( position, 1.0 );
}`;

const _occlusion_fragment = `
uniform sampler2DArray depthColor;
uniform float depthWidth;
uniform float depthHeight;
void main() {
vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );
if ( coord.x >= 1.0 ) {
gl_FragDepthEXT = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;
} else {
gl_FragDepthEXT = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;
}
}`;

class WebXRDepthSensing {

constructor() {

this.texture = null;
this.mesh = null;

this.depthNear = 0;
this.depthFar = 0;

}

init( renderer, depthData, renderState ) {

if ( this.texture === null ) {

const texture = new Texture();

const texProps = renderer.properties.get( texture );
texProps.__webglTexture = depthData.texture;

if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) {

this.depthNear = depthData.depthNear;
this.depthFar = depthData.depthFar;

}

this.texture = texture;

}

}

render( renderer, cameraXR ) {

if ( this.texture !== null ) {

if ( this.mesh === null ) {

const viewport = cameraXR.cameras[ 0 ].viewport;
const material = new ShaderMaterial( {
extensions: { fragDepth: true },
vertexShader: _occlusion_vertex,
fragmentShader: _occlusion_fragment,
uniforms: {
depthColor: { value: this.texture },
depthWidth: { value: viewport.z },
depthHeight: { value: viewport.w }
}
} );

this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material );

}

renderer.render( this.mesh, cameraXR );

}

}

reset() {

this.texture = null;
this.mesh = null;

}

}

export { WebXRDepthSensing };
46 changes: 46 additions & 0 deletions src/renderers/webxr/WebXRManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
import { WebXRController } from './WebXRController.js';
import { DepthTexture } from '../../textures/DepthTexture.js';
import { DepthFormat, DepthStencilFormat, RGBAFormat, UnsignedByteType, UnsignedIntType, UnsignedInt248Type } from '../../constants.js';
import { WebXRDepthSensing } from './WebXRDepthSensing.js';

class WebXRManager extends EventDispatcher {

Expand All @@ -34,7 +35,10 @@ class WebXRManager extends EventDispatcher {
let glProjLayer = null;
let glBaseLayer = null;
let xrFrame = null;

const depthSensing = new WebXRDepthSensing();
const attributes = gl.getContextAttributes();

let initialRenderTarget = null;
let newRenderTarget = null;

Expand Down Expand Up @@ -164,6 +168,8 @@ class WebXRManager extends EventDispatcher {
_currentDepthNear = null;
_currentDepthFar = null;

depthSensing.reset();

// restore framebuffer/rendering state

renderer.setRenderTarget( initialRenderTarget );
Expand Down Expand Up @@ -522,6 +528,13 @@ class WebXRManager extends EventDispatcher {

if ( session === null ) return;

if ( depthSensing.texture !== null ) {

camera.near = depthSensing.depthNear;
camera.far = depthSensing.depthFar;

}

cameraXR.near = cameraR.near = cameraL.near = camera.near;
cameraXR.far = cameraR.far = cameraL.far = camera.far;

Expand All @@ -537,6 +550,15 @@ class WebXRManager extends EventDispatcher {
_currentDepthNear = cameraXR.near;
_currentDepthFar = cameraXR.far;

cameraL.near = _currentDepthNear;
cameraL.far = _currentDepthFar;
cameraR.near = _currentDepthNear;
cameraR.far = _currentDepthFar;

cameraL.updateProjectionMatrix();
cameraR.updateProjectionMatrix();
camera.updateProjectionMatrix();

}

const parent = camera.parent;
Expand Down Expand Up @@ -638,6 +660,12 @@ class WebXRManager extends EventDispatcher {

};

this.hasDepthSensing = function () {

return depthSensing.texture !== null;

};

// Animation Loop

let onAnimationFrameCallback = null;
Expand Down Expand Up @@ -730,6 +758,22 @@ class WebXRManager extends EventDispatcher {

}

//

const enabledFeatures = session.enabledFeatures;

if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) {

const depthData = glBinding.getDepthInformation( views[ 0 ] );

if ( depthData && depthData.isValid && depthData.texture ) {

depthSensing.init( renderer, depthData, session.renderState );

}

}

}

//
Expand All @@ -747,6 +791,8 @@ class WebXRManager extends EventDispatcher {

}

depthSensing.render( renderer, cameraXR );

if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );

if ( frame.detectedPlanes ) {
Expand Down

0 comments on commit 6e3137a

Please sign in to comment.