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

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

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

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;
56

57
	}
58

59
	function isEnabled() {
60

61
		return requested && isAvailable();
62

63
	}
64

65
	if ( options.debug ) {
66

67
		if ( requested && ! isAvailable() ) {
68

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

71
		} else if ( requested !== false && isAvailable() ) {
72

73
			console.info( 'WebGLRenderer: Multiview enabled' );
74

75
		}
76

77
	}
78 79


80
	function updateCameraProjectionMatricesUniform( camera, uniforms ) {
81

82
		var cameras = getCameraArray( camera );
83

84
		for ( var i = 0; i < cameras.length; i ++ ) {
85

86
			mat4[ i ].copy( cameras[ i ].projectionMatrix );
87 88 89

		}

90
		uniforms.setValue( gl, 'projectionMatrices', mat4 );
91

92
	}
93

94
	function updateCameraViewMatricesUniform( camera, uniforms ) {
95

96
		var cameras = getCameraArray( camera );
97

98
		for ( var i = 0; i < cameras.length; i ++ ) {
99

100
			mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
101 102 103

		}

104
		uniforms.setValue( gl, 'viewMatrices', mat4 );
105

106
	}
107

108
	function updateObjectMatricesUniforms( object, camera, uniforms ) {
109

110
		var cameras = getCameraArray( camera );
111

112
		for ( var i = 0; i < cameras.length; i ++ ) {
113

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

		}

119 120
		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
		uniforms.setValue( gl, 'normalMatrices', mat3 );
121

122 123
	}

124

125
	function resizeRenderTarget( camera ) {
126

127 128 129 130 131 132 133
		if ( currentRenderTarget ) {

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

		} else {

			renderer.getDrawingBufferSize( renderSize );
134

135
		}
F
Fernando Serrano 已提交
136 137

		if ( camera.isArrayCamera ) {
138

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

141
			renderTarget.setSize( bounds.z * renderSize.x, bounds.w * renderSize.y );
142 143 144 145
			renderTarget.setNumViews( camera.cameras.length );

		} else {

146
			renderTarget.setSize( renderSize.x, renderSize.y );
147 148
			renderTarget.setNumViews( DEFAULT_NUMVIEWS );

F
Fernando Serrano 已提交
149 150
		}

151 152 153
	}

	function attachRenderTarget( camera ) {
154

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

159 160 161 162 163 164
	}

	function detachRenderTarget( camera ) {

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

166
	}
167

168
	function flush( camera ) {
169

170 171 172 173 174 175 176
		var srcRenderTarget = renderTarget;
		var numViews = srcRenderTarget.numViews;

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

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

F
Fernando Serrano 已提交
178
		if ( camera.isArrayCamera ) {
179

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

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

184 185 186 187
				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;
188

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

F
Fernando Serrano 已提交
192
			}
193

F
Fernando Serrano 已提交
194
		} else {
195

196 197
			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 );
198

F
Fernando Serrano 已提交
199
		}
200

201
	}
202

203

204
	if ( isEnabled() ) {
205

206
		renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
207

208
		renderSize = new Vector2();
209 210 211 212
		mat4 = [];
		mat3 = [];
		cameraArray = [];

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

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

		}

F
Fernando Serrano 已提交
220
	}
221

222 223 224 225 226 227 228 229 230 231

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

232 233 234
}

export { WebGLMultiview };