WebGLMultiview.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * @author fernandojsg / http://fernandojsg.com
  3. * @author Takahiro https://github.com/takahirox
  4. */
  5. import { WebGLMultiviewRenderTarget } from '../WebGLMultiviewRenderTarget.js';
  6. import { Matrix3 } from '../../math/Matrix3.js';
  7. import { Matrix4 } from '../../math/Matrix4.js';
  8. import { Vector2 } from '../../math/Vector2.js';
  9. function WebGLMultiview( renderer, gl ) {
  10. var DEFAULT_NUMVIEWS = 2;
  11. var extensions = renderer.extensions;
  12. var properties = renderer.properties;
  13. var renderTarget, currentRenderTarget;
  14. var mat3, mat4, cameraArray, renderSize;
  15. var available;
  16. var maxNumViews = 0;
  17. //
  18. function isAvailable() {
  19. if ( available === undefined ) {
  20. var extension = extensions.get( 'OVR_multiview2' );
  21. available = extension !== null && gl.getContextAttributes().antialias === false;
  22. if ( available ) {
  23. maxNumViews = gl.getParameter( extension.MAX_VIEWS_OVR );
  24. renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
  25. renderSize = new Vector2();
  26. mat4 = [];
  27. mat3 = [];
  28. cameraArray = [];
  29. for ( var i = 0; i < maxNumViews; i ++ ) {
  30. mat4[ i ] = new Matrix4();
  31. mat3[ i ] = new Matrix3();
  32. }
  33. }
  34. }
  35. return available;
  36. }
  37. function getCameraArray( camera ) {
  38. if ( camera.isArrayCamera ) return camera.cameras;
  39. cameraArray[ 0 ] = camera;
  40. return cameraArray;
  41. }
  42. function updateCameraProjectionMatricesUniform( camera, uniforms ) {
  43. var cameras = getCameraArray( camera );
  44. for ( var i = 0; i < cameras.length; i ++ ) {
  45. mat4[ i ].copy( cameras[ i ].projectionMatrix );
  46. }
  47. uniforms.setValue( gl, 'projectionMatrices', mat4 );
  48. }
  49. function updateCameraViewMatricesUniform( camera, uniforms ) {
  50. var cameras = getCameraArray( camera );
  51. for ( var i = 0; i < cameras.length; i ++ ) {
  52. mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
  53. }
  54. uniforms.setValue( gl, 'viewMatrices', mat4 );
  55. }
  56. function updateObjectMatricesUniforms( object, camera, uniforms ) {
  57. var cameras = getCameraArray( camera );
  58. for ( var i = 0; i < cameras.length; i ++ ) {
  59. mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );
  60. mat3[ i ].getNormalMatrix( mat4[ i ] );
  61. }
  62. uniforms.setValue( gl, 'modelViewMatrices', mat4 );
  63. uniforms.setValue( gl, 'normalMatrices', mat3 );
  64. }
  65. function isMultiviewCompatible( camera ) {
  66. if ( camera.isArrayCamera === undefined ) return true;
  67. var cameras = camera.cameras;
  68. if ( cameras.length > maxNumViews ) return false;
  69. for ( var i = 1, il = cameras.length; i < il; i ++ ) {
  70. if ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||
  71. cameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) return false;
  72. }
  73. return true;
  74. }
  75. function resizeRenderTarget( camera ) {
  76. if ( currentRenderTarget ) {
  77. renderSize.set( currentRenderTarget.width, currentRenderTarget.height );
  78. } else {
  79. renderer.getDrawingBufferSize( renderSize );
  80. }
  81. if ( camera.isArrayCamera ) {
  82. var viewport = camera.cameras[ 0 ].viewport;
  83. renderTarget.setSize( viewport.z, viewport.w );
  84. renderTarget.setNumViews( camera.cameras.length );
  85. } else {
  86. renderTarget.setSize( renderSize.x, renderSize.y );
  87. renderTarget.setNumViews( DEFAULT_NUMVIEWS );
  88. }
  89. }
  90. function attachCamera( camera ) {
  91. if ( isMultiviewCompatible( camera ) === false ) return;
  92. currentRenderTarget = renderer.getRenderTarget();
  93. resizeRenderTarget( camera );
  94. renderer.setRenderTarget( renderTarget );
  95. }
  96. function detachCamera( camera ) {
  97. if ( renderTarget !== renderer.getRenderTarget() ) return;
  98. renderer.setRenderTarget( currentRenderTarget );
  99. flush( camera );
  100. }
  101. function flush( camera ) {
  102. var srcRenderTarget = renderTarget;
  103. var numViews = srcRenderTarget.numViews;
  104. var srcFramebuffers = properties.get( srcRenderTarget ).__webglViewFramebuffers;
  105. var viewWidth = srcRenderTarget.width;
  106. var viewHeight = srcRenderTarget.height;
  107. if ( camera.isArrayCamera ) {
  108. for ( var i = 0; i < numViews; i ++ ) {
  109. var viewport = camera.cameras[ i ].viewport;
  110. var x1 = viewport.x;
  111. var y1 = viewport.y;
  112. var x2 = x1 + viewport.z;
  113. var y2 = y1 + viewport.w;
  114. gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
  115. gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
  116. }
  117. } else {
  118. gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ 0 ] );
  119. gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, 0, 0, renderSize.x, renderSize.y, gl.COLOR_BUFFER_BIT, gl.NEAREST );
  120. }
  121. }
  122. this.isAvailable = isAvailable;
  123. this.attachCamera = attachCamera;
  124. this.detachCamera = detachCamera;
  125. this.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;
  126. this.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;
  127. this.updateObjectMatricesUniforms = updateObjectMatricesUniforms;
  128. }
  129. export { WebGLMultiview };