StereoEffect.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. * @authod mrdoob / http://mrdoob.com/
  4. * @authod arodic / http://aleksandarrodic.com/
  5. * @authod fonserbc / http://twitter.com/fonserbc
  6. *
  7. * Off-axis stereoscopic effect based on http://paulbourke.net/stereographics/stereorender/
  8. */
  9. THREE.StereoEffect = function ( renderer ) {
  10. // API
  11. this.eyeSeparation = 3;
  12. this.focalLength = 15;
  13. // internals
  14. var _width, _height;
  15. var _position = new THREE.Vector3();
  16. var _quaternion = new THREE.Quaternion();
  17. var _scale = new THREE.Vector3();
  18. var _cameraL = new THREE.PerspectiveCamera();
  19. var _cameraR = new THREE.PerspectiveCamera();
  20. var _fov;
  21. var _outer, _inner, _top, _bottom;
  22. var _ndfl, _halfFocalWidth, _halfFocalHeight;
  23. var _innerFactor, _outerFactor;
  24. // initialization
  25. renderer.autoClear = false;
  26. this.setSize = function ( width, height ) {
  27. _width = width / 2;
  28. _height = height;
  29. renderer.setSize( width, height );
  30. };
  31. this.render = function ( scene, camera ) {
  32. scene.updateMatrixWorld();
  33. if ( camera.parent === undefined ) camera.updateMatrixWorld();
  34. camera.matrixWorld.decompose( _position, _quaternion, _scale );
  35. // Stereo frustum calculation
  36. _fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( camera.fov ) * 0.5 ) / camera.zoom ) );
  37. _ndfl = camera.near / this.focalLength;
  38. _halfFocalHeight = Math.tan( THREE.Math.degToRad( _fov ) * 0.5 ) * this.focalLength;
  39. _halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;
  40. _top = _halfFocalHeight * _ndfl;
  41. _bottom = - _top;
  42. _innerFactor = ( _halfFocalWidth + this.eyeSeparation / 2.0 ) / ( _halfFocalWidth * 2.0 );
  43. _outerFactor = 1.0 - _innerFactor;
  44. _outer = _halfFocalWidth * 2.0 * _ndfl * _outerFactor;
  45. _inner = _halfFocalWidth * 2.0 * _ndfl * _innerFactor;
  46. // left
  47. _cameraL.fov = _fov;
  48. _cameraL.aspect = 0.5 * camera.aspect;
  49. _cameraL.near = camera.near;
  50. _cameraL.far = camera.far;
  51. _cameraL.projectionMatrix.makeFrustum(
  52. - _outer,
  53. _inner,
  54. _bottom,
  55. _top,
  56. camera.near,
  57. camera.far
  58. );
  59. _cameraL.position.copy( _position );
  60. _cameraL.quaternion.copy( _quaternion );
  61. _cameraL.translateX( - this.eyeSeparation / 2.0 );
  62. // right
  63. _cameraR.fov = _fov;
  64. _cameraR.aspect = 0.5 * camera.aspect;
  65. _cameraR.near = camera.near;
  66. _cameraR.far = camera.far;
  67. _cameraR.projectionMatrix.makeFrustum(
  68. - _inner,
  69. _outer,
  70. _bottom,
  71. _top,
  72. camera.near,
  73. camera.far
  74. );
  75. _cameraR.position.copy( _position );
  76. _cameraR.quaternion.copy( _quaternion );
  77. _cameraR.translateX( this.eyeSeparation / 2.0 );
  78. //
  79. renderer.setViewport( 0, 0, _width * 2, _height );
  80. renderer.clear();
  81. renderer.setViewport( 0, 0, _width, _height );
  82. renderer.render( scene, _cameraL );
  83. renderer.setViewport( _width, 0, _width, _height );
  84. renderer.render( scene, _cameraR );
  85. };
  86. };