OculusRiftEffect.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /**
  2. * @author troffmo5 / http://github.com/troffmo5
  3. *
  4. * Effect to render the scene in stereo 3d side by side with lens distortion.
  5. * It is written to be used with the Oculus Rift (http://www.oculusvr.com/) but
  6. * it works also with other HMD using the same technology
  7. */
  8. THREE.OculusRiftEffect = function ( renderer ) {
  9. // Configuration
  10. this.separation = 10;
  11. this.distortion = 0.1;
  12. this.aspectFactor = 1;
  13. this.fov = null; // use original camera FOV
  14. // initialization
  15. var _width, _height;
  16. var _pCamera = new THREE.PerspectiveCamera();
  17. _pCamera.matrixAutoUpdate = false;
  18. _pCamera.target = new THREE.Vector3();
  19. var _scene = new THREE.Scene();
  20. var _oCamera = new THREE.OrthographicCamera( -1, 1, 1, -1, 1, 1000 );
  21. _oCamera.position.z = 1;
  22. _scene.add( _oCamera );
  23. // pre-render hooks
  24. this.preLeftRender = function() {};
  25. this.preRightRender = function() {};
  26. renderer.autoClear = false;
  27. var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
  28. var _renderTarget = new THREE.WebGLRenderTarget( 800, 600, _params );
  29. var _material = new THREE.ShaderMaterial( {
  30. uniforms: {
  31. "tex": { type: "t", value: _renderTarget },
  32. "c": { type: "f", value: this.distortion }
  33. },
  34. vertexShader: [
  35. "varying vec2 vUv;",
  36. "void main() {",
  37. " vUv = uv;",
  38. " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
  39. "}"
  40. ].join("\n"),
  41. // Formula used from the paper: "Applying and removing lens distortion in post production"
  42. // by Gergely Vass , Tamás Perlaki
  43. // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.136.3745
  44. fragmentShader: [
  45. "uniform float c;",
  46. "uniform sampler2D tex;",
  47. "varying vec2 vUv;",
  48. "void main()",
  49. "{",
  50. " vec2 uv = vUv;",
  51. " vec2 vector = uv * 2.0 - 1.0;",
  52. " float factor = 1.0/(1.0+c);",
  53. " float vectorLen = length(vector);",
  54. " vec2 direction = vector / vectorLen;",
  55. " float newLen = vectorLen + c * pow(vectorLen,3.0);",
  56. " vec2 newVector = direction * newLen * factor;",
  57. " newVector = (newVector + 1.0) / 2.0;",
  58. " if (newVector.x < 0.0 || newVector.x > 1.0 || newVector.y < 0.0 || newVector.y > 1.0)",
  59. " gl_FragColor = vec4(0.0,0.0,0.0,1.0);",
  60. " else",
  61. " gl_FragColor = texture2D(tex, newVector);",
  62. "}"
  63. ].join("\n")
  64. } );
  65. var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material );
  66. _scene.add( mesh );
  67. this.setSize = function ( width, height ) {
  68. _width = width / 2;
  69. _height = height;
  70. _renderTarget = new THREE.WebGLRenderTarget( width, height, _params );
  71. _material.uniforms[ "tex" ].value = _renderTarget;
  72. renderer.setSize( width, height );
  73. };
  74. this.render = function ( scene, camera ) {
  75. renderer.clear();
  76. _material.uniforms['c'].value = this.distortion;
  77. // camera parameters
  78. if (camera.matrixAutoUpdate) camera.updateMatrix();
  79. _pCamera.fov = this.fov ? this.fov : camera.fov;
  80. _pCamera.aspect = camera.aspect / (2*this.aspectFactor);
  81. _pCamera.near = camera.near;
  82. _pCamera.far = camera.far;
  83. _pCamera.updateProjectionMatrix();
  84. // Render left
  85. this.preLeftRender();
  86. var offset = new THREE.Vector3(-this.separation,0,0);
  87. _pCamera.matrix.copy(camera.matrix);
  88. _pCamera.matrix.translate(offset);
  89. _pCamera.matrixWorldNeedsUpdate = true;
  90. renderer.setViewport( 0, 0, _width, _height );
  91. renderer.render( scene, _pCamera, _renderTarget, true );
  92. renderer.render( _scene, _oCamera );
  93. // Render right
  94. this.preRightRender();
  95. offset.set(this.separation,0,0);
  96. _pCamera.matrix.copy(camera.matrix);
  97. _pCamera.matrix.translate(offset);
  98. _pCamera.matrixWorldNeedsUpdate = true;
  99. renderer.setViewport( _width, 0, _width, _height );
  100. renderer.render( scene, _pCamera, _renderTarget, true );
  101. renderer.render( _scene, _oCamera );
  102. };
  103. };