PeppersGhostEffect.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import {
  2. PerspectiveCamera,
  3. Quaternion,
  4. Vector3
  5. } from 'three';
  6. /**
  7. * peppers ghost effect based on http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS
  8. */
  9. class PeppersGhostEffect {
  10. constructor( renderer ) {
  11. const scope = this;
  12. scope.cameraDistance = 15;
  13. scope.reflectFromAbove = false;
  14. // Internals
  15. let _halfWidth, _width, _height;
  16. const _cameraF = new PerspectiveCamera(); //front
  17. const _cameraB = new PerspectiveCamera(); //back
  18. const _cameraL = new PerspectiveCamera(); //left
  19. const _cameraR = new PerspectiveCamera(); //right
  20. const _position = new Vector3();
  21. const _quaternion = new Quaternion();
  22. const _scale = new Vector3();
  23. // Initialization
  24. renderer.autoClear = false;
  25. this.setSize = function ( width, height ) {
  26. _halfWidth = width / 2;
  27. if ( width < height ) {
  28. _width = width / 3;
  29. _height = width / 3;
  30. } else {
  31. _width = height / 3;
  32. _height = height / 3;
  33. }
  34. renderer.setSize( width, height );
  35. };
  36. this.render = function ( scene, camera ) {
  37. if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
  38. if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
  39. camera.matrixWorld.decompose( _position, _quaternion, _scale );
  40. // front
  41. _cameraF.position.copy( _position );
  42. _cameraF.quaternion.copy( _quaternion );
  43. _cameraF.translateZ( scope.cameraDistance );
  44. _cameraF.lookAt( scene.position );
  45. // back
  46. _cameraB.position.copy( _position );
  47. _cameraB.quaternion.copy( _quaternion );
  48. _cameraB.translateZ( - ( scope.cameraDistance ) );
  49. _cameraB.lookAt( scene.position );
  50. _cameraB.rotation.z += 180 * ( Math.PI / 180 );
  51. // left
  52. _cameraL.position.copy( _position );
  53. _cameraL.quaternion.copy( _quaternion );
  54. _cameraL.translateX( - ( scope.cameraDistance ) );
  55. _cameraL.lookAt( scene.position );
  56. _cameraL.rotation.x += 90 * ( Math.PI / 180 );
  57. // right
  58. _cameraR.position.copy( _position );
  59. _cameraR.quaternion.copy( _quaternion );
  60. _cameraR.translateX( scope.cameraDistance );
  61. _cameraR.lookAt( scene.position );
  62. _cameraR.rotation.x += 90 * ( Math.PI / 180 );
  63. renderer.clear();
  64. renderer.setScissorTest( true );
  65. renderer.setScissor( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height );
  66. renderer.setViewport( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height );
  67. if ( scope.reflectFromAbove ) {
  68. renderer.render( scene, _cameraB );
  69. } else {
  70. renderer.render( scene, _cameraF );
  71. }
  72. renderer.setScissor( _halfWidth - ( _width / 2 ), 0, _width, _height );
  73. renderer.setViewport( _halfWidth - ( _width / 2 ), 0, _width, _height );
  74. if ( scope.reflectFromAbove ) {
  75. renderer.render( scene, _cameraF );
  76. } else {
  77. renderer.render( scene, _cameraB );
  78. }
  79. renderer.setScissor( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height );
  80. renderer.setViewport( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height );
  81. if ( scope.reflectFromAbove ) {
  82. renderer.render( scene, _cameraR );
  83. } else {
  84. renderer.render( scene, _cameraL );
  85. }
  86. renderer.setScissor( _halfWidth + ( _width / 2 ), _height, _width, _height );
  87. renderer.setViewport( _halfWidth + ( _width / 2 ), _height, _width, _height );
  88. if ( scope.reflectFromAbove ) {
  89. renderer.render( scene, _cameraL );
  90. } else {
  91. renderer.render( scene, _cameraR );
  92. }
  93. renderer.setScissorTest( false );
  94. };
  95. }
  96. }
  97. export { PeppersGhostEffect };