WebGLMultiview.js 4.5 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 ) {
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 getCameraArray( camera ) {
24

25 26 27 28 29
		if ( camera.isArrayCamera ) return camera.cameras;

		cameraArray[ 0 ] = camera;

		return cameraArray;
30

31
	}
32

33
	//
34

35
	function updateCameraProjectionMatricesUniform( camera, uniforms ) {
36

37
		var cameras = getCameraArray( camera );
38

39
		for ( var i = 0; i < cameras.length; i ++ ) {
40

41
			mat4[ i ].copy( cameras[ i ].projectionMatrix );
42 43 44

		}

45
		uniforms.setValue( gl, 'projectionMatrices', mat4 );
46

47
	}
48

49
	function updateCameraViewMatricesUniform( camera, uniforms ) {
50

51
		var cameras = getCameraArray( camera );
52

53
		for ( var i = 0; i < cameras.length; i ++ ) {
54

55
			mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
56 57 58

		}

59
		uniforms.setValue( gl, 'viewMatrices', mat4 );
60

61
	}
62

63
	function updateObjectMatricesUniforms( object, camera, uniforms ) {
64

65
		var cameras = getCameraArray( camera );
66

67
		for ( var i = 0; i < cameras.length; i ++ ) {
68

69 70
			mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );
			mat3[ i ].getNormalMatrix( mat4[ i ] );
71 72 73

		}

74 75
		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
		uniforms.setValue( gl, 'normalMatrices', mat3 );
76

77 78
	}

79 80 81 82 83 84 85 86 87 88
	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 ++ ) {

89 90
			if ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||
				cameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) return false;
91 92 93 94 95 96

		}

		return true;

	}
97

98
	function resizeRenderTarget( camera ) {
99

100 101 102 103 104 105 106
		if ( currentRenderTarget ) {

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

		} else {

			renderer.getDrawingBufferSize( renderSize );
107

108
		}
F
Fernando Serrano 已提交
109 110

		if ( camera.isArrayCamera ) {
111

112 113 114
			var viewport = camera.cameras[ 0 ].viewport;

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

116 117 118 119
			renderTarget.setNumViews( camera.cameras.length );

		} else {

120
			renderTarget.setSize( renderSize.x, renderSize.y );
121 122
			renderTarget.setNumViews( DEFAULT_NUMVIEWS );

F
Fernando Serrano 已提交
123 124
		}

125 126
	}

127
	function attachCamera( camera ) {
128

129 130
		if ( ! isMultiviewCompatible( camera ) ) return;

131 132
		currentRenderTarget = renderer.getRenderTarget();
		resizeRenderTarget( camera );
133
		renderer.setRenderTarget( renderTarget );
134

135 136
	}

F
Fernando Serrano 已提交
137
	function detachCamera( camera ) {
138

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

141 142
		renderer.setRenderTarget( currentRenderTarget );
		flush( camera );
143

144
	}
145

146
	function flush( camera ) {
147

148 149 150 151 152 153 154
		var srcRenderTarget = renderTarget;
		var numViews = srcRenderTarget.numViews;

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

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

F
Fernando Serrano 已提交
156
		if ( camera.isArrayCamera ) {
157

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

160
				var viewport = camera.cameras[ i ].viewport;
161

162 163 164 165
				var x1 = viewport.x;
				var y1 = viewport.y;
				var x2 = x1 + viewport.z;
				var y2 = y1 + viewport.w;
166

167 168
				gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
				gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
169

F
Fernando Serrano 已提交
170
			}
171

F
Fernando Serrano 已提交
172
		} else {
173

174 175
			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 );
176

F
Fernando Serrano 已提交
177
		}
178

179
	}
180

181

182
	if ( renderer.capabilities.multiview ) {
183

184
		renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
185

186
		renderSize = new Vector2();
187 188 189 190
		mat4 = [];
		mat3 = [];
		cameraArray = [];

191 192 193
		var maxViews = capabilities.maxMultiviewViews;

		for ( var i = 0; i < maxViews; i ++ ) {
194 195 196 197 198 199

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

		}

F
Fernando Serrano 已提交
200
	}
201

202

203
	this.attachCamera = attachCamera;
F
Fernando Serrano 已提交
204
	this.detachCamera = detachCamera;
205 206 207 208
	this.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;
	this.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;
	this.updateObjectMatricesUniforms = updateObjectMatricesUniforms;

209 210 211
}

export { WebGLMultiview };