123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- import { InternalTexture, InternalTextureSource } from '../../Materials/Textures/internalTexture';
- import { IMultiRenderTargetOptions } from '../../Materials/Textures/multiRenderTarget';
- import { IColor4Like } from "../../Maths/math.like";
- import { Logger } from '../../Misc/logger';
- import { Nullable } from '../../types';
- import { Constants } from '../constants';
- import { ThinEngine } from '../thinEngine';
- declare module "../../Engines/thinEngine" {
- export interface ThinEngine {
- /**
- * Unbind a list of render target textures from the webGL context
- * This is used only when drawBuffer extension or webGL2 are active
- * @param textures defines the render target textures to unbind
- * @param disableGenerateMipMaps defines a boolean indicating that mipmaps must not be generated
- * @param onBeforeUnbind defines a function which will be called before the effective unbind
- */
- unBindMultiColorAttachmentFramebuffer(textures: InternalTexture[], disableGenerateMipMaps: boolean, onBeforeUnbind?: () => void): void;
- /**
- * Create a multi render target texture
- * @see https://doc.babylonjs.com/features/webgl2#multiple-render-target
- * @param size defines the size of the texture
- * @param options defines the creation options
- * @param noDrawBuffers if set to true, the engine won't make an initializing call of drawBuffers
- * @returns the cube texture as an InternalTexture
- */
- createMultipleRenderTarget(size: any, options: IMultiRenderTargetOptions, noDrawBuffers?: boolean): InternalTexture[];
- /**
- * Update the sample count for a given multiple render target texture
- * @see https://doc.babylonjs.com/features/webgl2#multisample-render-targets
- * @param textures defines the textures to update
- * @param samples defines the sample count to set
- * @param noDrawBuffers if set to true, the engine won't make an initializing call of drawBuffers
- * @returns the effective sample count (could be 0 if multisample render targets are not supported)
- */
- updateMultipleRenderTargetTextureSampleCount(textures: Nullable<InternalTexture[]>, samples: number, noDrawBuffers?: boolean): number;
- /**
- * Select a subsets of attachments to draw to.
- * @param attachments gl attachments
- */
- bindAttachments(attachments: number[]) : void;
- /**
- * Creates a layout object to draw/clear on specific textures in a MRT
- * @param textureStatus textureStatus[i] indicates if the i-th is active
- * @returns A layout to be fed to the engine, calling `bindAttachments`.
- */
- buildTextureLayout(textureStatus: boolean[]) : number[];
- /**
- * Restores the webgl state to only draw on the main color attachment
- * when the frame buffer associated is the canvas frame buffer
- */
- restoreSingleAttachment() : void;
-
- /**
- * Restores the webgl state to only draw on the main color attachment
- * when the frame buffer associated is not the canvas frame buffer
- */
- restoreSingleAttachmentForRenderTarget() : void;
- /**
- * Clears a list of attachments
- * @param attachments list of the attachments
- * @param colorMain clear color for the main attachment (the first one)
- * @param colorOthers clear color for the other attachments
- * @param clearDepth true to clear the depth buffer. Used only for the first attachment
- * @param clearStencil true to clear the stencil buffer. Used only for the first attachment
- */
- clearAttachments(attachments: number[], colorMain: Nullable<IColor4Like>, colorOthers: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean): void;
- }
- }
- ThinEngine.prototype.restoreSingleAttachment = function(): void {
- const gl = this._gl;
- this.bindAttachments([gl.BACK]);
- };
- ThinEngine.prototype.restoreSingleAttachmentForRenderTarget = function(): void {
- const gl = this._gl;
- this.bindAttachments([gl.COLOR_ATTACHMENT0]);
- };
- ThinEngine.prototype.buildTextureLayout = function(textureStatus: boolean[]): number[] {
- const gl = this._gl;
- const result = [];
- for (let i = 0; i < textureStatus.length; i++) {
- if (textureStatus[i]) {
- result.push((<any>gl)["COLOR_ATTACHMENT" + i]);
- } else {
- result.push(gl.NONE);
- }
- }
- return result;
- };
- ThinEngine.prototype.bindAttachments = function(attachments: number[]): void {
- const gl = this._gl;
- gl.drawBuffers(attachments);
- };
- ThinEngine.prototype.clearAttachments = function(attachments: number[], colorMain: Nullable<IColor4Like>, colorOthers: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean): void {
- if (attachments.length === 0) {
- return;
- }
- const gl = this._gl;
- gl.drawBuffers([attachments[0]]);
- this.clear(colorMain, colorMain !== null, clearDepth, clearStencil);
- const saveVal = attachments[0];
- attachments[0] = gl.NONE;
- gl.drawBuffers(attachments);
- this.clear(colorOthers, colorOthers !== null, false, false);
- attachments[0] = saveVal;
- };
- ThinEngine.prototype.unBindMultiColorAttachmentFramebuffer = function(textures: InternalTexture[], disableGenerateMipMaps: boolean = false, onBeforeUnbind?: () => void): void {
- this._currentRenderTarget = null;
- // If MSAA, we need to bitblt back to main texture
- var gl = this._gl;
- var attachments = textures[0]._attachments!;
- var count = attachments.length;
- if (textures[0]._MSAAFramebuffer) {
- gl.bindFramebuffer(gl.READ_FRAMEBUFFER, textures[0]._MSAAFramebuffer);
- gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, textures[0]._framebuffer);
- for (var i = 0; i < count; i++) {
- var texture = textures[i];
- for (var j = 0; j < count; j++) {
- attachments[j] = gl.NONE;
- }
- attachments[i] = (<any>gl)[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
- gl.readBuffer(attachments[i]);
- gl.drawBuffers(attachments);
- gl.blitFramebuffer(0, 0, texture.width, texture.height,
- 0, 0, texture.width, texture.height,
- gl.COLOR_BUFFER_BIT, gl.NEAREST);
- }
- for (var i = 0; i < count; i++) {
- attachments[i] = (<any>gl)[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
- }
- gl.drawBuffers(attachments);
- }
- for (var i = 0; i < count; i++) {
- var texture = textures[i];
- if (texture.generateMipMaps && !disableGenerateMipMaps && !texture.isCube) {
- this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
- gl.generateMipmap(gl.TEXTURE_2D);
- this._bindTextureDirectly(gl.TEXTURE_2D, null);
- }
- }
- if (onBeforeUnbind) {
- if (textures[0]._MSAAFramebuffer) {
- // Bind the correct framebuffer
- this._bindUnboundFramebuffer(textures[0]._framebuffer);
- }
- onBeforeUnbind();
- }
- this._bindUnboundFramebuffer(null);
- };
- ThinEngine.prototype.createMultipleRenderTarget = function(size: any, options: IMultiRenderTargetOptions, noDrawBuffers?: boolean): InternalTexture[] {
- var generateMipMaps = false;
- var generateDepthBuffer = true;
- var generateStencilBuffer = false;
- var generateDepthTexture = false;
- var textureCount = 1;
- var defaultType = Constants.TEXTURETYPE_UNSIGNED_INT;
- var defaultSamplingMode = Constants.TEXTURE_TRILINEAR_SAMPLINGMODE;
- var types = new Array<number>();
- var samplingModes = new Array<number>();
- if (options !== undefined) {
- generateMipMaps = options.generateMipMaps === undefined ? false : options.generateMipMaps;
- generateDepthBuffer = options.generateDepthBuffer === undefined ? true : options.generateDepthBuffer;
- generateStencilBuffer = options.generateStencilBuffer === undefined ? false : options.generateStencilBuffer;
- generateDepthTexture = options.generateDepthTexture === undefined ? false : options.generateDepthTexture;
- textureCount = options.textureCount || 1;
- if (options.types) {
- types = options.types;
- }
- if (options.samplingModes) {
- samplingModes = options.samplingModes;
- }
- }
- var gl = this._gl;
- // Create the framebuffer
- var framebuffer = gl.createFramebuffer();
- this._bindUnboundFramebuffer(framebuffer);
- var width = size.width || size;
- var height = size.height || size;
- var textures = [];
- var attachments = [];
- var depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, width, height);
- for (var i = 0; i < textureCount; i++) {
- var samplingMode = samplingModes[i] || defaultSamplingMode;
- var type = types[i] || defaultType;
- if (type === Constants.TEXTURETYPE_FLOAT && !this._caps.textureFloatLinearFiltering) {
- // if floating point linear (gl.FLOAT) then force to NEAREST_SAMPLINGMODE
- samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
- }
- else if (type === Constants.TEXTURETYPE_HALF_FLOAT && !this._caps.textureHalfFloatLinearFiltering) {
- // if floating point linear (HALF_FLOAT) then force to NEAREST_SAMPLINGMODE
- samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
- }
- var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
- if (type === Constants.TEXTURETYPE_FLOAT && !this._caps.textureFloat) {
- type = Constants.TEXTURETYPE_UNSIGNED_INT;
- Logger.Warn("Float textures are not supported. Render target forced to TEXTURETYPE_UNSIGNED_BYTE type");
- }
- var texture = new InternalTexture(this, InternalTextureSource.MultiRenderTarget);
- var attachment = (<any>gl)[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
- textures.push(texture);
- attachments.push(attachment);
- gl.activeTexture((<any>gl)["TEXTURE" + i]);
- gl.bindTexture(gl.TEXTURE_2D, texture._hardwareTexture!.underlyingResource);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filters.mag);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filters.min);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), width, height, 0, gl.RGBA, this._getWebGLTextureType(type), null);
- gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, attachment, gl.TEXTURE_2D, texture._hardwareTexture!.underlyingResource, 0);
- if (generateMipMaps) {
- this._gl.generateMipmap(this._gl.TEXTURE_2D);
- }
- // Unbind
- this._bindTextureDirectly(gl.TEXTURE_2D, null);
- texture._framebuffer = framebuffer;
- texture._depthStencilBuffer = depthStencilBuffer;
- texture.baseWidth = width;
- texture.baseHeight = height;
- texture.width = width;
- texture.height = height;
- texture.isReady = true;
- texture.samples = 1;
- texture.generateMipMaps = generateMipMaps;
- texture.samplingMode = samplingMode;
- texture.type = type;
- texture._generateDepthBuffer = generateDepthBuffer;
- texture._generateStencilBuffer = generateStencilBuffer;
- texture._attachments = attachments;
- texture._textureArray = textures;
- this._internalTexturesCache.push(texture);
- }
- if (generateDepthTexture && this._caps.depthTextureExtension) {
- // Depth texture
- var depthTexture = new InternalTexture(this, InternalTextureSource.MultiRenderTarget);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, depthTexture._hardwareTexture!.underlyingResource);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.texImage2D(
- gl.TEXTURE_2D,
- 0,
- this.webGLVersion < 2 ? gl.DEPTH_COMPONENT : gl.DEPTH_COMPONENT16,
- width,
- height,
- 0,
- gl.DEPTH_COMPONENT,
- gl.UNSIGNED_SHORT,
- null
- );
- gl.framebufferTexture2D(
- gl.FRAMEBUFFER,
- gl.DEPTH_ATTACHMENT,
- gl.TEXTURE_2D,
- depthTexture._hardwareTexture!.underlyingResource,
- 0
- );
- depthTexture._framebuffer = framebuffer;
- depthTexture.baseWidth = width;
- depthTexture.baseHeight = height;
- depthTexture.width = width;
- depthTexture.height = height;
- depthTexture.isReady = true;
- depthTexture.samples = 1;
- depthTexture.generateMipMaps = generateMipMaps;
- depthTexture.samplingMode = gl.NEAREST;
- depthTexture._generateDepthBuffer = generateDepthBuffer;
- depthTexture._generateStencilBuffer = generateStencilBuffer;
- textures.push(depthTexture);
- this._internalTexturesCache.push(depthTexture);
- }
- if (!noDrawBuffers) {
- gl.drawBuffers(attachments);
- }
- this._bindUnboundFramebuffer(null);
- this.resetTextureCache();
- return textures;
- };
- ThinEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function(textures: Nullable<InternalTexture[]>, samples: number, noDrawBuffers?: boolean): number {
- if (this.webGLVersion < 2 || !textures) {
- return 1;
- }
- if (textures[0].samples === samples) {
- return samples;
- }
- var count = textures[0]._attachments!.length;
- if (count === 0) {
- return 1;
- }
- var gl = this._gl;
- samples = Math.min(samples, this.getCaps().maxMSAASamples);
- // Dispose previous render buffers
- if (textures[0]._depthStencilBuffer) {
- gl.deleteRenderbuffer(textures[0]._depthStencilBuffer);
- textures[0]._depthStencilBuffer = null;
- }
- if (textures[0]._MSAAFramebuffer) {
- gl.deleteFramebuffer(textures[0]._MSAAFramebuffer);
- textures[0]._MSAAFramebuffer = null;
- }
- for (var i = 0; i < count; i++) {
- if (textures[i]._MSAARenderBuffer) {
- gl.deleteRenderbuffer(textures[i]._MSAARenderBuffer);
- textures[i]._MSAARenderBuffer = null;
- }
- }
- if (samples > 1 && gl.renderbufferStorageMultisample) {
- let framebuffer = gl.createFramebuffer();
- if (!framebuffer) {
- throw new Error("Unable to create multi sampled framebuffer");
- }
- this._bindUnboundFramebuffer(framebuffer);
- let depthStencilBuffer = this._setupFramebufferDepthAttachments(textures[0]._generateStencilBuffer, textures[0]._generateDepthBuffer, textures[0].width, textures[0].height, samples);
- var attachments = [];
- for (var i = 0; i < count; i++) {
- var texture = textures[i];
- var attachment = (<any>gl)[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
- var colorRenderbuffer = gl.createRenderbuffer();
- if (!colorRenderbuffer) {
- throw new Error("Unable to create multi sampled framebuffer");
- }
- gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderbuffer);
- gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, this._getRGBAMultiSampleBufferFormat(texture.type), texture.width, texture.height);
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, colorRenderbuffer);
- texture._MSAAFramebuffer = framebuffer;
- texture._MSAARenderBuffer = colorRenderbuffer;
- texture.samples = samples;
- texture._depthStencilBuffer = depthStencilBuffer;
- gl.bindRenderbuffer(gl.RENDERBUFFER, null);
- attachments.push(attachment);
- }
- if (!noDrawBuffers) {
- gl.drawBuffers(attachments);
- }
- } else {
- this._bindUnboundFramebuffer(textures[0]._framebuffer);
- }
- this._bindUnboundFramebuffer(null);
- return samples;
- };
|