ParallaxBarrierEffect.js 4.3 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/**
 * @author mrdoob / http://mrdoob.com/
 * @author marklundin / http://mark-lundin.com/
 * @author alteredq / http://alteredqualia.com/
 */

THREE.ParallaxBarrierEffect = function ( renderer ) {

	var eyeRight = new THREE.Matrix4();
	var eyeLeft = new THREE.Matrix4();
	var focalLength = 125;
	var _aspect, _near, _far, _fov;

	var _cameraL = new THREE.PerspectiveCamera();
	_cameraL.matrixAutoUpdate = false;

	var _cameraR = new THREE.PerspectiveCamera();
	_cameraR.matrixAutoUpdate = false;

	var _scene = new THREE.Scene();

	var _camera = new THREE.PerspectiveCamera( 53, 1, 1, 10000 );
	_camera.position.z = 2;
	_scene.add( _camera );

	var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };

	var _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params );
	var _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params );

	var _material = new THREE.ShaderMaterial( {

		uniforms: {

			"mapLeft": { type: "t", value: _renderTargetL },
			"mapRight": { type: "t", value: _renderTargetR }

		},

		vertexShader: [

			"varying vec2 vUv;",

			"void main() {",

			"	vUv = vec2( uv.x, uv.y );",
			"	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",

			"}"

M
r72  
Mr.doob 已提交
51
		].join( "\n" ),
M
Mr.doob 已提交
52 53 54 55 56 57 58 59 60 61 62

		fragmentShader: [

			"uniform sampler2D mapLeft;",
			"uniform sampler2D mapRight;",
			"varying vec2 vUv;",

			"void main() {",

			"	vec2 uv = vUv;",

M
r63  
Mr.doob 已提交
63
			"	if ( ( mod( gl_FragCoord.y, 2.0 ) ) > 1.00 ) {",
M
Mr.doob 已提交
64 65 66 67 68 69 70 71 72 73 74

			"		gl_FragColor = texture2D( mapLeft, uv );",

			"	} else {",

			"		gl_FragColor = texture2D( mapRight, uv );",

			"	}",

			"}"

M
r72  
Mr.doob 已提交
75
		].join( "\n" )
M
Mr.doob 已提交
76 77 78

	} );

M
r69  
Mr.doob 已提交
79
	var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), _material );
M
Mr.doob 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	_scene.add( mesh );

	this.setSize = function ( width, height ) {

		_renderTargetL = new THREE.WebGLRenderTarget( width, height, _params );
		_renderTargetR = new THREE.WebGLRenderTarget( width, height, _params );

		_material.uniforms[ "mapLeft" ].value = _renderTargetL;
		_material.uniforms[ "mapRight" ].value = _renderTargetR;

		renderer.setSize( width, height );

	};

	/*
	 * 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 ) {

		scene.updateMatrixWorld();

M
r72  
Mr.doob 已提交
107
		if ( camera.parent === null ) camera.updateMatrixWorld();
M
Mr.doob 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

		var hasCameraChanged = ( _aspect !== camera.aspect ) || ( _near !== camera.near ) || ( _far !== camera.far ) || ( _fov !== camera.fov );

		if ( hasCameraChanged ) {

			_aspect = camera.aspect;
			_near = camera.near;
			_far = camera.far;
			_fov = camera.fov;

			var projectionMatrix = camera.projectionMatrix.clone();
			var eyeSep = focalLength / 30 * 0.5;
			var eyeSepOnProjection = eyeSep * _near / focalLength;
			var ymax = _near * Math.tan( THREE.Math.degToRad( _fov * 0.5 ) );
			var xmin, xmax;

			// translate xOffset

M
r72  
Mr.doob 已提交
126 127
			eyeRight.elements[ 12 ] = eyeSep;
			eyeLeft.elements[ 12 ] = - eyeSep;
M
Mr.doob 已提交
128 129 130

			// for left eye

M
r72  
Mr.doob 已提交
131
			xmin = - ymax * _aspect + eyeSepOnProjection;
M
Mr.doob 已提交
132 133
			xmax = ymax * _aspect + eyeSepOnProjection;

M
r72  
Mr.doob 已提交
134 135
			projectionMatrix.elements[ 0 ] = 2 * _near / ( xmax - xmin );
			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
M
Mr.doob 已提交
136 137 138 139 140

			_cameraL.projectionMatrix.copy( projectionMatrix );

			// for right eye

M
r72  
Mr.doob 已提交
141
			xmin = - ymax * _aspect - eyeSepOnProjection;
M
Mr.doob 已提交
142 143
			xmax = ymax * _aspect - eyeSepOnProjection;

M
r72  
Mr.doob 已提交
144 145
			projectionMatrix.elements[ 0 ] = 2 * _near / ( xmax - xmin );
			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
M
Mr.doob 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

			_cameraR.projectionMatrix.copy( projectionMatrix );

		}

		_cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
		_cameraL.position.copy( camera.position );
		_cameraL.near = camera.near;
		_cameraL.far = camera.far;

		renderer.render( scene, _cameraL, _renderTargetL, true );

		_cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
		_cameraR.position.copy( camera.position );
		_cameraR.near = camera.near;
		_cameraR.far = camera.far;

		renderer.render( scene, _cameraR, _renderTargetR, true );

		_scene.updateMatrixWorld();

		renderer.render( _scene, _camera );

	};

};