WebGLMultiview.js 4.2 KB

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