engine.multiview.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { Camera } from "../../Cameras/camera.js";
  2. import { Engine } from "../../Engines/engine.js";
  3. import { Scene } from "../../scene.js";
  4. import { InternalTexture, InternalTextureSource } from "../../Materials/Textures/internalTexture.js";
  5. import { Matrix, TmpVectors } from "../../Maths/math.vector.js";
  6. import { UniformBuffer } from "../../Materials/uniformBuffer.js";
  7. import { MultiviewRenderTarget } from "../../Materials/Textures/MultiviewRenderTarget.js";
  8. import { Frustum } from "../../Maths/math.frustum.js";
  9. Engine.prototype.createMultiviewRenderTargetTexture = function (width, height, colorTexture, depthStencilTexture) {
  10. const gl = this._gl;
  11. if (!this.getCaps().multiview) {
  12. // eslint-disable-next-line no-throw-literal
  13. throw "Multiview is not supported";
  14. }
  15. const rtWrapper = this._createHardwareRenderTargetWrapper(false, false, { width, height });
  16. rtWrapper._framebuffer = gl.createFramebuffer();
  17. const internalTexture = new InternalTexture(this, InternalTextureSource.Unknown, true);
  18. internalTexture.width = width;
  19. internalTexture.height = height;
  20. internalTexture.isMultiview = true;
  21. if (!colorTexture) {
  22. colorTexture = gl.createTexture();
  23. gl.bindTexture(gl.TEXTURE_2D_ARRAY, colorTexture);
  24. gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, 2);
  25. }
  26. rtWrapper._colorTextureArray = colorTexture;
  27. if (!depthStencilTexture) {
  28. depthStencilTexture = gl.createTexture();
  29. gl.bindTexture(gl.TEXTURE_2D_ARRAY, depthStencilTexture);
  30. gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.DEPTH24_STENCIL8, width, height, 2);
  31. }
  32. rtWrapper._depthStencilTextureArray = depthStencilTexture;
  33. internalTexture.isReady = true;
  34. rtWrapper.setTextures(internalTexture);
  35. rtWrapper._depthStencilTexture = internalTexture;
  36. return rtWrapper;
  37. };
  38. Engine.prototype.bindMultiviewFramebuffer = function (_multiviewTexture) {
  39. const multiviewTexture = _multiviewTexture;
  40. const gl = this._gl;
  41. const ext = this.getCaps().oculusMultiview || this.getCaps().multiview;
  42. this.bindFramebuffer(multiviewTexture, undefined, undefined, undefined, true);
  43. gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, multiviewTexture._framebuffer);
  44. if (multiviewTexture._colorTextureArray && multiviewTexture._depthStencilTextureArray) {
  45. if (this.getCaps().oculusMultiview) {
  46. ext.framebufferTextureMultisampleMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture._colorTextureArray, 0, multiviewTexture.samples, 0, 2);
  47. ext.framebufferTextureMultisampleMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, multiviewTexture._depthStencilTextureArray, 0, multiviewTexture.samples, 0, 2);
  48. }
  49. else {
  50. ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture._colorTextureArray, 0, 0, 2);
  51. ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, multiviewTexture._depthStencilTextureArray, 0, 0, 2);
  52. }
  53. }
  54. else {
  55. // eslint-disable-next-line no-throw-literal
  56. throw "Invalid multiview frame buffer";
  57. }
  58. };
  59. Engine.prototype.bindSpaceWarpFramebuffer = function (_spaceWarpTexture) {
  60. const spaceWarpTexture = _spaceWarpTexture;
  61. const gl = this._gl;
  62. const ext = this.getCaps().oculusMultiview || this.getCaps().multiview;
  63. this.bindFramebuffer(spaceWarpTexture, undefined, undefined, undefined, true);
  64. gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, spaceWarpTexture._framebuffer);
  65. if (spaceWarpTexture._colorTextureArray && spaceWarpTexture._depthStencilTextureArray) {
  66. ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, spaceWarpTexture._colorTextureArray, 0, 0, 2);
  67. ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, spaceWarpTexture._depthStencilTextureArray, 0, 0, 2);
  68. }
  69. else {
  70. throw new Error("Invalid Space Warp framebuffer");
  71. }
  72. };
  73. Camera.prototype._useMultiviewToSingleView = false;
  74. Camera.prototype._multiviewTexture = null;
  75. Camera.prototype._resizeOrCreateMultiviewTexture = function (width, height) {
  76. if (!this._multiviewTexture) {
  77. this._multiviewTexture = new MultiviewRenderTarget(this.getScene(), { width: width, height: height });
  78. }
  79. else if (this._multiviewTexture.getRenderWidth() != width || this._multiviewTexture.getRenderHeight() != height) {
  80. this._multiviewTexture.dispose();
  81. this._multiviewTexture = new MultiviewRenderTarget(this.getScene(), { width: width, height: height });
  82. }
  83. };
  84. function createMultiviewUbo(engine, name) {
  85. const ubo = new UniformBuffer(engine, undefined, true, name);
  86. ubo.addUniform("viewProjection", 16);
  87. ubo.addUniform("viewProjectionR", 16);
  88. ubo.addUniform("view", 16);
  89. ubo.addUniform("projection", 16);
  90. ubo.addUniform("vEyePosition", 4);
  91. return ubo;
  92. }
  93. const currentCreateSceneUniformBuffer = Scene.prototype.createSceneUniformBuffer;
  94. Scene.prototype._transformMatrixR = Matrix.Zero();
  95. Scene.prototype._multiviewSceneUbo = null;
  96. Scene.prototype._createMultiviewUbo = function () {
  97. this._multiviewSceneUbo = createMultiviewUbo(this.getEngine(), "scene_multiview");
  98. };
  99. Scene.prototype.createSceneUniformBuffer = function (name) {
  100. if (this._multiviewSceneUbo) {
  101. return createMultiviewUbo(this.getEngine(), name);
  102. }
  103. return currentCreateSceneUniformBuffer.bind(this)(name);
  104. };
  105. Scene.prototype._updateMultiviewUbo = function (viewR, projectionR) {
  106. if (viewR && projectionR) {
  107. viewR.multiplyToRef(projectionR, this._transformMatrixR);
  108. }
  109. if (viewR && projectionR) {
  110. viewR.multiplyToRef(projectionR, TmpVectors.Matrix[0]);
  111. Frustum.GetRightPlaneToRef(TmpVectors.Matrix[0], this._frustumPlanes[3]); // Replace right plane by second camera right plane
  112. }
  113. if (this._multiviewSceneUbo) {
  114. this._multiviewSceneUbo.updateMatrix("viewProjection", this.getTransformMatrix());
  115. this._multiviewSceneUbo.updateMatrix("viewProjectionR", this._transformMatrixR);
  116. this._multiviewSceneUbo.updateMatrix("view", this._viewMatrix);
  117. this._multiviewSceneUbo.updateMatrix("projection", this._projectionMatrix);
  118. }
  119. };
  120. Scene.prototype._renderMultiviewToSingleView = function (camera) {
  121. // Multiview is only able to be displayed directly for API's such as webXR
  122. // This displays a multiview image by rendering to the multiview image and then
  123. // copying the result into the sub cameras instead of rendering them and proceeding as normal from there
  124. // Render to a multiview texture
  125. camera._resizeOrCreateMultiviewTexture(camera._rigPostProcess && camera._rigPostProcess && camera._rigPostProcess.width > 0 ? camera._rigPostProcess.width : this.getEngine().getRenderWidth(true), camera._rigPostProcess && camera._rigPostProcess && camera._rigPostProcess.height > 0 ? camera._rigPostProcess.height : this.getEngine().getRenderHeight(true));
  126. if (!this._multiviewSceneUbo) {
  127. this._createMultiviewUbo();
  128. }
  129. camera.outputRenderTarget = camera._multiviewTexture;
  130. this._renderForCamera(camera);
  131. camera.outputRenderTarget = null;
  132. // Consume the multiview texture through a shader for each eye
  133. for (let index = 0; index < camera._rigCameras.length; index++) {
  134. const engine = this.getEngine();
  135. this._activeCamera = camera._rigCameras[index];
  136. engine.setViewport(this._activeCamera.viewport);
  137. if (this.postProcessManager) {
  138. this.postProcessManager._prepareFrame();
  139. this.postProcessManager._finalizeFrame(this._activeCamera.isIntermediate);
  140. }
  141. }
  142. };
  143. //# sourceMappingURL=engine.multiview.js.map