UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

216 lines 20.7 kB
import { TgdPainterGroup } from "./group.js"; import { webglCreateFramebuffer, webglLookup, webglRenderbufferStorageMultisample, } from "./../utils/index.js"; export class TgdPainterFramebufferWithAntiAliasing extends TgdPainterGroup { constructor(context, options) { var _a; super(options.children); this.context = context; this.options = options; this.colorRenderbuffersMSAA = []; this._depthBufferMSAA = null; this._framebufferMSAA = null; /** * The framebuffer becomes dirty as soon as the width or height changes. */ this.dirty = true; this._width = 0; this._height = 0; this._framebuffer = null; this._depthBuffer = null; this._stencilBuffer = null; const { textureColor0, textureColor1, textureColor2, textureColor3 } = options; if (!(textureColor0 || textureColor1 || textureColor2 || textureColor3)) { console.error("[TgdPainterFramebuffer] You gave no color texture in the constructor: nothing will be rendered!", options); } this.textureColor0 = nameTexture(textureColor0, "textureColor0"); this.textureColor1 = nameTexture(textureColor1, "textureColor1"); this.textureColor2 = nameTexture(textureColor2, "textureColor2"); this.textureColor3 = nameTexture(textureColor3, "textureColor3"); this.textureDepth = options.textureDepth; this.onEnter = options.onEnter; this.onExit = options.onExit; const { gl } = this.context; this.drawBuffers = [ this.textureColor0 ? gl.COLOR_ATTACHMENT0 : gl.NONE, this.textureColor1 ? gl.COLOR_ATTACHMENT1 : gl.NONE, this.textureColor2 ? gl.COLOR_ATTACHMENT2 : gl.NONE, this.textureColor3 ? gl.COLOR_ATTACHMENT3 : gl.NONE, ]; this.samples = Math.min((_a = options.samples) !== null && _a !== void 0 ? _a : 4, gl.getParameter(gl.MAX_SAMPLES)); } get width() { return this._width; } set width(v) { if (this._width === v) return; this._width = v; this.dirty = true; } get height() { return this._height; } set height(v) { if (this._height === v) return; this._height = v; this.dirty = true; } updateTextureForColor(tgdTexture, attachment) { if (!tgdTexture) return; const { context, width, height } = this; const { gl } = context; tgdTexture.resize(width, height); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + attachment, gl.TEXTURE_2D, tgdTexture.glTexture, 0); } createDepthBufferMSAA(gl) { if (this.options.depthBuffer === false) return; const { width, height } = this; // Create a Depth Buffer, because the default // framebuffer has none. const depthBuffer = gl.createRenderbuffer(); if (!depthBuffer) throw new Error("Unable to create WebGLRenderBuffer for depth!"); this._depthBufferMSAA = depthBuffer; gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); webglRenderbufferStorageMultisample(gl, this.samples, gl.DEPTH_COMPONENT16, width, height); gl.bindRenderbuffer(gl.RENDERBUFFER, null); } createStencilBuffer(gl) { if (this.options.stencilBuffer !== false) { const { width, height } = this; const stencilBuffer = gl.createRenderbuffer(); if (!stencilBuffer) throw new Error("Unable to create WebGLRenderBuffer for stencil!"); this._stencilBuffer = stencilBuffer; gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer); gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilBuffer); } } createFramebufferMSAA() { const { context } = this; const { gl } = context; this.createRenderbuffersMSAA(); this.createDepthBufferMSAA(gl); this._framebufferMSAA = webglCreateFramebuffer(gl); gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebufferMSAA); this.colorRenderbuffersMSAA.map((renderbuffer, index) => { if (renderbuffer) { gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + index, gl.RENDERBUFFER, renderbuffer); } }); if (this._depthBufferMSAA) { gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthBufferMSAA); } gl.bindFramebuffer(gl.FRAMEBUFFER, null); } createFramebufferIfNeeded() { if (!this.dirty) return; const { context, width, height } = this; if (width < 1 || height < 1) return; this.delete(); const { gl } = context; this.createFramebufferMSAA(); this._framebuffer = webglCreateFramebuffer(gl); gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer); this.updateTextureForColor(this.textureColor0, 0); this.updateTextureForColor(this.textureColor1, 1); this.updateTextureForColor(this.textureColor2, 2); this.updateTextureForColor(this.textureColor3, 3); this.createStencilBuffer(gl); const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); if (status !== gl.FRAMEBUFFER_COMPLETE) { console.error(`Your Framebuffer is incomplete: ${webglLookup(status)}!`); } this.dirty = false; } blitFramebuffers() { const { context, width, height } = this; const { gl } = context; gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._framebufferMSAA); gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._framebuffer); this.colorRenderbuffersMSAA.map((_rd, index) => { gl.readBuffer(gl.COLOR_ATTACHMENT0 + index); const buffers = [gl.NONE, gl.NONE, gl.NONE, gl.NONE]; buffers[index] = gl.COLOR_ATTACHMENT0 + index; gl.drawBuffers(buffers); gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST); }); gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); } paint(time, delay) { const { context, options } = this; const { gl } = context; const { viewportMatchingScale = 1 } = options; this.width = Math.round(context.width * viewportMatchingScale); this.height = Math.round(context.height * viewportMatchingScale); this.createFramebufferIfNeeded(); gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebufferMSAA); gl.drawBuffers(this.drawBuffers); super.paint(time, delay); gl.bindFramebuffer(gl.FRAMEBUFFER, null); this.blitFramebuffers(); } delete() { const { context, _framebuffer, _depthBuffer, _stencilBuffer } = this; const { gl } = context; if (_framebuffer) { gl.deleteFramebuffer(_framebuffer); this._framebuffer = null; } if (_depthBuffer) { gl.deleteRenderbuffer(_depthBuffer); this._depthBuffer = null; } if (_stencilBuffer) { gl.deleteRenderbuffer(_stencilBuffer); this._stencilBuffer = null; } if (this._depthBufferMSAA) gl.deleteRenderbuffer(this._depthBufferMSAA); if (this._framebufferMSAA) gl.deleteFramebuffer(this._framebufferMSAA); this.deleteRenderbuffersMSAA(); } deleteRenderbuffersMSAA() { const { gl } = this.context; for (const colorRenderbuffer of this.colorRenderbuffersMSAA) { if (colorRenderbuffer) gl.deleteRenderbuffer(colorRenderbuffer); } } createRenderbuffersMSAA() { const { context, textureColor0, textureColor1, textureColor2, textureColor3, width, height, } = this; const { gl } = context; this.deleteRenderbuffersMSAA(); this.colorRenderbuffersMSAA = [ textureColor0, textureColor1, textureColor2, textureColor3, ].map(texture => { if (!texture) return; const colorRenderBuffer = gl.createRenderbuffer(); if (!colorRenderBuffer) throw new Error("Unable to create RenderBuffer!"); gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderBuffer); webglRenderbufferStorageMultisample(gl, this.samples, gl.RGBA8, width, height); gl.bindRenderbuffer(gl.RENDERBUFFER, null); return colorRenderBuffer; }); } } function nameTexture(texture, name) { if (texture) { texture.name += `/${name}`; } return texture; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhbWVidWZmZXItbXNhYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYWludGVyL2ZyYW1lYnVmZmVyLW1zYWEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUN6QyxPQUFPLEVBQ0gsc0JBQXNCLEVBQ3RCLFdBQVcsRUFDWCxtQ0FBbUMsR0FDdEMsTUFBTSxZQUFZLENBQUE7QUE4Q25CLE1BQU0sT0FBTyxxQ0FBc0MsU0FBUSxlQUFlO0lBdUJ0RSxZQUNxQixPQUFtQixFQUNuQixPQUE4RDs7UUFFL0UsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUhOLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFDbkIsWUFBTyxHQUFQLE9BQU8sQ0FBdUQ7UUFqQjNFLDJCQUFzQixHQUFzQyxFQUFFLENBQUE7UUFDOUQscUJBQWdCLEdBQTZCLElBQUksQ0FBQTtRQUNqRCxxQkFBZ0IsR0FBNEIsSUFBSSxDQUFBO1FBRXhEOztXQUVHO1FBQ0ssVUFBSyxHQUFHLElBQUksQ0FBQTtRQUNaLFdBQU0sR0FBRyxDQUFDLENBQUE7UUFDVixZQUFPLEdBQUcsQ0FBQyxDQUFBO1FBQ1gsaUJBQVksR0FBNEIsSUFBSSxDQUFBO1FBQzVDLGlCQUFZLEdBQTZCLElBQUksQ0FBQTtRQUM3QyxtQkFBYyxHQUE2QixJQUFJLENBQUE7UUFRbkQsTUFBTSxFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLGFBQWEsRUFBRSxHQUNoRSxPQUFPLENBQUE7UUFDWCxJQUNJLENBQUMsQ0FBQyxhQUFhLElBQUksYUFBYSxJQUFJLGFBQWEsSUFBSSxhQUFhLENBQUMsRUFDckUsQ0FBQztZQUNDLE9BQU8sQ0FBQyxLQUFLLENBQ1QsaUdBQWlHLEVBQ2pHLE9BQU8sQ0FDVixDQUFBO1FBQ0wsQ0FBQztRQUNELElBQUksQ0FBQyxhQUFhLEdBQUcsV0FBVyxDQUFDLGFB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