|
@@ -40,6 +40,7 @@ import { WebGLState } from './webgl/WebGLState.js';
|
|
import { WebGLTextures } from './webgl/WebGLTextures.js';
|
|
import { WebGLTextures } from './webgl/WebGLTextures.js';
|
|
import { WebGLUniforms } from './webgl/WebGLUniforms.js';
|
|
import { WebGLUniforms } from './webgl/WebGLUniforms.js';
|
|
import { WebGLUtils } from './webgl/WebGLUtils.js';
|
|
import { WebGLUtils } from './webgl/WebGLUtils.js';
|
|
|
|
+import { WebGLMultiview } from './webgl/WebGLMultiview.js';
|
|
import { WebVRManager } from './webvr/WebVRManager.js';
|
|
import { WebVRManager } from './webvr/WebVRManager.js';
|
|
import { WebXRManager } from './webvr/WebXRManager.js';
|
|
import { WebXRManager } from './webvr/WebXRManager.js';
|
|
|
|
|
|
@@ -58,6 +59,8 @@ function WebGLRenderer( parameters ) {
|
|
var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
|
|
var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
|
|
_context = parameters.context !== undefined ? parameters.context : null,
|
|
_context = parameters.context !== undefined ? parameters.context : null,
|
|
|
|
|
|
|
|
+ _multiview = parameters.multiview !== undefined ? parameters.multiview : false,
|
|
|
|
+
|
|
_alpha = parameters.alpha !== undefined ? parameters.alpha : false,
|
|
_alpha = parameters.alpha !== undefined ? parameters.alpha : false,
|
|
_depth = parameters.depth !== undefined ? parameters.depth : true,
|
|
_depth = parameters.depth !== undefined ? parameters.depth : true,
|
|
_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
|
|
_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
|
|
@@ -312,6 +315,20 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
this.vr = vr;
|
|
this.vr = vr;
|
|
|
|
|
|
|
|
+
|
|
|
|
+ if ( _multiview && ! capabilities.multiview ) {
|
|
|
|
+
|
|
|
|
+ console.warn( 'WebGLRenderer: Multiview requested but not supported by the browser' );
|
|
|
|
+ this.vr.multiview = false;
|
|
|
|
+
|
|
|
|
+ } else if ( _multiview !== false && capabilities.multiview ) {
|
|
|
|
+
|
|
|
|
+ console.info( 'WebGLRenderer: Multiview enabled' );
|
|
|
|
+ this.vr.multiview = true;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
// shadow map
|
|
// shadow map
|
|
|
|
|
|
var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
|
|
var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
|
|
@@ -1360,44 +1377,95 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ var multiviewObject = new WebGLMultiview(_gl, _canvas, extensions );
|
|
|
|
+
|
|
function renderObjects( renderList, scene, camera, overrideMaterial ) {
|
|
function renderObjects( renderList, scene, camera, overrideMaterial ) {
|
|
|
|
|
|
- for ( var i = 0, l = renderList.length; i < l; i ++ ) {
|
|
|
|
|
|
+ if ( vr.multiview ) {
|
|
|
|
+ multiviewObject.bindMultiviewFrameBuffer();
|
|
|
|
+
|
|
|
|
+ _gl.disable( _gl.SCISSOR_TEST );
|
|
|
|
+
|
|
|
|
+ var width = _canvas.width;
|
|
|
|
+ var height = _canvas.height;
|
|
|
|
+
|
|
|
|
+ var halfWidth = Math.floor(width * 0.5);
|
|
|
|
+
|
|
|
|
+ _gl.viewport( 0, 0, halfWidth, height );
|
|
|
|
+ renderer.setViewport( 0, 0, halfWidth, height );
|
|
|
|
+
|
|
|
|
+ _gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT | _gl.STENCIL_BUFFER_BIT );
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, l = renderList.length; i < l; i ++ ) {
|
|
|
|
|
|
- var renderItem = renderList[ i ];
|
|
|
|
|
|
+ var renderItem = renderList[ i ];
|
|
|
|
|
|
- var object = renderItem.object;
|
|
|
|
- var geometry = renderItem.geometry;
|
|
|
|
- var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
|
|
|
|
- var group = renderItem.group;
|
|
|
|
|
|
+ var object = renderItem.object;
|
|
|
|
+ var geometry = renderItem.geometry;
|
|
|
|
+ var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
|
|
|
|
+ var group = renderItem.group;
|
|
|
|
|
|
- if ( camera.isArrayCamera ) {
|
|
|
|
|
|
+ renderObject( object, scene, camera, geometry, material, group );
|
|
|
|
|
|
- _currentArrayCamera = camera;
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ multiviewObject.unbindMultiviewFrameBuffer();
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, l = renderList.length; i < l; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var renderItem = renderList[ i ];
|
|
|
|
+
|
|
|
|
+ var object = renderItem.object;
|
|
|
|
+ var geometry = renderItem.geometry;
|
|
|
|
+ var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
|
|
|
|
+ var group = renderItem.group;
|
|
|
|
+
|
|
|
|
+ if ( camera.isArrayCamera ) {
|
|
|
|
|
|
- var cameras = camera.cameras;
|
|
|
|
|
|
+ _currentArrayCamera = camera;
|
|
|
|
|
|
- for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
|
|
|
|
|
|
+ var cameras = camera.cameras;
|
|
|
|
|
|
- var camera2 = cameras[ j ];
|
|
|
|
|
|
+ for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
|
|
|
|
|
|
- if ( object.layers.test( camera2.layers ) ) {
|
|
|
|
|
|
+ var camera2 = cameras[ j ];
|
|
|
|
|
|
- state.viewport( _currentViewport.copy( camera2.viewport ) );
|
|
|
|
|
|
+ if ( object.layers.test( camera2.layers ) ) {
|
|
|
|
+
|
|
|
|
+ if ( 'viewport' in camera2 ) { // XR
|
|
|
|
+
|
|
|
|
+ state.viewport( _currentViewport.copy( camera2.viewport ) );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ var bounds = camera2.bounds;
|
|
|
|
+
|
|
|
|
+ var x = bounds.x * _width;
|
|
|
|
+ var y = bounds.y * _height;
|
|
|
|
+ var width = bounds.z * _width;
|
|
|
|
+ var height = bounds.w * _height;
|
|
|
|
+
|
|
|
|
+ state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- currentRenderState.setupLights( camera2 );
|
|
|
|
|
|
+ currentRenderState.setupLights( camera2 );
|
|
|
|
|
|
- renderObject( object, scene, camera2, geometry, material, group );
|
|
|
|
|
|
+ renderObject( object, scene, camera2, geometry, material, group );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ _currentArrayCamera = null;
|
|
|
|
|
|
- _currentArrayCamera = null;
|
|
|
|
|
|
+ renderObject( object, scene, camera, geometry, material, group );
|
|
|
|
|
|
- renderObject( object, scene, camera, geometry, material, group );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1682,7 +1750,24 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
if ( refreshProgram || _currentCamera !== camera ) {
|
|
if ( refreshProgram || _currentCamera !== camera ) {
|
|
|
|
|
|
- p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
|
|
|
|
|
|
+ if ( vr.multiview ) {
|
|
|
|
+
|
|
|
|
+ if ( false && vr.isPresenting() ) {
|
|
|
|
+
|
|
|
|
+ // @todo Obviously remove the map :)
|
|
|
|
+ p_uniforms.setValue( _gl, 'projectionMatrices', camera.cameras.map( c => c.projectionMatrix ) );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ p_uniforms.setValue( _gl, 'projectionMatrices', [ camera.projectionMatrix, camera.projectionMatrix ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
if ( capabilities.logarithmicDepthBuffer ) {
|
|
if ( capabilities.logarithmicDepthBuffer ) {
|
|
|
|
|
|
@@ -1730,7 +1815,27 @@ function WebGLRenderer( parameters ) {
|
|
material.isShaderMaterial ||
|
|
material.isShaderMaterial ||
|
|
material.skinning ) {
|
|
material.skinning ) {
|
|
|
|
|
|
- p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
|
|
|
|
|
|
+ if ( vr.multiview ) {
|
|
|
|
+
|
|
|
|
+ if ( vr.isPresenting() ) {
|
|
|
|
+
|
|
|
|
+ // @todo Obviously remove the map :)
|
|
|
|
+ p_uniforms.setValue( _gl, 'viewMatrix', camera.cameras.map( c => c.matrixWorldInverse ) );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ var newMat = camera.matrixWorldInverse.clone();
|
|
|
|
+ var newMat = new Matrix4();
|
|
|
|
+
|
|
|
|
+ p_uniforms.setValue( _gl, 'viewMatrices', [camera.matrixWorldInverse, newMat] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|