WebGLMultiview.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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, requested, options ) {
  10. options = Object.assign( {}, { debug: false }, options );
  11. var DEFAULT_NUMVIEWS = 2;
  12. var gl = renderer.context;
  13. var capabilities = renderer.capabilities;
  14. var properties = renderer.properties;
  15. var maxNumViews = capabilities.maxMultiviewViews;
  16. var renderTarget, currentRenderTarget;
  17. var mat3, mat4, cameraArray, renderSize;
  18. function getMaxViews() {
  19. return capabilities.maxMultiviewViews;
  20. }
  21. function getNumViews() {
  22. if ( renderTarget && renderer.getRenderTarget() === renderTarget ) {
  23. return renderTarget.numViews;
  24. }
  25. return 0;
  26. }
  27. function getCameraArray( camera ) {
  28. if ( camera.isArrayCamera ) return camera.cameras;
  29. cameraArray[ 0 ] = camera;
  30. return cameraArray;
  31. }
  32. //
  33. function isAvailable() {
  34. return capabilities.multiview;
  35. }
  36. function isEnabled() {
  37. return requested && isAvailable();
  38. }
  39. if ( options.debug ) {
  40. if ( requested && ! isAvailable() ) {
  41. console.warn( 'WebGLRenderer: Multiview requested but not supported by the browser' );
  42. } else if ( requested !== false && isAvailable() ) {
  43. console.info( 'WebGLRenderer: Multiview enabled' );
  44. }
  45. }
  46. function updateCameraProjectionMatricesUniform( camera, uniforms ) {
  47. var cameras = getCameraArray( camera );
  48. for ( var i = 0; i < cameras.length; i ++ ) {
  49. mat4[ i ].copy( cameras[ i ].projectionMatrix );
  50. }
  51. uniforms.setValue( gl, 'projectionMatrices', mat4 );
  52. }
  53. function updateCameraViewMatricesUniform( camera, uniforms ) {
  54. var cameras = getCameraArray( camera );
  55. for ( var i = 0; i < cameras.length; i ++ ) {
  56. mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
  57. }
  58. uniforms.setValue( gl, 'viewMatrices', mat4 );
  59. }
  60. function updateObjectMatricesUniforms( object, camera, uniforms ) {
  61. var cameras = getCameraArray( camera );
  62. for ( var i = 0; i < cameras.length; i ++ ) {
  63. mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );
  64. mat3[ i ].getNormalMatrix( mat4[ i ] );
  65. }
  66. uniforms.setValue( gl, 'modelViewMatrices', mat4 );
  67. uniforms.setValue( gl, 'normalMatrices', mat3 );
  68. }
  69. function isMultiviewCompatible( camera ) {
  70. if ( ! camera.isArrayCamera ) return true;
  71. var cameras = camera.cameras;
  72. if ( cameras.length > maxNumViews ) return false;
  73. for ( var i = 1, il = cameras.length; i < il; i ++ ) {
  74. if ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||
  75. cameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) return false;
  76. }
  77. return true;
  78. }
  79. function resizeRenderTarget( camera ) {
  80. if ( currentRenderTarget ) {
  81. renderSize.set( currentRenderTarget.width, currentRenderTarget.height );
  82. } else {
  83. renderer.getDrawingBufferSize( renderSize );
  84. }
  85. if ( camera.isArrayCamera ) {
  86. var viewport = camera.cameras[ 0 ].viewport;
  87. renderTarget.setSize( viewport.z, viewport.w );
  88. renderTarget.setNumViews( camera.cameras.length );
  89. } else {
  90. renderTarget.setSize( renderSize.x, renderSize.y );
  91. renderTarget.setNumViews( DEFAULT_NUMVIEWS );
  92. }
  93. }
  94. function attachRenderTarget( camera ) {
  95. if ( ! isMultiviewCompatible( camera ) ) return;
  96. currentRenderTarget = renderer.getRenderTarget();
  97. resizeRenderTarget( camera );
  98. renderer.setRenderTarget( renderTarget );
  99. }
  100. function detachRenderTarget( camera ) {
  101. if ( renderTarget !== renderer.getRenderTarget() ) return false;
  102. renderer.setRenderTarget( currentRenderTarget );
  103. flush( camera );
  104. }
  105. function flush( camera ) {
  106. var srcRenderTarget = renderTarget;
  107. var numViews = srcRenderTarget.numViews;
  108. var srcFramebuffers = properties.get( srcRenderTarget ).__webglViewFramebuffers;
  109. var viewWidth = srcRenderTarget.width;
  110. var viewHeight = srcRenderTarget.height;
  111. if ( camera.isArrayCamera ) {
  112. for ( var i = 0; i < numViews; i ++ ) {
  113. var viewport = camera.cameras[ i ].viewport;
  114. var x1 = viewport.x;
  115. var y1 = viewport.y;
  116. var x2 = x1 + viewport.z;
  117. var y2 = y1 + viewport.w;
  118. gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
  119. gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
  120. }
  121. } else {
  122. gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ 0 ] );
  123. gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, 0, 0, renderSize.x, renderSize.y, gl.COLOR_BUFFER_BIT, gl.NEAREST );
  124. }
  125. }
  126. if ( isEnabled() ) {
  127. renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
  128. renderSize = new Vector2();
  129. mat4 = [];
  130. mat3 = [];
  131. cameraArray = [];
  132. for ( var i = 0; i < getMaxViews(); i ++ ) {
  133. mat4[ i ] = new Matrix4();
  134. mat3[ i ] = new Matrix3();
  135. }
  136. }
  137. this.attachRenderTarget = attachRenderTarget;
  138. this.detachRenderTarget = detachRenderTarget;
  139. this.isAvailable = isAvailable;
  140. this.isEnabled = isEnabled;
  141. this.getNumViews = getNumViews;
  142. this.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;
  143. this.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;
  144. this.updateObjectMatricesUniforms = updateObjectMatricesUniforms;
  145. }
  146. export { WebGLMultiview };