WebGLMultiview.js 4.2 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
	var capabilities = renderer.capabilities;
16
	var extensions = renderer.extensions;
17
	var properties = renderer.properties;
18

19
	var renderTarget, currentRenderTarget;
20
	var mat3, mat4, renderSize;
21

22 23
	var available;
	var maxNumViews = 0;
24

25
	//
26

27
	function isAvailable() {
28

29
		if ( available === undefined ) {
30

31
			var extension = extensions.get( 'OVR_multiview2' );
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
			available = extension !== null && gl.getContextAttributes().antialias === false;

			if ( available ) {

				maxNumViews = gl.getParameter( extension.MAX_VIEWS_OVR );
				renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );

				renderSize = new Vector2();
				mat4 = [];
				mat3 = [];

				var maxViews = capabilities.maxMultiviewViews;

				for ( var i = 0; i < maxViews; i ++ ) {

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

				}

			}

		}

		return available;

	}
60

61
	function updateCameraProjectionMatricesUniform( camera, uniforms ) {
62

63
		var cameras = camera.cameras;
64

65
		for ( var i = 0; i < cameras.length; i ++ ) {
66

67
			mat4[ i ].copy( cameras[ i ].projectionMatrix );
68 69 70

		}

71
		uniforms.setValue( gl, 'projectionMatrices', mat4 );
72

73
	}
74

75
	function updateCameraViewMatricesUniform( camera, uniforms ) {
76

77
		var cameras = camera.cameras;
78

79
		for ( var i = 0; i < cameras.length; i ++ ) {
80

81
			mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
82 83 84

		}

85
		uniforms.setValue( gl, 'viewMatrices', mat4 );
86

87
	}
88

89
	function updateObjectMatricesUniforms( object, camera, uniforms ) {
90

91
		var cameras = camera.cameras;
92

93
		for ( var i = 0; i < cameras.length; i ++ ) {
94

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

		}

100 101
		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
		uniforms.setValue( gl, 'normalMatrices', mat3 );
102

103 104
	}

105 106 107 108 109 110 111 112
	function isMultiviewCompatible( camera ) {

		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
		var viewport = camera.cameras[ 0 ].viewport;
135

136 137
		renderTarget.setSize( viewport.z, viewport.w );
		renderTarget.setNumViews( camera.cameras.length );
F
Fernando Serrano 已提交
138

139 140
	}

141
	function attachCamera( camera ) {
142

143 144
		if ( ! isMultiviewCompatible( camera ) ) return;

145 146
		currentRenderTarget = renderer.getRenderTarget();
		resizeRenderTarget( camera );
147
		renderer.setRenderTarget( renderTarget );
148

149 150
	}

F
Fernando Serrano 已提交
151
	function detachCamera( camera ) {
152

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

155
		renderer.setRenderTarget( currentRenderTarget );
156

157
		flush( camera );
158

159
	}
160

161
	function flush( camera ) {
162

163 164 165 166 167 168 169
		var srcRenderTarget = renderTarget;
		var numViews = srcRenderTarget.numViews;

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

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

171
		for ( var i = 0; i < numViews; i ++ ) {
172

173
			var viewport = camera.cameras[ i ].viewport;
174

175 176 177 178
			var x1 = viewport.x;
			var y1 = viewport.y;
			var x2 = x1 + viewport.z;
			var y2 = y1 + viewport.w;
179

180 181
			gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
			gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
182 183 184

		}

F
Fernando Serrano 已提交
185
	}
186

187
	this.isAvailable = isAvailable;
188
	this.attachCamera = attachCamera;
F
Fernando Serrano 已提交
189
	this.detachCamera = detachCamera;
190 191 192 193
	this.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;
	this.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;
	this.updateObjectMatricesUniforms = updateObjectMatricesUniforms;

194 195 196
}

export { WebGLMultiview };