Spaces:
Running
Running
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 }; | |