123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- import { InternalTexture, InternalTextureSource } from '../../Materials/Textures/internalTexture';
- import { IMultiRenderTargetOptions } from '../../Materials/Textures/multiRenderTarget';
- import { Logger } from '../../Misc/logger';
- import { Nullable } from '../../types';
- import { Constants } from '../constants';
- import { ThinEngine } from '../thinEngine';
- import { IColor4Like } from '../../Maths/math.like';
- 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 count number of color textures
- * @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 http://doc.babylonjs.com/features/webgl2#multiple-render-target
- * @param size defines the size of the texture
- * @param options defines the creation options
- * @returns the cube texture as an InternalTexture
- */
- createMultipleRenderTarget(size: any, options: IMultiRenderTargetOptions): InternalTexture[];
- /**
- * Update the sample count for a given multiple render target texture
- * @see http://doc.babylonjs.com/features/webgl2#multisample-render-targets
- * @param count number of color textures
- * @param textures defines the textures to update
- * @param samples defines the sample count to set
- * @returns the effective sample count (could be 0 if multisample render targets are not supported)
- */
- updateMultipleRenderTargetTextureSampleCount(textures: Nullable<InternalTexture[]>, samples: number): number;
- /**
- * Clears attachments
- * @param texture texture to clear
- * @param attachments attachments to clear
- * @param color Clear color
- */
- clearColorAttachments(texture: InternalTexture, attachments: number[], color?: IColor4Like) : void;
- /**
- * Select a subsets of attachments to draw to.
- * @param attachments gl attachments
- */
- renderToAttachments(attachments: any[]) : void;
- }
- }
- ThinEngine.prototype.renderToAttachments = function(attachments: any[]): void {
- const gl = this._gl;
- gl.drawBuffers(attachments);
- };
- ThinEngine.prototype.clearColorAttachments = function(texture: InternalTexture, attachments: number[], color?: IColor4Like): void {
- // Default clear everything to transparent black
- const gl = this._gl;
- // We don't clear the first attachments which is cleared with the user clear color
- gl.drawBuffers(attachments);
- if (color) {
- gl.clearColor(color.r, color.g, color.b, color.a);
- } else {
- gl.clearColor(0, 0, 0, 0);
- }
- gl.clear(gl.COLOR_BUFFER_BIT);
- // Restore default attachments
- gl.drawBuffers(texture._attachments!);
- };
- 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;
- if (textures[0]._MSAAFramebuffer) {
- gl.bindFramebuffer(gl.READ_FRAMEBUFFER, textures[0]._MSAAFramebuffer);
- gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, textures[0]._framebuffer);
- var attachments = textures[0]._attachments!;
- var count = attachments.length;
- for (var i = 0; i < count; i++) {
- var texture = textures[i];
- for (var j = 0; j < attachments.length; 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 < attachments.length; i++) {
- attachments[i] = (<any>gl)[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
- }
- gl.drawBuffers(attachments);
- }
- for (var i = 0; i < textures[0]._attachments!.length; 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): 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._webGLTexture);
- 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._webGLTexture, 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._webGLTexture);
- 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._webGLTexture,
- 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);
- }
- gl.drawBuffers(attachments);
- this._bindUnboundFramebuffer(null);
- this.resetTextureCache();
- return textures;
- };
- ThinEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function(textures: Nullable<InternalTexture[]>, samples: number): 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);
- }
- gl.drawBuffers(attachments);
- } else {
- this._bindUnboundFramebuffer(textures[0]._framebuffer);
- }
- this._bindUnboundFramebuffer(null);
- return samples;
- };
|