WebGLMultiview.js 4.6 KB
Newer Older
1 2
/**
 * @author fernandojsg / http://fernandojsg.com
3
 * @author Takahiro https://github.com/takahirox
4 5
 */

6
import { WebGLMultiviewRenderTarget } from '../WebGLMultiviewRenderTarget.js';
7 8
import { Matrix3 } from '../../math/Matrix3.js';
import { Matrix4 } from '../../math/Matrix4.js';
9

10 11 12 13 14 15
function WebGLMultiview( renderer, requested ) {

	var gl = renderer.context;
	var canvas = renderer.domElement;
	var capabilities = renderer.capabilities;
	var properties = renderer.properties;
16

F
Fernando Serrano 已提交
17
	this.isAvailable = function () {
18

F
Fernando Serrano 已提交
19
		return capabilities.multiview;
20

F
Fernando Serrano 已提交
21
	};
22

23 24 25 26 27 28
	this.getNumViews = function () {

		return numViews;

	};

F
Fernando Serrano 已提交
29
	this.getMaxViews = function () {
30

F
Fernando Serrano 已提交
31
		return capabilities.maxMultiviewViews;
32

F
Fernando Serrano 已提交
33
	};
34

F
Fernando Serrano 已提交
35
	this.isEnabled = function () {
36

F
Fernando Serrano 已提交
37
		return requested && this.isAvailable();
38

F
Fernando Serrano 已提交
39
	};
40

41 42 43 44 45 46 47 48
	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' );

F
Fernando Serrano 已提交
49
	}
50

51
	var numViews = 2;
52
	var renderTarget, currentRenderTarget;
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67
	this.computeCameraMatrices = function ( camera ) {

		if ( ! camera.projectionMatrices ) {

			camera.projectionMatrices = new Array( numViews );
			camera.viewMatrices = new Array( numViews );

			for ( var i = 0; i < numViews; i ++ ) {

				camera.projectionMatrices[ i ] = new Matrix4();
				camera.viewMatrices[ i ] = new Matrix4();

			}

68
		}
69

70
		if ( camera.isArrayCamera ) {
71

72
			for ( var i = 0; i < numViews; i ++ ) {
73

74 75
				camera.projectionMatrices[ i ].copy( camera.cameras[ i ].projectionMatrix );
				camera.viewMatrices[ i ].copy( camera.cameras[ i ].matrixWorldInverse );
76

77
			}
78

79
		} else {
80

81
			for ( var i = 0; i < numViews; i ++ ) {
82

83 84
				camera.projectionMatrices[ i ].copy( camera.projectionMatrix );
				camera.viewMatrices[ i ].copy( camera.matrixWorldInverse );
85 86 87 88 89 90 91

			}

		}

	};

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
	this.computeObjectMatrices = function ( object, camera ) {

		if ( ! object.modelViewMatrices ) {

			object.modelViewMatrices = new Array( numViews );
			object.normalMatrices = new Array( numViews );

			for ( var i = 0; i < numViews; i ++ ) {

				object.modelViewMatrices[ i ] = new Matrix4();
				object.normalMatrices[ i ] = new Matrix3();

			}

		}

		if ( camera.isArrayCamera ) {

			for ( var i = 0; i < numViews; i ++ ) {

				object.modelViewMatrices[ i ].multiplyMatrices( camera.cameras[ i ].matrixWorldInverse, object.matrixWorld );
				object.normalMatrices[ i ].getNormalMatrix( object.modelViewMatrices[ i ] );

			}

		} else {

			// In this case we still need to provide an array of matrices but just the first one will be used
			object.modelViewMatrices[ 0 ].multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
			object.normalMatrices[ 0 ].getNormalMatrix( object.modelViewMatrices[ 0 ] );

123
			for ( var i = 1; i < numViews; i ++ ) {
124 125 126 127 128 129 130 131 132

				object.modelViewMatrices[ i ].copy( object.modelViewMatrices[ 0 ] );
				object.normalMatrices[ i ].copy( object.normalMatrices[ 0 ] );

			}

		}

	};
133

134
	this.attachRenderTarget = function ( camera ) {
135

136
		currentRenderTarget = renderer.getRenderTarget();
137

138
		// Resize if needed
F
Fernando Serrano 已提交
139 140 141 142
		var width = canvas.width;
		var height = canvas.height;

		if ( camera.isArrayCamera ) {
143

F
Fernando Serrano 已提交
144 145
			// Every camera must have the same size, so we just get the size from the first one
			var bounds = camera.cameras[ 0 ].bounds;
146

F
Fernando Serrano 已提交
147 148 149 150 151
			width *= bounds.z;
			height *= bounds.w;

		}

152
		renderTarget.setSize( width, height );
153

154
		renderer.setRenderTarget( renderTarget );
155 156 157

	};

158
	this.detachRenderTarget = function ( camera ) {
159

160 161 162 163
		var viewFramebuffers = properties.get( renderTarget ).__webglViewFramebuffers;

		// @todo Use actual framebuffer
		gl.bindFramebuffer( gl.FRAMEBUFFER, null );
164

F
Fernando Serrano 已提交
165
		if ( camera.isArrayCamera ) {
166

F
Fernando Serrano 已提交
167
			for ( var i = 0; i < camera.cameras.length; i ++ ) {
168

F
Fernando Serrano 已提交
169
				var bounds = camera.cameras[ i ].bounds;
170

F
Fernando Serrano 已提交
171 172 173 174
				var x = bounds.x * canvas.width;
				var y = bounds.y * canvas.height;
				var width = bounds.z * canvas.width;
				var height = bounds.w * canvas.height;
175

176
				gl.bindFramebuffer( gl.READ_FRAMEBUFFER, viewFramebuffers[ i ] );
F
Fernando Serrano 已提交
177
				gl.blitFramebuffer( 0, 0, width, height, x, y, x + width, y + height, gl.COLOR_BUFFER_BIT, gl.NEAREST );
178

F
Fernando Serrano 已提交
179
			}
180

F
Fernando Serrano 已提交
181
		} else {
182

183 184
			// If no array camera, blit just one view
			gl.bindFramebuffer( gl.READ_FRAMEBUFFER, viewFramebuffers[ 0 ] );
F
Fernando Serrano 已提交
185
			gl.blitFramebuffer( 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height, gl.COLOR_BUFFER_BIT, gl.NEAREST );
186

F
Fernando Serrano 已提交
187
		}
188

189 190
		renderer.setRenderTarget( currentRenderTarget );

191 192
	};

193

F
Fernando Serrano 已提交
194
	if ( this.isEnabled() ) {
195

196
		renderTarget = new WebGLMultiviewRenderTarget( canvas.width, canvas.height, numViews );
197

F
Fernando Serrano 已提交
198
	}
199 200 201 202

}

export { WebGLMultiview };