|
@@ -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();
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|