Bläddra i källkod

Modified Anaglyph Renderer to use an asymmetric perspective projection. Added focal length to the equation and updated to allow for camera rotation

Mark Lundin 14 år sedan
förälder
incheckning
72be2f0ad4
1 ändrade filer med 65 tillägg och 12 borttagningar
  1. 65 12
      src/extras/renderers/AnaglyphWebGLRenderer.js

+ 65 - 12
src/extras/renderers/AnaglyphWebGLRenderer.js

@@ -2,12 +2,19 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-THREE.AnaglyphWebGLRenderer = function ( parameters ) {
+THREE.AnaglyphWebGLRenderer = function ( parameters ) {	
 
 	THREE.WebGLRenderer.call( this, parameters );
 
 	var _this = this, _setSize = this.setSize, _render = this.render;
 	var _cameraL = new THREE.Camera(), _cameraR = new THREE.Camera();
+	var eyeRight = new THREE.Matrix4(),
+		eyeLeft = new THREE.Matrix4(),
+		focalLength = 125,
+		aspect, near, fov;
+	
+	_cameraL.useTarget = _cameraR.useTarget = false;
+	_cameraL.matrixAutoUpdate = _cameraR.matrixAutoUpdate = false;
 
 	var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
 	var _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params ), _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params );
@@ -74,21 +81,67 @@ THREE.AnaglyphWebGLRenderer = function ( parameters ) {
 
 	};
 
-	this.render = function ( scene, camera, renderTarget, forceClear ) {
-
-		_cameraL.projectionMatrix = camera.projectionMatrix;
+	/*
+	 * Renderer now uses an asymmetric perspective projection (http://paulbourke.net/miscellaneous/stereographics/stereorender/). 
+	 * Each camera is offset by the eye seperation and its projection matrix is also skewed asymetrically back to converge on the same
+	 * projection plane. Added a focal length parameter to, this is where the parallax is equal to 0. 
+	 */
+	this.render = function ( scene, camera, renderTarget, forceClear ) {	
+		
+		
+		camera.update( null, true );
+		
+		var hasCameraChanged = 	aspect !== camera.aspect || 
+								near !== camera.near ||
+								fov !== camera.fov;
+								
+		if( hasCameraChanged )
+		{
+		
+			aspect = camera.aspect;
+			near = camera.near;
+			fov = camera.fov;	
+		
+			var projectionMatrix = camera.projectionMatrix.clone(),
+				eyeSep = focalLength / 30 * 0.5,
+				eyeSepOnProjection = eyeSep * near / focalLength,
+				ymax = near * Math.tan( fov * Math.PI / 360 ),
+				xmin, xmax;
+
+			//translate xOffset
+			eyeRight.n14 = eyeSep;
+			eyeLeft.n14 = -eyeSep;
+	
+			//For left eye
+			xmin = -ymax * aspect + eyeSepOnProjection;
+			xmax = ymax * aspect + eyeSepOnProjection;
+			projectionMatrix.n11 = 2 * near / ( xmax - xmin );
+			projectionMatrix.n13 = ( xmax + xmin ) / ( xmax - xmin );
+			_cameraL.projectionMatrix = projectionMatrix.clone();
+			
+			//for right eye		
+			xmin = -ymax * aspect - eyeSepOnProjection;
+			xmax = ymax * aspect - eyeSepOnProjection;
+			projectionMatrix.n11 = 2 * near / ( xmax - xmin );
+			projectionMatrix.n13 = ( xmax + xmin ) / ( xmax - xmin );
+			_cameraR.projectionMatrix = projectionMatrix.clone();
+				
+		}	
+		
+		_cameraL.matrix = camera.matrixWorld.clone().multiplySelf( eyeLeft );
+		_cameraL.update(null, true);
 		_cameraL.position.copy( camera.position );
-		_cameraL.target.position.copy( camera.target.position );
-		_cameraL.translateX( - 10 );
+		_cameraL.near = near;
+		_cameraL.far = camera.far;
+		_render.call( _this, scene, _cameraL, _renderTargetL, true );
 
-		_cameraR.projectionMatrix = camera.projectionMatrix;
+		_cameraR.matrix = camera.matrixWorld.clone().multiplySelf( eyeRight );
+		_cameraR.update(null, true);
 		_cameraR.position.copy( camera.position );
-		_cameraR.target.position.copy( camera.target.position );
-		_cameraR.translateX( 10 );
-
-		_render.call( _this, scene, _cameraL, _renderTargetL, true );
+		_cameraR.near = near;
+		_cameraR.far = camera.far;
 		_render.call( _this, scene, _cameraR, _renderTargetR, true );
-
+		
 		_render.call( _this, _scene, _camera );
 
 	};