WebGLMultiview.js 4.9 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
function WebGLMultiview( renderer, gl, contextAttributes ) {
12

13
	var DEFAULT_NUMVIEWS = 2;
14

15 16
	var capabilities = renderer.capabilities;
	var properties = renderer.properties;
17

18 19
	var maxNumViews = capabilities.maxMultiviewViews;

20
	var renderTarget, currentRenderTarget;
21
	var mat3, mat4, cameraArray, renderSize;
22

23
	function getMaxViews() {
24

25
		return capabilities.maxMultiviewViews;
26

27
	}
28

29
	function getNumViews() {
30

31 32 33 34 35 36 37
		if ( renderTarget && renderer.getRenderTarget() === renderTarget ) {

			return renderTarget.numViews;

		}

		return 0;
38

39
	}
40

41
	function getCameraArray( camera ) {
42

43 44 45 46 47
		if ( camera.isArrayCamera ) return camera.cameras;

		cameraArray[ 0 ] = camera;

		return cameraArray;
48

49
	}
50

51
	//
52

53
	function isAvailable() {
54

55
		return capabilities.multiview && ! contextAttributes.antialias;
56

57
	}
58

59
	function updateCameraProjectionMatricesUniform( camera, uniforms ) {
60

61
		var cameras = getCameraArray( camera );
62

63
		for ( var i = 0; i < cameras.length; i ++ ) {
64

65
			mat4[ i ].copy( cameras[ i ].projectionMatrix );
66 67 68

		}

69
		uniforms.setValue( gl, 'projectionMatrices', mat4 );
70

71
	}
72

73
	function updateCameraViewMatricesUniform( camera, uniforms ) {
74

75
		var cameras = getCameraArray( camera );
76

77
		for ( var i = 0; i < cameras.length; i ++ ) {
78

79
			mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
80 81 82

		}

83
		uniforms.setValue( gl, 'viewMatrices', mat4 );
84

85
	}
86

87
	function updateObjectMatricesUniforms( object, camera, uniforms ) {
88

89
		var cameras = getCameraArray( camera );
90

91
		for ( var i = 0; i < cameras.length; i ++ ) {
92

93 94
			mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );
			mat3[ i ].getNormalMatrix( mat4[ i ] );
95 96 97

		}

98 99
		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
		uniforms.setValue( gl, 'normalMatrices', mat3 );
100

101 102
	}

103 104 105 106 107 108 109 110 111 112
	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 ++ ) {

113 114
			if ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||
				cameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) return false;
115 116 117 118 119 120

		}

		return true;

	}
121

122
	function resizeRenderTarget( camera ) {
123

124 125 126 127 128 129 130
		if ( currentRenderTarget ) {

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

		} else {

			renderer.getDrawingBufferSize( renderSize );
131

132
		}
F
Fernando Serrano 已提交
133 134

		if ( camera.isArrayCamera ) {
135

136 137 138
			var viewport = camera.cameras[ 0 ].viewport;

			renderTarget.setSize( viewport.z, viewport.w );
139

140 141 142 143
			renderTarget.setNumViews( camera.cameras.length );

		} else {

144
			renderTarget.setSize( renderSize.x, renderSize.y );
145 146
			renderTarget.setNumViews( DEFAULT_NUMVIEWS );

F
Fernando Serrano 已提交
147 148
		}

149 150 151
	}

	function attachRenderTarget( camera ) {
152

153 154
		if ( ! isMultiviewCompatible( camera ) ) return;

155 156
		currentRenderTarget = renderer.getRenderTarget();
		resizeRenderTarget( camera );
157
		renderer.setRenderTarget( renderTarget );
158

159 160 161 162
	}

	function detachRenderTarget( camera ) {

F
Fernando Serrano 已提交
163
		if ( renderTarget !== renderer.getRenderTarget() ) return;
164

165 166
		renderer.setRenderTarget( currentRenderTarget );
		flush( camera );
167

168
	}
169

170
	function flush( camera ) {
171

172 173 174 175 176 177 178
		var srcRenderTarget = renderTarget;
		var numViews = srcRenderTarget.numViews;

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

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

F
Fernando Serrano 已提交
180
		if ( camera.isArrayCamera ) {
181

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

184
				var viewport = camera.cameras[ i ].viewport;
185

186 187 188 189
				var x1 = viewport.x;
				var y1 = viewport.y;
				var x2 = x1 + viewport.z;
				var y2 = y1 + viewport.w;
190

191 192
				gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
				gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
193

F
Fernando Serrano 已提交
194
			}
195

F
Fernando Serrano 已提交
196
		} else {
197

198 199
			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 );
200

F
Fernando Serrano 已提交
201
		}
202

203
	}
204

205

206 207
	if ( isAvailable() ) {

208
		renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
209

210
		renderSize = new Vector2();
211 212 213 214
		mat4 = [];
		mat3 = [];
		cameraArray = [];

215
		for ( var i = 0; i < getMaxViews(); i ++ ) {
216 217 218 219 220 221

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

		}

F
Fernando Serrano 已提交
222
	}
223

224 225 226 227 228 229 230 231 232

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

233 234 235
}

export { WebGLMultiview };