WebGLMultiview.js 4.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

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
	var renderTarget, currentRenderTarget;
21
	var mat3, mat4, cameraArray;
22

23
	this.getMaxViews = function () {
24

25
		return capabilities.maxMultiviewViews;
26

27
	};
28

29
	this.getNumViews = function () {
30

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

			return renderTarget.numViews;

		}

		return 0;
38

39
	};
40 41


42
	function getCameraArray( camera ) {
43

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

		cameraArray[ 0 ] = camera;

		return cameraArray;
49

50
	}
51

52
	//
53

54
	this.isAvailable = function () {
55

56
		return capabilities.multiview;
57

F
Fernando Serrano 已提交
58
	};
59

F
Fernando Serrano 已提交
60
	this.isEnabled = function () {
61

F
Fernando Serrano 已提交
62
		return requested && this.isAvailable();
63

F
Fernando Serrano 已提交
64
	};
65

66
	if ( options.debug ) {
67

68
		if ( requested && ! this.isAvailable() ) {
69

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

72
		} else if ( requested !== false && this.isAvailable() ) {
73

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

76
		}
77

78
	}
79 80


81
	this.updateCameraProjectionMatrices = function ( camera, uniforms ) {
82

83
		var cameras = getCameraArray( camera );
84

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

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

		}

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

93 94
	};

95 96
	this.updateCameraViewMatrices = function ( camera, uniforms ) {

97
		var cameras = getCameraArray( camera );
98

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

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

		}

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

	};

109 110
	this.updateObjectMatrices = function ( object, camera, uniforms ) {

111
		var cameras = getCameraArray( camera );
112

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

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

		}

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

123
	};
124

125
	this.attachRenderTarget = function ( camera ) {
126

127
		currentRenderTarget = renderer.getRenderTarget();
128

129
		// Resize if needed
F
Fernando Serrano 已提交
130 131 132 133
		var width = canvas.width;
		var height = canvas.height;

		if ( camera.isArrayCamera ) {
134

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

F
Fernando Serrano 已提交
138 139 140
			width *= bounds.z;
			height *= bounds.w;

141 142 143 144 145 146
			renderTarget.setNumViews( camera.cameras.length );

		} else {

			renderTarget.setNumViews( DEFAULT_NUMVIEWS );

F
Fernando Serrano 已提交
147 148
		}

149
		renderTarget.setSize( width, height );
150

151
		renderer.setRenderTarget( renderTarget );
152 153 154

	};

155
	this.detachRenderTarget = function ( camera ) {
156

157 158 159 160
		var viewFramebuffers = properties.get( renderTarget ).__webglViewFramebuffers;

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

F
Fernando Serrano 已提交
162
		if ( camera.isArrayCamera ) {
163

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

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

F
Fernando Serrano 已提交
168 169 170 171
				var x = bounds.x * canvas.width;
				var y = bounds.y * canvas.height;
				var width = bounds.z * canvas.width;
				var height = bounds.w * canvas.height;
172

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

F
Fernando Serrano 已提交
176
			}
177

F
Fernando Serrano 已提交
178
		} else {
179

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

F
Fernando Serrano 已提交
184
		}
185

186 187
		renderer.setRenderTarget( currentRenderTarget );

188 189
	};

190

F
Fernando Serrano 已提交
191
	if ( this.isEnabled() ) {
192

193
		renderTarget = new WebGLMultiviewRenderTarget( canvas.width, canvas.height, this.numViews );
194

195 196 197 198 199 200 201 202 203 204 205 206
		// Auxiliary matrices to be used when updating arrays of uniforms
		mat4 = [];
		mat3 = [];
		cameraArray = [];

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

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

		}

F
Fernando Serrano 已提交
207
	}
208 209 210 211

}

export { WebGLMultiview };