@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
216 lines • 20.7 kB
JavaScript
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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