Browse Source

.setViewOffset method for OrthographicCamera (#8872)

* added .setViewOffset method to OrthographicCamera

* fixed .setViewOffset method

* added .clearViewOffset method

* added camera switcher to msaa_unbiased example

* renamed variables

* typo in docs

* added doc for perspective camera .clearViewOffset

* added doc for orthographic camera .set/.clearViewOffset
Alexander Rose 9 years ago
parent
commit
7e0a836ef1

+ 19 - 0
docs/api/cameras/OrthographicCamera.html

@@ -74,6 +74,25 @@ scene.add( camera );</code>
 
 		<h2>Methods</h2>
 
+		<h3>[method:null setViewOffset]( [page:Float fullWidth], [page:Float fullHeight], [page:Float x], [page:Float y], [page:Float width], [page:Float height] )</h3>
+		<div>
+		fullWidth — full width of multiview setup<br />
+		fullHeight — full height of multiview setup<br />
+		x — horizontal offset of subcamera<br />
+		y — vertical offset of subcamera<br />
+		width — width of subcamera<br />
+		height — height of subcamera
+		</div>
+
+		<div>
+		Sets an offset in a larger frustum. This is useful for multi-window or multi-monitor/multi-machine setups. For an example on how to use it see [page:PerspectiveCamera].
+		</div>
+
+		<h3>[method:null clearViewOffset]()</h3>
+		<div>
+		Removes any offset set by the .setViewOffset method.
+		</div>
+
 		<h3>[method:null updateProjectionMatrix]()</h3>
 		<div>
 		Updates the camera projection matrix. Must be called after change of parameters.

+ 6 - 1
docs/api/cameras/PerspectiveCamera.html

@@ -88,7 +88,7 @@ scene.add( camera );</code>
 
 		<h3>[method:Float getFilmHeight]()</h3>
 		<div>
-		Returns the height of the image on the film. If .aspect is less than or equal to one (portrait format), the result equals .fimlGauge.
+		Returns the height of the image on the film. If .aspect is less than or equal to one (portrait format), the result equals .filmGauge.
 		</div>
 
 		<h3>[method:null setFocalLength]( [page:Float focalLength] )</h3>
@@ -157,6 +157,11 @@ camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
 		Note there is no reason monitors have to be the same size or in a grid.
 		</div>
 
+		<h3>[method:null clearViewOffset]()</h3>
+		<div>
+		Removes any offset set by the .setViewOffset method.
+		</div>
+
 		<h3>[method:null updateProjectionMatrix]()</h3>
 		<div>
 		Updates the camera projection matrix. Must be called after change of parameters.

+ 50 - 16
examples/webgl_postprocessing_msaa_unbiased.html

@@ -50,12 +50,15 @@
 
 		<script>
 
-			var camera, scene, renderer, composer, copyPass, msaaRenderPass;
+			var scene, renderer;
+			var cameraP, composerP, copyPassP, msaaRenderPassP;
+			var cameraO, composerO, copyPassO, msaaRenderPassO;
 			var gui, stats, texture;
 
 			var param = {
 				sampleLevel: 4,
-				unbiased: true
+				unbiased: true,
+				camera: 'perspective'
 			};
 
 			init();
@@ -78,6 +81,7 @@
 					'Level 4: 16 Samples': 4,
 					'Level 5: 32 Samples': 5
 				} );
+				gui.add( param, 'camera', [ 'perspective', 'ortho' ] );
 
 				gui.open();
 
@@ -89,6 +93,7 @@
 
 				var width = window.innerWidth || 1;
 				var height = window.innerHeight || 1;
+				var aspect = width / height;
 				var devicePixelRatio = window.devicePixelRatio || 1;
 
 				renderer = new THREE.WebGLRenderer( { antialias: false } );
@@ -101,8 +106,17 @@
 
 				//
 
-				camera = new THREE.PerspectiveCamera( 65, width / height, 3, 10 );
-				camera.position.z = 7;
+				cameraP = new THREE.PerspectiveCamera( 65, aspect, 3, 10 );
+				cameraP.position.z = 7;
+
+				cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 3, 10 );
+				cameraO.position.z = 7;
+
+				var fov = THREE.Math.degToRad( cameraP.fov );
+				var hyperfocus = ( cameraP.near + cameraP.far ) / 2;
+				var _height = 2 * Math.tan( fov / 2 ) * hyperfocus;
+				cameraO.zoom = height / _height;
+
 
 				scene = new THREE.Scene();
 
@@ -152,14 +166,19 @@
 
 				// postprocessing
 
-				composer = new THREE.EffectComposer( renderer );
-
-				msaaRenderPass = new THREE.ManualMSAARenderPass( scene, camera );
-				composer.addPass( msaaRenderPass );
+				composerP = new THREE.EffectComposer( renderer );
+				msaaRenderPassP = new THREE.ManualMSAARenderPass( scene, cameraP );
+				composerP.addPass( msaaRenderPassP );
+				copyPassP = new THREE.ShaderPass( THREE.CopyShader );
+				copyPassP.renderToScreen = true;
+				composerP.addPass( copyPassP );
 
-				copyPass = new THREE.ShaderPass( THREE.CopyShader );
-		    copyPass.renderToScreen = true;
-				composer.addPass( copyPass );
+				composerO = new THREE.EffectComposer( renderer );
+				msaaRenderPassO = new THREE.ManualMSAARenderPass( scene, cameraO );
+				composerO.addPass( msaaRenderPassO );
+				copyPassO = new THREE.ShaderPass( THREE.CopyShader );
+				copyPassO.renderToScreen = true;
+				composerO.addPass( copyPassO );
 
 				window.addEventListener( 'resize', onWindowResize, false );
 
@@ -169,9 +188,16 @@
 
 				var width = window.innerWidth;
 				var height = window.innerHeight;
+				var aspect = width / height;
 
-				camera.aspect = width / height;
-				camera.updateProjectionMatrix();
+				cameraP.aspect = aspect;
+				cameraO.updateProjectionMatrix();
+
+				cameraO.left = - height * aspect;
+				cameraO.right = height * aspect;
+				cameraO.top = height;
+				cameraO.bottom = - height;
+				cameraO.updateProjectionMatrix();
 
 				renderer.setSize( width, height );
 
@@ -197,10 +223,18 @@
 
 				}
 
-				msaaRenderPass.sampleLevel = param.sampleLevel;
-				msaaRenderPass.unbiased = param.unbiased;
+				msaaRenderPassP.sampleLevel = param.sampleLevel;
+				msaaRenderPassP.unbiased = param.unbiased;
+
+				msaaRenderPassO.sampleLevel = param.sampleLevel;
+				msaaRenderPassO.unbiased = param.unbiased;
+
+				if( param.camera === 'perspective' ){
+					composerP.render();
+				}else{
+					composerO.render();
+				}
 
-				composer.render();
 				stats.end();
 
 			}

+ 47 - 1
src/cameras/OrthographicCamera.js

@@ -1,5 +1,6 @@
 /**
  * @author alteredq / http://alteredqualia.com/
+ * @author arose / http://github.com/arose
  */
 
 THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
@@ -9,6 +10,7 @@ THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
 	this.type = 'OrthographicCamera';
 
 	this.zoom = 1;
+	this.view = null;
 
 	this.left = left;
 	this.right = right;
@@ -38,11 +40,34 @@ THREE.OrthographicCamera.prototype = Object.assign( Object.create( THREE.Camera.
 		this.far = source.far;
 
 		this.zoom = source.zoom;
+		this.view = source.view === null ? null : Object.assign( {}, source.view );
 
 		return this;
 
 	},
 
+	setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) {
+
+		this.view = {
+			fullWidth: fullWidth,
+			fullHeight: fullHeight,
+			offsetX: x,
+			offsetY: y,
+			width: width,
+			height: height
+		};
+
+		this.updateProjectionMatrix();
+
+	},
+
+	clearViewOffset: function() {
+
+		this.view = null;
+		this.updateProjectionMatrix();
+
+	},
+
 	updateProjectionMatrix: function () {
 
 		var dx = ( this.right - this.left ) / ( 2 * this.zoom );
@@ -50,7 +75,26 @@ THREE.OrthographicCamera.prototype = Object.assign( Object.create( THREE.Camera.
 		var cx = ( this.right + this.left ) / 2;
 		var cy = ( this.top + this.bottom ) / 2;
 
-		this.projectionMatrix.makeOrthographic( cx - dx, cx + dx, cy + dy, cy - dy, this.near, this.far );
+		var left = cx - dx;
+		var right = cx + dx;
+		var top = cy + dy;
+		var bottom = cy - dy;
+
+		if ( this.view !== null ) {
+
+			var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
+			var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
+			var scaleW = ( this.right - this.left ) / this.view.width;
+			var scaleH = ( this.top - this.bottom ) / this.view.height;
+
+			left += scaleW * ( this.view.offsetX / zoomW );
+			right = left + scaleW * ( this.view.width / zoomW );
+			top -= scaleH * ( this.view.offsetY / zoomH );
+			bottom = top - scaleH * ( this.view.height / zoomH );
+
+		}
+
+		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
 
 	},
 
@@ -66,6 +110,8 @@ THREE.OrthographicCamera.prototype = Object.assign( Object.create( THREE.Camera.
 		data.object.near = this.near;
 		data.object.far = this.far;
 
+		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
+
 		return data;
 
 	}