WebGLMultiview.js 5.4 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
import { Vector2 } from '../../math/Vector2.js';
10

11 12 13
function WebGLMultiview( renderer, requested, options ) {

	options = Object.assign( {}, { debug: false }, options );
14

15
	var DEFAULT_NUMVIEWS = 2;
16
	var gl = renderer.context;
17 18 19

	var maxNumViews = capabilities.maxMultiviewViews;

20 21
	var capabilities = renderer.capabilities;
	var properties = renderer.properties;
22

23
	var renderTarget, currentRenderTarget;
24
	var mat3, mat4, cameraArray, renderSize;
25

26
	function getMaxViews() {
27

28
		return capabilities.maxMultiviewViews;
29

30
	}
31

32
	function getNumViews() {
33

34 35 36 37 38 39 40
		if ( renderTarget && renderer.getRenderTarget() === renderTarget ) {

			return renderTarget.numViews;

		}

		return 0;
41

42
	}
43

44
	function getCameraArray( camera ) {
45

46 47 48 49 50
		if ( camera.isArrayCamera ) return camera.cameras;

		cameraArray[ 0 ] = camera;

		return cameraArray;
51

52
	}
53

54
	//
55

56
	function isAvailable() {
57

58
		return capabilities.multiview;
59

60
	}
61

62
	function isEnabled() {
63

64
		return requested && isAvailable();
65

66
	}
67

68
	if ( options.debug ) {
69

70
		if ( requested && ! isAvailable() ) {
71

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

74
		} else if ( requested !== false && isAvailable() ) {
75

76
			console.info( 'WebGLRenderer: Multiview enabled' );
77

78
		}
79

80
	}
81

82
	function updateCameraProjectionMatricesUniform( camera, uniforms ) {
83

84
		var cameras = getCameraArray( camera );
85

86
		for ( var i = 0; i < cameras.length; i ++ ) {
87

88
			mat4[ i ].copy( cameras[ i ].projectionMatrix );
89 90 91

		}

92
		uniforms.setValue( gl, 'projectionMatrices', mat4 );
93

94
	}
95

96
	function updateCameraViewMatricesUniform( camera, uniforms ) {
97

98
		var cameras = getCameraArray( camera );
99

100
		for ( var i = 0; i < cameras.length; i ++ ) {
101

102
			mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
103 104 105

		}

106
		uniforms.setValue( gl, 'viewMatrices', mat4 );
107

108
	}
109

110
	function updateObjectMatricesUniforms( object, camera, uniforms ) {
111

112
		var cameras = getCameraArray( camera );
113

114
		for ( var i = 0; i < cameras.length; i ++ ) {
115

116 117
			mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );
			mat3[ i ].getNormalMatrix( mat4[ i ] );
118 119 120

		}

121 122
		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
		uniforms.setValue( gl, 'normalMatrices', mat3 );
123

124 125
	}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	function isMultiviewCompatible( camera ) {

		if ( ! camera.isArrayCamera ) return true;

		var cameras = camera.cameras;

		if ( cameras.length > maxNumViews ) return false;

		for ( var i = 1, il = cameras.length; i < il; i ++ ) {

			if ( cameras[ 0 ].bounds.z !== cameras[ i ].bounds.z ||
				cameras[ 0 ].bounds.w !== cameras[ i ].bounds.w ) return false;

		}

		return true;

	}
144

145
	function resizeRenderTarget( camera ) {
146

147 148 149 150 151 152 153
		if ( currentRenderTarget ) {

			renderSize.set( currentRenderTarget.width, currentRenderTarget.height );

		} else {

			renderer.getDrawingBufferSize( renderSize );
154

155
		}
F
Fernando Serrano 已提交
156 157

		if ( camera.isArrayCamera ) {
158

F
Fernando Serrano 已提交
159
			var bounds = camera.cameras[ 0 ].bounds;
160

161
			renderTarget.setSize( bounds.z * renderSize.x, bounds.w * renderSize.y );
162 163 164 165
			renderTarget.setNumViews( camera.cameras.length );

		} else {

166
			renderTarget.setSize( renderSize.x, renderSize.y );
167 168
			renderTarget.setNumViews( DEFAULT_NUMVIEWS );

F
Fernando Serrano 已提交
169 170
		}

171 172 173
	}

	function attachRenderTarget( camera ) {
174

175 176
		if ( ! isMultiviewCompatible( camera ) ) return;

177 178
		currentRenderTarget = renderer.getRenderTarget();
		resizeRenderTarget( camera );
179
		renderer.setRenderTarget( renderTarget );
180

181 182 183 184
	}

	function detachRenderTarget( camera ) {

185 186
		if ( renderTarget !== renderer.getRenderTarget() ) return false;

187 188
		renderer.setRenderTarget( currentRenderTarget );
		flush( camera );
189

190
	}
191

192
	function flush( camera ) {
193

194 195 196 197 198 199 200
		var srcRenderTarget = renderTarget;
		var numViews = srcRenderTarget.numViews;

		var srcFramebuffers = properties.get( srcRenderTarget ).__webglViewFramebuffers;

		var viewWidth = srcRenderTarget.width;
		var viewHeight = srcRenderTarget.height;
201

F
Fernando Serrano 已提交
202
		if ( camera.isArrayCamera ) {
203

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

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

208 209 210 211
				var x1 = bounds.x * renderSize.x;
				var y1 = bounds.y * renderSize.y;
				var x2 = x1 + bounds.z * renderSize.x;
				var y2 = y1 + bounds.w * renderSize.y;
212

213 214
				gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
				gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
215

F
Fernando Serrano 已提交
216
			}
217

F
Fernando Serrano 已提交
218
		} else {
219

220 221
			gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ 0 ] );
			gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, 0, 0, renderSize.x, renderSize.y, gl.COLOR_BUFFER_BIT, gl.NEAREST );
222

F
Fernando Serrano 已提交
223
		}
224

225
	}
226

227

228
	if ( isEnabled() ) {
229

230
		renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
231

232
		renderSize = new Vector2();
233 234 235 236
		mat4 = [];
		mat3 = [];
		cameraArray = [];

237
		for ( var i = 0; i < getMaxViews(); i ++ ) {
238 239 240 241 242 243

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

		}

F
Fernando Serrano 已提交
244
	}
245

246 247 248 249 250 251 252 253 254 255

	this.attachRenderTarget = attachRenderTarget;
	this.detachRenderTarget = detachRenderTarget;
	this.isAvailable = isAvailable;
	this.isEnabled = isEnabled;
	this.getNumViews = getNumViews;
	this.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;
	this.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;
	this.updateObjectMatricesUniforms = updateObjectMatricesUniforms;

256 257 258
}

export { WebGLMultiview };