Skip to content
Open
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
864 changes: 783 additions & 81 deletions build/three.cjs

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions build/three.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -47613,6 +47613,21 @@ class ObjectLoader extends Loader {
geometry = bufferGeometryLoader.parse( data );
break;

case 'Geometry':

if ( 'THREE' in window && 'LegacyJSONLoader' in THREE ) {

var geometryLoader = new THREE.LegacyJSONLoader();
geometry = geometryLoader.parse( data, this.resourcePath ).geometry;


} else {

console.error( 'THREE.ObjectLoader: You have to import LegacyJSONLoader in order load geometry data of type "Geometry".' );

}
break;

default:

if ( data.type in Geometries ) {
Expand Down
2 changes: 1 addition & 1 deletion build/three.core.min.js

Large diffs are not rendered by default.

855 changes: 771 additions & 84 deletions build/three.module.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/three.module.min.js

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ class WebGLRenderer {

// xr

const xr = new WebXRManager( _this, _gl );
const xr = new WebXRManager( _this, _gl, extensions, multiviewStereo );

/**
* A reference to the XR manager.
Expand Down Expand Up @@ -1687,6 +1687,8 @@ class WebGLRenderer {

if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );

textures.runDeferredUploads();

// _gl.finish();

bindingStates.resetDefaultState();
Expand Down Expand Up @@ -2709,9 +2711,15 @@ class WebGLRenderer {
this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) {

const renderTargetProperties = properties.get( renderTarget );
if ( xr.isSpaceWarp === true ) {

renderTargetProperties.__autoAllocateDepthBuffer = true;
renderTarget.resolveDepthBuffer = false;

}

renderTargetProperties.__autoAllocateDepthBuffer = renderTarget.resolveDepthBuffer === false;
if ( ! renderTargetProperties.__autoAllocateDepthBuffer === false && ( ! _currentRenderTarget || ! _currentRenderTarget.isWebGLMultiviewRenderTarget ) ) {
if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) {

// The multisample_render_to_texture extension doesn't work properly if there
// are midframe flushes and an external depth buffer. Disable use of the extension.
Expand Down
2 changes: 1 addition & 1 deletion src/renderers/webgl/WebGLPrograms.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
if ( parameters.alphaToCoverage )
_programLayers.enable( 21 );
if ( parameters.numMultiviewViews )
_programLayers.enable( 21 );
_programLayers.enable( 22 );

array.push( _programLayers.mask );

Expand Down
1 change: 1 addition & 0 deletions src/renderers/webgl/WebGLTextures.js
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );

}
}

function setDeferTextureUploads( deferFlag ) {

Expand Down
41 changes: 28 additions & 13 deletions src/renderers/webxr/WebXRManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ 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';
import { WebXRSpaceWarp } from './WebXRSpaceWarp.js';

/**
* This class represents an abstraction of the WebXR Device API and is
Expand Down Expand Up @@ -82,6 +83,8 @@ class WebXRManager extends EventDispatcher {
let _currentDepthNear = null;
let _currentDepthFar = null;

this.spaceWarp = new WebXRSpaceWarp( renderer, gl );

/**
* Whether the manager's XR camera should be automatically updated or not.
*
Expand Down Expand Up @@ -110,6 +113,7 @@ class WebXRManager extends EventDispatcher {
*/
this.isPresenting = false;
this.isMultiview = false;
this.isSpaceWarp = false;

this.getCameraPose = function ( ) {

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

if ( scope.spaceWarp ) scope.spaceWarp.dispose();

depthSensing.reset();

// restore framebuffer/rendering state
Expand Down Expand Up @@ -465,6 +471,7 @@ class WebXRManager extends EventDispatcher {
}

scope.isMultiview = useMultiview && extensions.has( 'OCULUS_multiview' );
scope.isSpaceWarp = scope.isMultiview && ( renderer.spaceWarp === true );

const projectionlayerInit = {
colorFormat: gl.RGBA8,
Expand Down Expand Up @@ -943,6 +950,7 @@ class WebXRManager extends EventDispatcher {

pose = frame.getViewerPose( customReferenceSpace || referenceSpace );
xrFrame = frame;
let glSubImage = null;

if ( pose !== null ) {

Expand Down Expand Up @@ -978,21 +986,9 @@ class WebXRManager extends EventDispatcher {

} else {

const glSubImage = glBinding.getViewSubImage( glProjLayer, view );
glSubImage = glBinding.getViewSubImage( glProjLayer, view );
viewport = glSubImage.viewport;

// For side-by-side projection, we only produce a single texture for both eyes.
if ( i === 0 ) {

renderer.setRenderTargetTextures(
newRenderTarget,
glSubImage.colorTexture,
glSubImage.depthStencilTexture );

renderer.setRenderTarget( newRenderTarget );

}

}

let camera = cameras[ i ];
Expand Down Expand Up @@ -1027,6 +1023,18 @@ class WebXRManager extends EventDispatcher {

}

// Setup multiview render target for the main color pass.
if ( glSubImage ) {

renderer.setRenderTargetTextures(
newRenderTarget,
glSubImage.colorTexture,
glSubImage.depthStencilTexture );

renderer.setRenderTarget( newRenderTarget );

}

//

const enabledFeatures = session.enabledFeatures;
Expand Down Expand Up @@ -1065,6 +1073,13 @@ class WebXRManager extends EventDispatcher {

if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );

// Run motion vector pass after the app callback so current-frame transforms are up to date.
if ( scope.isSpaceWarp && glSubImage ) {

scope.spaceWarp.render( glSubImage, cameraXR );

}

if ( frame.detectedPlanes ) {

scope.dispatchEvent( { type: 'planesdetected', data: frame } );
Expand Down
174 changes: 174 additions & 0 deletions src/renderers/webxr/WebXRSpaceWarp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { Scene } from '../../scenes/Scene.js';
import { DepthTexture } from '../../textures/DepthTexture.js';
import { RGBAFormat, HalfFloatType, NearestFilter, NoColorSpace, DepthStencilFormat, DepthFormat, UnsignedInt248Type, UnsignedIntType } from '../../constants.js';
import { WebGLMultiviewRenderTarget } from '../WebGLMultiviewRenderTarget.js';

/**
* A XR module that renders motion vectors for SpaceWarp in a second lower-resolution pass.
*/
class WebXRSpaceWarp {

constructor( renderer, gl ) {

this.renderer = renderer;
this.gl = gl;
this.multiviewExt = gl.getExtension( 'OVR_multiview2' );

this.frameBuffer = null;
this.motionVectorRenderTarget = null;

this.scene = new Scene();

}

isSupported() {

return this.multiviewExt !== null;

}

hasValidSubImage( glSubImage ) {

return !!(
glSubImage &&
glSubImage.motionVectorTexture &&
glSubImage.depthStencilTexture &&
Number.isFinite( glSubImage.motionVectorTextureWidth ) &&
Number.isFinite( glSubImage.motionVectorTextureHeight )
);

}

needsReinit( glSubImage ) {

if ( ! this.motionVectorRenderTarget ) return true;

return (
this.motionVectorRenderTarget.width !== glSubImage.motionVectorTextureWidth ||
this.motionVectorRenderTarget.height !== glSubImage.motionVectorTextureHeight
);

}

render( glSubImage, cameraXR ) {

if ( ! this.isSupported() ) return false;
if ( ! this.hasValidSubImage( glSubImage ) ) return false;
if ( ! cameraXR || ! cameraXR.cameras || cameraXR.cameras.length < 2 ) return false;

if ( this.needsReinit( glSubImage ) ) this.initRenderTarget( glSubImage );
if ( ! this.motionVectorRenderTarget || ! this.frameBuffer ) return false;

const { renderer, gl, multiviewExt } = this;
const prevRenderTarget = renderer.getRenderTarget();
const depthAttachment = gl.getContextAttributes().stencil ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;

const leftCam = cameraXR.cameras[ 0 ];
const rightCam = cameraXR.cameras[ 1 ];
if ( ! leftCam || ! rightCam || ! leftCam.viewport || ! rightCam.viewport ) return false;

const w = this.motionVectorRenderTarget.width;
const h = this.motionVectorRenderTarget.height;

// Save viewports (No GC)
const lvp = leftCam.viewport, rvp = rightCam.viewport;
const lx = lvp.x, ly = lvp.y, lw = lvp.z, lh = lvp.w;
const rx = rvp.x, ry = rvp.y, rw = rvp.z, rh = rvp.w;

try {

gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, this.frameBuffer );

multiviewExt.framebufferTextureMultiviewOVR( gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, glSubImage.motionVectorTexture, 0, 0, 2 );
multiviewExt.framebufferTextureMultiviewOVR( gl.DRAW_FRAMEBUFFER, depthAttachment, glSubImage.depthStencilTexture, 0, 0, 2 );

renderer.setRenderTarget( this.motionVectorRenderTarget );
renderer.clear();

// Force full size for this target
lvp.set( 0, 0, w, h );
rvp.set( 0, 0, w, h );

renderer.render( this.scene, cameraXR );

return true;

} finally {

// Restore viewports
lvp.set( lx, ly, lw, lh );
rvp.set( rx, ry, rw, rh );

renderer.setRenderTarget( prevRenderTarget );

}

}

initRenderTarget( glSubImage ) {

if ( ! this.hasValidSubImage( glSubImage ) ) return;

const { renderer, gl } = this;
const width = glSubImage.motionVectorTextureWidth;
const height = glSubImage.motionVectorTextureHeight;

if ( this.motionVectorRenderTarget &&
this.motionVectorRenderTarget.width === width &&
this.motionVectorRenderTarget.height === height ) {

return;

}

if ( this.motionVectorRenderTarget ) {

this.motionVectorRenderTarget.dispose();
this.motionVectorRenderTarget = null;

}

const attributes = gl.getContextAttributes();
const depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat;
const depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType;

const motionVectorOptions = {
format: RGBAFormat,
type: HalfFloatType,
minFilter: NearestFilter,
magFilter: NearestFilter,
colorSpace: NoColorSpace,
stencilBuffer: attributes.stencil,
depthTexture: new DepthTexture( width, height, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ),
samples: 0
};

this.motionVectorRenderTarget = new WebGLMultiviewRenderTarget( width, height, 2, motionVectorOptions );
this.motionVectorRenderTarget.ignoreDepthValues = false;

if ( ! this.frameBuffer ) this.frameBuffer = renderer.getContext().createFramebuffer();
renderer.setRenderTargetFramebuffer( this.motionVectorRenderTarget, this.frameBuffer );

}

dispose() {

if ( this.motionVectorRenderTarget ) {

this.motionVectorRenderTarget.dispose();
this.motionVectorRenderTarget = null;

}

if ( this.frameBuffer ) {

this.gl.deleteFramebuffer( this.frameBuffer );
this.frameBuffer = null;

}

}

}

export { WebXRSpaceWarp };