From 9072316c141438472b9b9f873f88ee4f4a449c40 Mon Sep 17 00:00:00 2001 From: Fernando Serrano Date: Tue, 23 Apr 2019 01:14:03 +0200 Subject: [PATCH] Added arrayCamera support on multiview --- src/renderers/WebGLRenderer.js | 44 ++++---- src/renderers/webgl/WebGLCapabilities.js | 14 ++- src/renderers/webgl/WebGLMultiview.js | 131 +++++++++++++++-------- src/renderers/webgl/WebGLProgram.js | 8 +- 4 files changed, 114 insertions(+), 83 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 549fae9605..03a1933d7e 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -315,19 +315,8 @@ function WebGLRenderer( parameters ) { 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; - - } - + var multiviewObject = new WebGLMultiview(_multiview, _gl, _canvas, extensions, capabilities ); + var multiviewEnabled = this.multiviewEnabled = multiviewObject.isEnabled(); // shadow map @@ -1377,22 +1366,27 @@ function WebGLRenderer( parameters ) { } - var multiviewObject = new WebGLMultiview(_gl, _canvas, extensions ); - function renderObjects( renderList, scene, camera, overrideMaterial ) { - if ( vr.multiview ) { - multiviewObject.bindMultiviewFrameBuffer(); + if ( multiviewEnabled ) { + + multiviewObject.bindMultiviewFrameBuffer( camera ); _gl.disable( _gl.SCISSOR_TEST ); - var width = _canvas.width; - var height = _canvas.height; + if ( camera.isArrayCamera ) { + + var height = _canvas.height; + var width = Math.floor( _canvas.width * 0.5 ); - var halfWidth = Math.floor(width * 0.5); + } else { + + var width = _canvas.width; + var height = _canvas.height; - _gl.viewport( 0, 0, halfWidth, height ); - renderer.setViewport( 0, 0, halfWidth, height ); + } + _gl.viewport( 0, 0, width, height ); + renderer.setViewport( 0, 0, width, height ); _gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT | _gl.STENCIL_BUFFER_BIT ); @@ -1409,7 +1403,7 @@ function WebGLRenderer( parameters ) { } - multiviewObject.unbindMultiviewFrameBuffer(); + multiviewObject.unbindMultiviewFrameBuffer( camera ); } else { @@ -1750,7 +1744,7 @@ function WebGLRenderer( parameters ) { if ( refreshProgram || _currentCamera !== camera ) { - if ( vr.multiview ) { + if ( multiviewEnabled ) { if ( false && vr.isPresenting() ) { @@ -1815,7 +1809,7 @@ function WebGLRenderer( parameters ) { material.isShaderMaterial || material.skinning ) { - if ( vr.multiview ) { + if ( multiviewEnabled ) { if ( vr.isPresenting() ) { diff --git a/src/renderers/webgl/WebGLCapabilities.js b/src/renderers/webgl/WebGLCapabilities.js index 70c219dbe2..d30ea49ef5 100644 --- a/src/renderers/webgl/WebGLCapabilities.js +++ b/src/renderers/webgl/WebGLCapabilities.js @@ -86,13 +86,10 @@ function WebGLCapabilities( gl, extensions, parameters ) { var maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0; - var multiview = isWebGL2 && ( !! extensions.get( 'WEBGL_multiview' ) || !! extensions.get( 'OVR_multiview' ) || !! extensions.get( 'OVR_multiview2' ) ); -/* - var ovrMultiview2 = extensions.get( 'OVR_multiview2' ); - if (ovrMultiview2) { - var num = gl.getParameter(ovrMultiview2.MAX_VIEWS_OVR); - } -*/ + var multiviewExt = extensions.get( 'OVR_multiview2' ); + var multiview = isWebGL2 && ( !! multiviewExt ); + var maxMultiviewViews = multiview ? gl.getParameter(multiviewExt.MAX_VIEWS_OVR) : 1; + return { isWebGL2: isWebGL2, @@ -119,7 +116,8 @@ function WebGLCapabilities( gl, extensions, parameters ) { maxSamples: maxSamples, - multiview: multiview + multiview: multiview, + maxMultiviewViews: maxMultiviewViews }; diff --git a/src/renderers/webgl/WebGLMultiview.js b/src/renderers/webgl/WebGLMultiview.js index 0b92eff518..79d3beddcc 100644 --- a/src/renderers/webgl/WebGLMultiview.js +++ b/src/renderers/webgl/WebGLMultiview.js @@ -1,38 +1,45 @@ +function WebGLMultiview( requested, gl, canvas, extensions, capabilities ) { -function err() { + this.isAvailable = function () { - console.error( bgl.getError() ); + return capabilities.multiview; -} + } -var bgl; + this.getMaxViews = function () { -function WebGLMultiview( gl, canvas, extensions ) { + return capabilities.maxMultiviewViews; - var NUM_MULTIVIEW_VIEWS = 2; - bgl = gl; - var width = canvas.width; - var height = canvas.height; - var g_multiviewFb; // multiview framebuffer. - var g_multiviewViewFb; // single views inside the multiview framebuffer. - var g_multiviewColorTexture; // Color texture for multiview framebuffer. - var g_multiviewDepth; // Depth texture for multiview framebuffer. - var g_multiviewFbWidth = 0; - var g_multiviewFbHeight = 0; + } + this.isEnabled = function () { + + return requested && this.isAvailable(); - var ext = extensions.get( 'OVR_multiview2' ); - if (!ext) { - return; } + + if ( requested && ! this.isAvailable() ) { + + console.warn( 'WebGLRenderer: Multiview requested but not supported by the browser' ); + + } else if ( requested !== false && this.isAvailable() ) { + + console.info( 'WebGLRenderer: Multiview enabled' ); + + } + + var numViews = 2; + var framebuffer; // multiview framebuffer. + var viewFramebuffer; // single views inside the multiview framebuffer. + var framebufferWidth = 0; + var framebufferHeight = 0; + var texture = { color: null, depthStencil: null }; - var framebuffer = gl.createFramebuffer(); - var multiviewViewFb = null; this.createMultiviewRenderTargetTexture = function () { @@ -41,62 +48,94 @@ function WebGLMultiview( gl, canvas, extensions ) { framebuffer = gl.createFramebuffer(); gl.bindFramebuffer( gl.FRAMEBUFFER, framebuffer ); + var ext = extensions.get( 'OVR_multiview2' ); + texture.color = gl.createTexture(); gl.bindTexture( gl.TEXTURE_2D_ARRAY, texture.color ); gl.texParameteri( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); gl.texParameteri( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, halfWidth, canvas.height, NUM_MULTIVIEW_VIEWS, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); - ext.framebufferTextureMultiviewOVR( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture.color, 0, 0, NUM_MULTIVIEW_VIEWS ); + gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, halfWidth, canvas.height, numViews, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); + ext.framebufferTextureMultiviewOVR( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture.color, 0, 0, numViews ); texture.depthStencil = gl.createTexture(); gl.bindTexture( gl.TEXTURE_2D_ARRAY, texture.depthStencil ); gl.texParameteri( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); gl.texParameteri( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.DEPTH24_STENCIL8, halfWidth, canvas.height, NUM_MULTIVIEW_VIEWS, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null ); - ext.framebufferTextureMultiviewOVR( gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, texture.depthStencil, 0, 0, NUM_MULTIVIEW_VIEWS ); + gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.DEPTH24_STENCIL8, halfWidth, canvas.height, numViews, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null ); + ext.framebufferTextureMultiviewOVR( gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, texture.depthStencil, 0, 0, numViews ); - multiviewViewFb = [ null, null ]; - for ( var viewIndex = 0; viewIndex < 2; ++ viewIndex ) { + viewFramebuffer = new Array( numViews ); + for ( var viewIndex = 0; viewIndex < numViews; ++ viewIndex ) { - multiviewViewFb[ viewIndex ] = gl.createFramebuffer(); - gl.bindFramebuffer( gl.FRAMEBUFFER, multiviewViewFb[ viewIndex ] ); + viewFramebuffer[ viewIndex ] = gl.createFramebuffer(); + gl.bindFramebuffer( gl.FRAMEBUFFER, viewFramebuffer[ viewIndex ] ); gl.framebufferTextureLayer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture.color, 0, viewIndex ); } - g_multiviewFbWidth = halfWidth; - g_multiviewFbHeight = canvas.height; + framebufferWidth = halfWidth; + framebufferHeight = canvas.height; }; - this.bindMultiviewFrameBuffer = function () { + this.bindMultiviewFrameBuffer = function ( camera ) { var halfWidth = Math.floor( canvas.width * 0.5 ); - if ( g_multiviewFbWidth < halfWidth || g_multiviewFbHeight < canvas.height ) { - console.log( 'Updating multiview FBO with dimensions: ', halfWidth, canvas.height ); + if (camera.isArrayCamera) { + + } else { + halfWidth *= 2; + } + + if ( framebufferWidth < halfWidth || framebufferHeight < canvas.height ) { + console.log( 'WebGLMultiview: Updating multiview FBO with dimensions: ', halfWidth, canvas.height ); gl.bindTexture( gl.TEXTURE_2D_ARRAY, texture.color ); - gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, halfWidth, canvas.height, NUM_MULTIVIEW_VIEWS, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, halfWidth, canvas.height, numViews, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); gl.bindTexture( gl.TEXTURE_2D_ARRAY, texture.depthStencil ); - gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.DEPTH24_STENCIL8, halfWidth, canvas.height, NUM_MULTIVIEW_VIEWS, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null); - g_multiviewFbWidth = halfWidth; - g_multiviewFbHeight = canvas.height; + gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.DEPTH24_STENCIL8, halfWidth, canvas.height, numViews, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null); + framebufferWidth = halfWidth; + framebufferHeight = canvas.height; } - // gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, framebuffer ); }; - this.unbindMultiviewFrameBuffer = function () { + this.unbindMultiviewFrameBuffer = function ( camera ) { - var halfWidth = Math.floor( canvas.width * 0.5 ); - gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); - gl.bindFramebuffer( gl.READ_FRAMEBUFFER, multiviewViewFb[ 0 ] ); - gl.blitFramebuffer( 0, 0, halfWidth, canvas.height, 0, 0, halfWidth, canvas.height, gl.COLOR_BUFFER_BIT, gl.NEAREST ); - gl.bindFramebuffer( gl.READ_FRAMEBUFFER, multiviewViewFb[ 1 ] ); - gl.blitFramebuffer( 0, 0, halfWidth, canvas.height, halfWidth, 0, canvas.width, canvas.height, gl.COLOR_BUFFER_BIT, gl.NEAREST ); + gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); + + if ( camera.isArrayCamera ) { + + + for ( var i = 0; i < camera.cameras.length; i ++ ) { + + var bounds = camera.cameras[ i ].bounds; + + var x = bounds.x * canvas.width; + var y = bounds.y * canvas.height; + var width = bounds.z * canvas.width; + var height = bounds.w * canvas.height; + + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, viewFramebuffer[ i ] ); + gl.blitFramebuffer( 0, 0, width, height, x, y, x + width, y + height, gl.COLOR_BUFFER_BIT, gl.NEAREST ); + + } + + } else { + + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, viewFramebuffer[ 0 ] ); + gl.blitFramebuffer( 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height, gl.COLOR_BUFFER_BIT, gl.NEAREST ); + + } }; - this.createMultiviewRenderTargetTexture(); + + if ( this.isEnabled() ) { + + this.createMultiviewRenderTargetTexture(); + + } } diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index b660b98fff..c8425d3763 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -430,7 +430,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, 'uniform mat4 modelMatrix;', 'uniform vec3 cameraPosition;', - renderer.vr.multiview ? [ + renderer.multiviewEnabled ? [ 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrices[2];', 'uniform mat3 normalMatrix;', @@ -566,7 +566,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, 'uniform vec3 cameraPosition;', - renderer.vr.multiview ? [ + renderer.multiviewEnabled ? [ 'uniform mat4 viewMatrices[2];', '#define viewMatrix viewMatrices[VIEW_ID]' @@ -627,7 +627,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, prefixVertex = [ '#version 300 es\n', - renderer.vr.multiview ? [ + renderer.multiviewEnabled ? [ '#extension GL_OVR_multiview2 : require', 'layout(num_views = 2) in;', @@ -642,7 +642,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, prefixFragment = [ '#version 300 es\n', - renderer.vr.multiview ? [ + renderer.multiviewEnabled ? [ '#extension GL_OVR_multiview2 : require', '#define VIEW_ID gl_ViewID_OVR' -- GitLab