engine.renderTarget.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { InternalTexture, InternalTextureSource } from "../../Materials/Textures/internalTexture.js";
  2. import { Logger } from "../../Misc/logger.js";
  3. import { ThinEngine } from "../thinEngine.js";
  4. import { WebGLRenderTargetWrapper } from "../WebGL/webGLRenderTargetWrapper.js";
  5. ThinEngine.prototype._createHardwareRenderTargetWrapper = function (isMulti, isCube, size) {
  6. const rtWrapper = new WebGLRenderTargetWrapper(isMulti, isCube, size, this, this._gl);
  7. this._renderTargetWrapperCache.push(rtWrapper);
  8. return rtWrapper;
  9. };
  10. ThinEngine.prototype.createRenderTargetTexture = function (size, options) {
  11. const rtWrapper = this._createHardwareRenderTargetWrapper(false, false, size);
  12. let generateDepthBuffer = true;
  13. let generateStencilBuffer = false;
  14. let noColorAttachment = false;
  15. let colorAttachment = undefined;
  16. let samples = 1;
  17. let label = undefined;
  18. if (options !== undefined && typeof options === "object") {
  19. generateDepthBuffer = options.generateDepthBuffer ?? true;
  20. generateStencilBuffer = !!options.generateStencilBuffer;
  21. noColorAttachment = !!options.noColorAttachment;
  22. colorAttachment = options.colorAttachment;
  23. samples = options.samples ?? 1;
  24. label = options.label;
  25. }
  26. const texture = colorAttachment || (noColorAttachment ? null : this._createInternalTexture(size, options, true, InternalTextureSource.RenderTarget));
  27. const width = size.width || size;
  28. const height = size.height || size;
  29. const currentFrameBuffer = this._currentFramebuffer;
  30. const gl = this._gl;
  31. // Create the framebuffer
  32. const framebuffer = gl.createFramebuffer();
  33. this._bindUnboundFramebuffer(framebuffer);
  34. rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, width, height);
  35. // No need to rebind on every frame
  36. if (texture && !texture.is2DArray && !texture.is3D) {
  37. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._hardwareTexture.underlyingResource, 0);
  38. }
  39. this._bindUnboundFramebuffer(currentFrameBuffer);
  40. rtWrapper.label = label ?? "RenderTargetWrapper";
  41. rtWrapper._framebuffer = framebuffer;
  42. rtWrapper._generateDepthBuffer = generateDepthBuffer;
  43. rtWrapper._generateStencilBuffer = generateStencilBuffer;
  44. rtWrapper.setTextures(texture);
  45. this.updateRenderTargetTextureSampleCount(rtWrapper, samples);
  46. return rtWrapper;
  47. };
  48. ThinEngine.prototype._createDepthStencilTexture = function (size, options) {
  49. const gl = this._gl;
  50. const layers = size.layers || 0;
  51. const depth = size.depth || 0;
  52. let target = gl.TEXTURE_2D;
  53. if (layers !== 0) {
  54. target = gl.TEXTURE_2D_ARRAY;
  55. }
  56. else if (depth !== 0) {
  57. target = gl.TEXTURE_3D;
  58. }
  59. const internalTexture = new InternalTexture(this, InternalTextureSource.DepthStencil);
  60. internalTexture.label = options.label;
  61. if (!this._caps.depthTextureExtension) {
  62. Logger.Error("Depth texture is not supported by your browser or hardware.");
  63. return internalTexture;
  64. }
  65. const internalOptions = {
  66. bilinearFiltering: false,
  67. comparisonFunction: 0,
  68. generateStencil: false,
  69. ...options,
  70. };
  71. this._bindTextureDirectly(target, internalTexture, true);
  72. this._setupDepthStencilTexture(internalTexture, size, internalOptions.generateStencil, internalOptions.comparisonFunction === 0 ? false : internalOptions.bilinearFiltering, internalOptions.comparisonFunction, internalOptions.samples);
  73. if (internalOptions.depthTextureFormat !== undefined) {
  74. if (internalOptions.depthTextureFormat !== 15 &&
  75. internalOptions.depthTextureFormat !== 16 &&
  76. internalOptions.depthTextureFormat !== 17 &&
  77. internalOptions.depthTextureFormat !== 13 &&
  78. internalOptions.depthTextureFormat !== 14 &&
  79. internalOptions.depthTextureFormat !== 18) {
  80. Logger.Error("Depth texture format is not supported.");
  81. return internalTexture;
  82. }
  83. internalTexture.format = internalOptions.depthTextureFormat;
  84. }
  85. else {
  86. internalTexture.format = internalOptions.generateStencil ? 13 : 16;
  87. }
  88. const hasStencil = internalTexture.format === 17 ||
  89. internalTexture.format === 13 ||
  90. internalTexture.format === 18;
  91. let type = gl.UNSIGNED_INT;
  92. if (internalTexture.format === 15) {
  93. type = gl.UNSIGNED_SHORT;
  94. }
  95. else if (internalTexture.format === 17 || internalTexture.format === 13) {
  96. type = gl.UNSIGNED_INT_24_8;
  97. }
  98. else if (internalTexture.format === 14) {
  99. type = gl.FLOAT;
  100. }
  101. else if (internalTexture.format === 18) {
  102. type = gl.FLOAT_32_UNSIGNED_INT_24_8_REV;
  103. }
  104. const format = hasStencil ? gl.DEPTH_STENCIL : gl.DEPTH_COMPONENT;
  105. let internalFormat = format;
  106. if (this.webGLVersion > 1) {
  107. if (internalTexture.format === 15) {
  108. internalFormat = gl.DEPTH_COMPONENT16;
  109. }
  110. else if (internalTexture.format === 16) {
  111. internalFormat = gl.DEPTH_COMPONENT24;
  112. }
  113. else if (internalTexture.format === 17 || internalTexture.format === 13) {
  114. internalFormat = gl.DEPTH24_STENCIL8;
  115. }
  116. else if (internalTexture.format === 14) {
  117. internalFormat = gl.DEPTH_COMPONENT32F;
  118. }
  119. else if (internalTexture.format === 18) {
  120. internalFormat = gl.DEPTH32F_STENCIL8;
  121. }
  122. }
  123. if (internalTexture.is2DArray) {
  124. gl.texImage3D(target, 0, internalFormat, internalTexture.width, internalTexture.height, layers, 0, format, type, null);
  125. }
  126. else if (internalTexture.is3D) {
  127. gl.texImage3D(target, 0, internalFormat, internalTexture.width, internalTexture.height, depth, 0, format, type, null);
  128. }
  129. else {
  130. gl.texImage2D(target, 0, internalFormat, internalTexture.width, internalTexture.height, 0, format, type, null);
  131. }
  132. this._bindTextureDirectly(target, null);
  133. this._internalTexturesCache.push(internalTexture);
  134. return internalTexture;
  135. };
  136. ThinEngine.prototype.updateRenderTargetTextureSampleCount = function (rtWrapper, samples) {
  137. if (this.webGLVersion < 2 || !rtWrapper || !rtWrapper.texture) {
  138. return 1;
  139. }
  140. if (rtWrapper.samples === samples) {
  141. return samples;
  142. }
  143. const gl = this._gl;
  144. samples = Math.min(samples, this.getCaps().maxMSAASamples);
  145. // Dispose previous render buffers
  146. if (rtWrapper._depthStencilBuffer) {
  147. gl.deleteRenderbuffer(rtWrapper._depthStencilBuffer);
  148. rtWrapper._depthStencilBuffer = null;
  149. }
  150. if (rtWrapper._MSAAFramebuffer) {
  151. gl.deleteFramebuffer(rtWrapper._MSAAFramebuffer);
  152. rtWrapper._MSAAFramebuffer = null;
  153. }
  154. const hardwareTexture = rtWrapper.texture._hardwareTexture;
  155. hardwareTexture.releaseMSAARenderBuffers();
  156. if (samples > 1 && typeof gl.renderbufferStorageMultisample === "function") {
  157. const framebuffer = gl.createFramebuffer();
  158. if (!framebuffer) {
  159. throw new Error("Unable to create multi sampled framebuffer");
  160. }
  161. rtWrapper._MSAAFramebuffer = framebuffer;
  162. this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer);
  163. const colorRenderbuffer = this._createRenderBuffer(rtWrapper.texture.width, rtWrapper.texture.height, samples, -1 /* not used */, this._getRGBABufferInternalSizedFormat(rtWrapper.texture.type, rtWrapper.texture.format, rtWrapper.texture._useSRGBBuffer), gl.COLOR_ATTACHMENT0, false);
  164. if (!colorRenderbuffer) {
  165. throw new Error("Unable to create multi sampled framebuffer");
  166. }
  167. hardwareTexture.addMSAARenderBuffer(colorRenderbuffer);
  168. }
  169. else {
  170. this._bindUnboundFramebuffer(rtWrapper._framebuffer);
  171. }
  172. rtWrapper.texture.samples = samples;
  173. rtWrapper._samples = samples;
  174. rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(rtWrapper._generateStencilBuffer, rtWrapper._generateDepthBuffer, rtWrapper.texture.width, rtWrapper.texture.height, samples);
  175. this._bindUnboundFramebuffer(null);
  176. return samples;
  177. };
  178. //# sourceMappingURL=engine.renderTarget.js.map