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
function WebGLMultiview( renderer, requested, options ) {

	options = Object.assign( {}, { debug: false }, options );
13 14 15 16 17

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

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
	var numViews = 2;
	var renderTarget, currentRenderTarget;

	// Auxiliary matrices to be used when updating arrays of uniforms
	var aux = {
		mat4: [],
		mat3: []
	};

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

		aux.mat4[ i ] = new Matrix4();
		aux.mat3[ i ] = new Matrix3();

	}

	//

F
Fernando Serrano 已提交
37
	this.isAvailable = function () {
38

F
Fernando Serrano 已提交
39
		return capabilities.multiview;
40

F
Fernando Serrano 已提交
41
	};
42

43 44 45 46 47 48
	this.getNumViews = function () {

		return numViews;

	};

F
Fernando Serrano 已提交
49
	this.getMaxViews = function () {
50

F
Fernando Serrano 已提交
51
		return capabilities.maxMultiviewViews;
52

F
Fernando Serrano 已提交
53
	};
54

F
Fernando Serrano 已提交
55
	this.isEnabled = function () {
56

F
Fernando Serrano 已提交
57
		return requested && this.isAvailable();
58

F
Fernando Serrano 已提交
59
	};
60

61
	if ( options.debug ) {
62

63
		if ( requested && ! this.isAvailable() ) {
64

65
			console.warn( 'WebGLRenderer: Multiview requested but not supported by the browser' );
66

67
		} else if ( requested !== false && this.isAvailable() ) {
68

69
			console.info( 'WebGLRenderer: Multiview enabled' );
70

71
		}
72

73
	}
74

75
	this.updateCameraProjectionMatrices = function ( camera, p_uniforms ) {
76

77
		if ( camera.isArrayCamera ) {
78

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

81
				aux.mat4[ i ].copy( camera.cameras[ i ].projectionMatrix );
82

83
			}
84

85
		} else {
86

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

89
				aux.mat4[ i ].copy( camera.projectionMatrix );
90 91 92 93 94

			}

		}

95 96
		p_uniforms.setValue( gl, 'projectionMatrices', aux.mat4 );

97 98
	};

99 100 101 102 103
	this.updateCameraViewMatrices = function ( camera, p_uniforms ) {

		if ( camera.isArrayCamera ) {

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

105
				aux.mat4[ i ].copy( camera.cameras[ i ].matrixWorldInverse );
106

107 108 109
			}

		} else {
110 111 112

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

113
				aux.mat4[ i ].copy( camera.matrixWorldInverse );
114 115 116 117 118

			}

		}

119 120 121 122 123 124
		p_uniforms.setValue( gl, 'viewMatrices', aux.mat4 );

	};

	this.updateObjectMatrices = function ( object, camera, p_uniforms ) {

125 126 127 128
		if ( camera.isArrayCamera ) {

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

129 130
				aux.mat4[ i ].multiplyMatrices( camera.cameras[ i ].matrixWorldInverse, object.matrixWorld );
				aux.mat3[ i ].getNormalMatrix( aux.mat4[ i ] );
131 132 133 134 135 136

			}

		} else {

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

140
			for ( var i = 1; i < numViews; i ++ ) {
141

142 143
				aux.mat4[ i ].copy( aux.mat4[ 0 ] );
				aux.mat3[ i ].copy( aux.mat3[ 0 ] );
144 145 146 147 148

			}

		}

149 150 151
		p_uniforms.setValue( gl, 'modelViewMatrices', aux.mat4 );
		p_uniforms.setValue( gl, 'normalMatrices', aux.mat3 );

152
	};
153

154
	this.attachRenderTarget = function ( camera ) {
155

156
		currentRenderTarget = renderer.getRenderTarget();
157

158
		// Resize if needed
F
Fernando Serrano 已提交
159 160 161 162
		var width = canvas.width;
		var height = canvas.height;

		if ( camera.isArrayCamera ) {
163

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

F
Fernando Serrano 已提交
167 168 169 170 171
			width *= bounds.z;
			height *= bounds.w;

		}

172
		renderTarget.setSize( width, height );
173

174
		renderer.setRenderTarget( renderTarget );
175 176 177

	};

178
	this.detachRenderTarget = function ( camera ) {
179

180 181 182 183
		var viewFramebuffers = properties.get( renderTarget ).__webglViewFramebuffers;

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

F
Fernando Serrano 已提交
185
		if ( camera.isArrayCamera ) {
186

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

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

F
Fernando Serrano 已提交
191 192 193 194
				var x = bounds.x * canvas.width;
				var y = bounds.y * canvas.height;
				var width = bounds.z * canvas.width;
				var height = bounds.w * canvas.height;
195

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

F
Fernando Serrano 已提交
199
			}
200

F
Fernando Serrano 已提交
201
		} else {
202

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

F
Fernando Serrano 已提交
207
		}
208

209 210
		renderer.setRenderTarget( currentRenderTarget );

211 212
	};

213

F
Fernando Serrano 已提交
214
	if ( this.isEnabled() ) {
215

216
		renderTarget = new WebGLMultiviewRenderTarget( canvas.width, canvas.height, numViews );
217

F
Fernando Serrano 已提交
218
	}
219 220 221 222

}

export { WebGLMultiview };