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 };
							 |