StereoEffect.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. * @authod mrdoob / http://mrdoob.com/
  4. * @authod arodic / http://aleksandarrodic.com/
  5. * @authod fonserbc / http://fonserbc.github.io/
  6. *
  7. * Off-axis stereoscopic effect based on http://paulbourke.net/stereographics/stereorender/
  8. */
  9. THREE.StereoEffect = function ( renderer ) {
  10. // API
  11. var scope = this;
  12. this.eyeSeparation = 3;
  13. this.focalLength = 15; // Distance to the non-parallax or projection plane
  14. Object.defineProperties( this, {
  15. separation: {
  16. get: function () {
  17. return scope.eyeSeparation;
  18. },
  19. set: function ( value ) {
  20. console.warn( 'THREE.StereoEffect: .separation is now .eyeSeparation.' );
  21. scope.eyeSeparation = value;
  22. }
  23. },
  24. targetDistance: {
  25. get: function () {
  26. return scope.focalLength;
  27. },
  28. set: function ( value ) {
  29. console.warn( 'THREE.StereoEffect: .targetDistance is now .focalLength.' );
  30. scope.focalLength = value;
  31. }
  32. }
  33. } );
  34. // internals
  35. var _width, _height;
  36. var _position = new THREE.Vector3();
  37. var _quaternion = new THREE.Quaternion();
  38. var _scale = new THREE.Vector3();
  39. var _cameraL = new THREE.PerspectiveCamera();
  40. var _cameraR = new THREE.PerspectiveCamera();
  41. var _fov;
  42. var _outer, _inner, _top, _bottom;
  43. var _ndfl, _halfFocalWidth, _halfFocalHeight;
  44. var _innerFactor, _outerFactor;
  45. // initialization
  46. renderer.autoClear = false;
  47. this.setSize = function ( width, height ) {
  48. _width = width / 2;
  49. _height = height;
  50. renderer.setSize( width, height );
  51. };
  52. this.render = function ( scene, camera ) {
  53. scene.updateMatrixWorld();
  54. if ( camera.parent === null ) camera.updateMatrixWorld();
  55. camera.matrixWorld.decompose( _position, _quaternion, _scale );
  56. // Effective fov of the camera
  57. _fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( camera.fov ) * 0.5 ) / camera.zoom ) );
  58. _ndfl = camera.near / this.focalLength;
  59. _halfFocalHeight = Math.tan( THREE.Math.degToRad( _fov ) * 0.5 ) * this.focalLength;
  60. _halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;
  61. _top = _halfFocalHeight * _ndfl;
  62. _bottom = - _top;
  63. _innerFactor = ( _halfFocalWidth + this.eyeSeparation / 2.0 ) / ( _halfFocalWidth * 2.0 );
  64. _outerFactor = 1.0 - _innerFactor;
  65. _outer = _halfFocalWidth * 2.0 * _ndfl * _outerFactor;
  66. _inner = _halfFocalWidth * 2.0 * _ndfl * _innerFactor;
  67. // left
  68. _cameraL.projectionMatrix.makeFrustum(
  69. - _outer,
  70. _inner,
  71. _bottom,
  72. _top,
  73. camera.near,
  74. camera.far
  75. );
  76. _cameraL.position.copy( _position );
  77. _cameraL.quaternion.copy( _quaternion );
  78. _cameraL.translateX( - this.eyeSeparation / 2.0 );
  79. // right
  80. _cameraR.projectionMatrix.makeFrustum(
  81. - _inner,
  82. _outer,
  83. _bottom,
  84. _top,
  85. camera.near,
  86. camera.far
  87. );
  88. _cameraR.position.copy( _position );
  89. _cameraR.quaternion.copy( _quaternion );
  90. _cameraR.translateX( this.eyeSeparation / 2.0 );
  91. //
  92. renderer.clear();
  93. renderer.enableScissorTest( true );
  94. renderer.setScissor( 0, 0, _width, _height );
  95. renderer.setViewport( 0, 0, _width, _height );
  96. renderer.render( scene, _cameraL );
  97. renderer.setScissor( _width, 0, _width, _height );
  98. renderer.setViewport( _width, 0, _width, _height );
  99. renderer.render( scene, _cameraR );
  100. renderer.enableScissorTest( false );
  101. };
  102. };