WebGLMultiview.js 4.8 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
	var DEFAULT_NUMVIEWS = 2;
15 16 17 18
	var gl = renderer.context;
	var canvas = renderer.domElement;
	var capabilities = renderer.capabilities;
	var properties = renderer.properties;
19

20 21
	var renderTarget, currentRenderTarget;

22
	this.getMaxViews = function () {
23

24
		return capabilities.maxMultiviewViews;
25

26
	};
27

28
	this.getNumViews = function () {
29

30
		return renderTarget ? renderTarget.numViews : 0;
31

32
	};
33

34 35 36
	// Auxiliary matrices to be used when updating arrays of uniforms
	var mat4 = [];
	var mat3 = [];
37

38
	for ( var i = 0; i < this.getMaxViews(); i ++ ) {
39

40 41
		mat4[ i ] = new Matrix4();
		mat3[ i ] = new Matrix3();
42

43
	}
44

45
	//
46

47
	this.isAvailable = function () {
48

49
		return capabilities.multiview;
50

F
Fernando Serrano 已提交
51
	};
52

F
Fernando Serrano 已提交
53
	this.isEnabled = function () {
54

F
Fernando Serrano 已提交
55
		return requested && this.isAvailable();
56

F
Fernando Serrano 已提交
57
	};
58

59
	if ( options.debug ) {
60

61
		if ( requested && ! this.isAvailable() ) {
62

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

65
		} else if ( requested !== false && this.isAvailable() ) {
66

67
			console.info( 'WebGLRenderer: Multiview enabled' );
68

69
		}
70

71
	}
72

73 74 75
	this.updateCameraProjectionMatrices = function ( camera, uniforms ) {

		var numViews = this.getNumViews();
76

77
		if ( camera.isArrayCamera ) {
78

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

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

83
			}
84

85
		} else {
86

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

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

			}

		}

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

97 98
	};

99 100 101
	this.updateCameraViewMatrices = function ( camera, uniforms ) {

		var numViews = this.getNumViews();
102 103 104 105

		if ( camera.isArrayCamera ) {

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

107
				mat4[ i ].copy( camera.cameras[ i ].matrixWorldInverse );
108

109 110 111
			}

		} else {
112 113 114

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

115
				mat4[ i ].copy( camera.matrixWorldInverse );
116 117 118 119 120

			}

		}

121
		uniforms.setValue( gl, 'viewMatrices', mat4 );
122 123 124

	};

125 126 127
	this.updateObjectMatrices = function ( object, camera, uniforms ) {

		var numViews = this.getNumViews();
128

129 130 131 132
		if ( camera.isArrayCamera ) {

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

133 134
				mat4[ i ].multiplyMatrices( camera.cameras[ i ].matrixWorldInverse, object.matrixWorld );
				mat3[ i ].getNormalMatrix( mat4[ i ] );
135 136 137 138 139 140

			}

		} else {

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

144
			for ( var i = 1; i < numViews; i ++ ) {
145

146 147
				mat4[ i ].copy( mat4[ 0 ] );
				mat3[ i ].copy( mat3[ 0 ] );
148 149 150 151 152

			}

		}

153 154
		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
		uniforms.setValue( gl, 'normalMatrices', mat3 );
155

156
	};
157

158
	this.attachRenderTarget = function ( camera ) {
159

160
		currentRenderTarget = renderer.getRenderTarget();
161

162
		// Resize if needed
F
Fernando Serrano 已提交
163 164 165 166
		var width = canvas.width;
		var height = canvas.height;

		if ( camera.isArrayCamera ) {
167

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

F
Fernando Serrano 已提交
171 172 173
			width *= bounds.z;
			height *= bounds.w;

174 175 176 177 178 179
			renderTarget.setNumViews( camera.cameras.length );

		} else {

			renderTarget.setNumViews( DEFAULT_NUMVIEWS );

F
Fernando Serrano 已提交
180 181
		}

182
		renderTarget.setSize( width, height );
183

184
		renderer.setRenderTarget( renderTarget );
185 186 187

	};

188
	this.detachRenderTarget = function ( camera ) {
189

190 191 192 193
		var viewFramebuffers = properties.get( renderTarget ).__webglViewFramebuffers;

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

F
Fernando Serrano 已提交
195
		if ( camera.isArrayCamera ) {
196

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

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

F
Fernando Serrano 已提交
201 202 203 204
				var x = bounds.x * canvas.width;
				var y = bounds.y * canvas.height;
				var width = bounds.z * canvas.width;
				var height = bounds.w * canvas.height;
205

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

F
Fernando Serrano 已提交
209
			}
210

F
Fernando Serrano 已提交
211
		} else {
212

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

F
Fernando Serrano 已提交
217
		}
218

219 220
		renderer.setRenderTarget( currentRenderTarget );

221 222
	};

223

F
Fernando Serrano 已提交
224
	if ( this.isEnabled() ) {
225

226
		renderTarget = new WebGLMultiviewRenderTarget( canvas.width, canvas.height, this.numViews );
227

F
Fernando Serrano 已提交
228
	}
229 230 231 232

}

export { WebGLMultiview };