Browse Source

Switch to native MSAA for WebXR (#22230)

Rik Cabanier 4 years ago
parent
commit
3defafa0ce
1 changed files with 103 additions and 29 deletions
  1. 103 29
      src/renderers/webxr/WebXRManager.js

+ 103 - 29
src/renderers/webxr/WebXRManager.js

@@ -26,6 +26,12 @@ class WebXRManager extends EventDispatcher {
 		let glFramebuffer = null;
 		let glProjLayer = null;
 		let glBaseLayer = null;
+		let isMultisample = false;
+		let glMultisampledFramebuffer = null;
+		let glColorRenderbuffer = null;
+		let glDepthRenderbuffer = null;
+		let depthStyle = null;
+		let clearStyle = null;
 
 		const controllers = [];
 		const inputSourcesMap = new Map();
@@ -133,6 +139,15 @@ class WebXRManager extends EventDispatcher {
 			state.bindXRFramebuffer( null );
 			renderer.setRenderTarget( renderer.getRenderTarget() );
 
+			if ( glFramebuffer ) gl.deleteFramebuffer( glFramebuffer );
+			if ( glMultisampledFramebuffer ) gl.deleteFramebuffer( glMultisampledFramebuffer );
+			if ( glColorRenderbuffer ) gl.deleteRenderbuffer( glColorRenderbuffer );
+			if ( glDepthRenderbuffer ) gl.deleteRenderbuffer( glDepthRenderbuffer );
+			glFramebuffer = null;
+			glMultisampledFramebuffer = null;
+			glColorRenderbuffer = null;
+			glDepthRenderbuffer = null;
+
 			//
 
 			animation.stop();
@@ -216,46 +231,80 @@ class WebXRManager extends EventDispatcher {
 
 					session.updateRenderState( { baseLayer: glBaseLayer } );
 
+				} else if ( gl instanceof WebGLRenderingContext ) {
+
+					// Use old style webgl layer because we can't use MSAA
+					// WebGL2 support.
+
+					const layerInit = {
+						antialias: true,
+						alpha: attributes.alpha,
+						depth: attributes.depth,
+						stencil: attributes.stencil,
+						framebufferScaleFactor: framebufferScaleFactor
+					};
+
+					glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
+
+					session.updateRenderState( { layers: [ glBaseLayer ] } );
+
 				} else {
 
-					let depthFormat = 0;
+					isMultisample = attributes.antialias;
+					let depthFormat = null;
 
-					// for anti-aliased output, use classic webgllayer for now
-					if ( attributes.antialias ) {
 
-						const layerInit = {
-							antialias: true,
-							alpha: attributes.alpha,
-							depth: attributes.depth,
-							stencil: attributes.stencil,
-							framebufferScaleFactor: framebufferScaleFactor
-						};
+					if ( attributes.depth ) {
 
-						glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
+						clearStyle = gl.DEPTH_BUFFER_BIT;
 
-						session.updateRenderState( { layers: [ glBaseLayer ] } );
+						if ( attributes.stencil ) clearStyle |= gl.STENCIL_BUFFER_BIT;
 
-					} else {
+						depthStyle = attributes.stencil ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
+						depthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
 
-						if ( attributes.depth ) {
+					}
+
+					const projectionlayerInit = {
+						colorFormat: attributes.alpha ? gl.RGBA8 : gl.RGB8,
+						depthFormat: depthFormat,
+						scaleFactor: framebufferScaleFactor
+					};
 
-							depthFormat = attributes.stencil ? gl.DEPTH_STENCIL : gl.DEPTH_COMPONENT;
+					glBinding = new XRWebGLBinding( session, gl );
 
-						}
+					glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
 
-						const projectionlayerInit = {
-							colorFormat: attributes.alpha ? gl.RGBA : gl.RGB,
-							depthFormat: depthFormat,
-							scaleFactor: framebufferScaleFactor
-						};
+					glFramebuffer = gl.createFramebuffer();
 
-						glBinding = new XRWebGLBinding( session, gl );
+					session.updateRenderState( { layers: [ glProjLayer ] } );
 
-						glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
+					if ( isMultisample ) {
 
-						glFramebuffer = gl.createFramebuffer();
+						glMultisampledFramebuffer = gl.createFramebuffer();
+						glColorRenderbuffer = gl.createRenderbuffer();
+						gl.bindRenderbuffer( gl.RENDERBUFFER, glColorRenderbuffer );
+						gl.renderbufferStorageMultisample(
+							gl.RENDERBUFFER,
+							4,
+							gl.RGBA8,
+							glProjLayer.textureWidth,
+							glProjLayer.textureHeight );
+						state.bindFramebuffer( gl.FRAMEBUFFER, glMultisampledFramebuffer );
+						gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, glColorRenderbuffer );
+						gl.bindRenderbuffer( gl.RENDERBUFFER, null );
 
-						session.updateRenderState( { layers: [ glProjLayer ] } );
+						if ( depthFormat !== null ) {
+
+							glDepthRenderbuffer = gl.createRenderbuffer();
+							gl.bindRenderbuffer( gl.RENDERBUFFER, glDepthRenderbuffer );
+							gl.renderbufferStorageMultisample( gl.RENDERBUFFER, 4, depthFormat, glProjLayer.textureWidth, glProjLayer.textureHeight );
+							gl.framebufferRenderbuffer( gl.FRAMEBUFFER, depthStyle, gl.RENDERBUFFER, glDepthRenderbuffer );
+							gl.bindRenderbuffer( gl.RENDERBUFFER, null );
+
+						}
+
+						state.bindFramebuffer( gl.FRAMEBUFFER, null );
 
 					}
 
@@ -532,7 +581,6 @@ class WebXRManager extends EventDispatcher {
 
 					cameraVRNeedsUpdate = true;
 
-
 				}
 
 				for ( let i = 0; i < views.length; i ++ ) {
@@ -553,7 +601,7 @@ class WebXRManager extends EventDispatcher {
 
 						if ( glSubImage.depthStencilTexture !== undefined ) {
 
-							gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, glSubImage.depthStencilTexture, 0 );
+							gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, glSubImage.depthStencilTexture, 0 );
 
 						}
 
@@ -566,9 +614,7 @@ class WebXRManager extends EventDispatcher {
 					const camera = cameras[ i ];
 
 					camera.matrix.fromArray( view.transform.matrix );
-
 					camera.projectionMatrix.fromArray( view.projectionMatrix );
-
 					camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
 
 					if ( i === 0 ) {
@@ -585,6 +631,14 @@ class WebXRManager extends EventDispatcher {
 
 				}
 
+				if ( isMultisample ) {
+
+					state.bindXRFramebuffer( glMultisampledFramebuffer );
+
+					if ( clearStyle !== null ) gl.clear( clearStyle );
+
+				}
+
 			}
 
 			//
@@ -602,6 +656,26 @@ class WebXRManager extends EventDispatcher {
 
 			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
 
+			if ( isMultisample ) {
+
+				const width = glProjLayer.textureWidth;
+				const height = glProjLayer.textureHeight;
+
+				state.bindFramebuffer( gl.READ_FRAMEBUFFER, glMultisampledFramebuffer );
+				state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, glFramebuffer );
+				// Invalidate the depth here to avoid flush of the depth data to main memory.
+				gl.invalidateFramebuffer( gl.READ_FRAMEBUFFER, [ depthStyle ] );
+				gl.invalidateFramebuffer( gl.DRAW_FRAMEBUFFER, [ depthStyle ] );
+				gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST );
+				// Invalidate the MSAA buffer because it's not needed anymore.
+				gl.invalidateFramebuffer( gl.READ_FRAMEBUFFER, [ gl.COLOR_ATTACHMENT0 ] );
+				state.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
+				state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null );
+
+				state.bindFramebuffer( gl.FRAMEBUFFER, glMultisampledFramebuffer );
+
+			}
+
 		}
 
 		const animation = new WebGLAnimation();