154 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			154 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | import { | ||
|  | 	PerspectiveCamera, | ||
|  | 	Quaternion, | ||
|  | 	Vector3 | ||
|  | } from 'three'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * peppers ghost effect based on http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS
 | ||
|  |  */ | ||
|  | 
 | ||
|  | class PeppersGhostEffect { | ||
|  | 
 | ||
|  | 	constructor( renderer ) { | ||
|  | 
 | ||
|  | 		const scope = this; | ||
|  | 
 | ||
|  | 		scope.cameraDistance = 15; | ||
|  | 		scope.reflectFromAbove = false; | ||
|  | 
 | ||
|  | 		// Internals
 | ||
|  | 		let _halfWidth, _width, _height; | ||
|  | 
 | ||
|  | 		const _cameraF = new PerspectiveCamera(); //front
 | ||
|  | 		const _cameraB = new PerspectiveCamera(); //back
 | ||
|  | 		const _cameraL = new PerspectiveCamera(); //left
 | ||
|  | 		const _cameraR = new PerspectiveCamera(); //right
 | ||
|  | 
 | ||
|  | 		const _position = new Vector3(); | ||
|  | 		const _quaternion = new Quaternion(); | ||
|  | 		const _scale = new Vector3(); | ||
|  | 
 | ||
|  | 		// Initialization
 | ||
|  | 		renderer.autoClear = false; | ||
|  | 
 | ||
|  | 		this.setSize = function ( width, height ) { | ||
|  | 
 | ||
|  | 			_halfWidth = width / 2; | ||
|  | 			if ( width < height ) { | ||
|  | 
 | ||
|  | 				_width = width / 3; | ||
|  | 				_height = width / 3; | ||
|  | 
 | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				_width = height / 3; | ||
|  | 				_height = height / 3; | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			renderer.setSize( width, height ); | ||
|  | 
 | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		this.render = function ( scene, camera ) { | ||
|  | 
 | ||
|  | 			if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); | ||
|  | 
 | ||
|  | 			if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
|  | 
 | ||
|  | 			camera.matrixWorld.decompose( _position, _quaternion, _scale ); | ||
|  | 
 | ||
|  | 			// front
 | ||
|  | 			_cameraF.position.copy( _position ); | ||
|  | 			_cameraF.quaternion.copy( _quaternion ); | ||
|  | 			_cameraF.translateZ( scope.cameraDistance ); | ||
|  | 			_cameraF.lookAt( scene.position ); | ||
|  | 
 | ||
|  | 			// back
 | ||
|  | 			_cameraB.position.copy( _position ); | ||
|  | 			_cameraB.quaternion.copy( _quaternion ); | ||
|  | 			_cameraB.translateZ( - ( scope.cameraDistance ) ); | ||
|  | 			_cameraB.lookAt( scene.position ); | ||
|  | 			_cameraB.rotation.z += 180 * ( Math.PI / 180 ); | ||
|  | 
 | ||
|  | 			// left
 | ||
|  | 			_cameraL.position.copy( _position ); | ||
|  | 			_cameraL.quaternion.copy( _quaternion ); | ||
|  | 			_cameraL.translateX( - ( scope.cameraDistance ) ); | ||
|  | 			_cameraL.lookAt( scene.position ); | ||
|  | 			_cameraL.rotation.x += 90 * ( Math.PI / 180 ); | ||
|  | 
 | ||
|  | 			// right
 | ||
|  | 			_cameraR.position.copy( _position ); | ||
|  | 			_cameraR.quaternion.copy( _quaternion ); | ||
|  | 			_cameraR.translateX( scope.cameraDistance ); | ||
|  | 			_cameraR.lookAt( scene.position ); | ||
|  | 			_cameraR.rotation.x += 90 * ( Math.PI / 180 ); | ||
|  | 
 | ||
|  | 
 | ||
|  | 			renderer.clear(); | ||
|  | 			renderer.setScissorTest( true ); | ||
|  | 
 | ||
|  | 			renderer.setScissor( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height ); | ||
|  | 			renderer.setViewport( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height ); | ||
|  | 
 | ||
|  | 			if ( scope.reflectFromAbove ) { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraB ); | ||
|  | 
 | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraF ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			renderer.setScissor( _halfWidth - ( _width / 2 ), 0, _width, _height ); | ||
|  | 			renderer.setViewport( _halfWidth - ( _width / 2 ), 0, _width, _height ); | ||
|  | 
 | ||
|  | 			if ( scope.reflectFromAbove ) { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraF ); | ||
|  | 
 | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraB ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			renderer.setScissor( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height ); | ||
|  | 			renderer.setViewport( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height ); | ||
|  | 
 | ||
|  | 			if ( scope.reflectFromAbove ) { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraR ); | ||
|  | 
 | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraL ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			renderer.setScissor( _halfWidth + ( _width / 2 ), _height, _width, _height ); | ||
|  | 			renderer.setViewport( _halfWidth + ( _width / 2 ), _height, _width, _height ); | ||
|  | 
 | ||
|  | 			if ( scope.reflectFromAbove ) { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraL ); | ||
|  | 
 | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				renderer.render( scene, _cameraR ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			renderer.setScissorTest( false ); | ||
|  | 
 | ||
|  | 		}; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | export { PeppersGhostEffect }; |