cables_dev/cables/src/core/cgl/cgl_framebuffer2.js
// * see framebuffer1
import { Logger } from "cables-shared-client";
import { Texture } from "./cgl_texture.js";
const Framebuffer2 = function (cgl, w, h, options)
{
this._log = new Logger("cgl_framebuffer2");
if (cgl.glVersion == 1) return this._log.error("framebuffer2 used on webgl1");
this.Framebuffer2DrawTargetsDefault = null;
this.Framebuffer2BlittingFramebuffer = null;
this.Framebuffer2FinalFramebuffer = null;
this._cgl = cgl;
this._cgl.printError("before framebuffer2 constructor");
this._width = 0;
this._height = 0;
this.valid = true;
this._depthRenderbuffer = null;
this._frameBuffer = null;
this._textureFrameBuffer = null;
this._colorRenderbuffers = [];
this._drawTargetArray = [];
this._disposed = false;
if (!this.Framebuffer2BlittingFramebuffer) this.Framebuffer2BlittingFramebuffer = cgl.gl.createFramebuffer();
if (!this.Framebuffer2FinalFramebuffer) this.Framebuffer2FinalFramebuffer = cgl.gl.createFramebuffer();
if (!this.Framebuffer2DrawTargetsDefault) this.Framebuffer2DrawTargetsDefault = [cgl.gl.COLOR_ATTACHMENT0];
this._options = options || {
"isFloatingPointTexture": false,
};
// this._cgl.printError("fb2 before");
this.name = this._options.name || "unknown";
this._cgl.profileData.addHeavyEvent("framebuffer create", this.name);
if (!this._options.hasOwnProperty("numRenderBuffers")) this._options.numRenderBuffers = 1;
if (!this._options.hasOwnProperty("depth")) this._options.depth = true;
if (!this._options.hasOwnProperty("clear")) this._options.clear = true;
if (!this._options.hasOwnProperty("multisampling"))
{
this._options.multisampling = false;
this._options.multisamplingSamples = 0;
}
if (this._options.multisamplingSamples)
{
if (this._cgl.glSlowRenderer) this._options.multisamplingSamples = 0;
if (!this._cgl.gl.MAX_SAMPLES) this._options.multisamplingSamples = 0;
else this._options.multisamplingSamples = Math.min(this._cgl.maxSamples, this._options.multisamplingSamples);
}
if (!this._options.hasOwnProperty("filter")) this._options.filter = Texture.FILTER_LINEAR;
if (!this._options.hasOwnProperty("wrap")) this._options.wrap = Texture.WRAP_REPEAT;
this._numRenderBuffers = this._options.numRenderBuffers;
this._colorTextures = [];
this.clearColors = [];
for (let i = 0; i < this._numRenderBuffers; i++) this.clearColors.push([0, 0, 0, 1]);
if (!options.pixelFormat)
{
if (options.isFloatingPointTexture) this._options.pixelFormat = Texture.PFORMATSTR_RGBA32F;
else this._options.pixelFormat = Texture.PFORMATSTR_RGBA8UB;
}
for (let i = 0; i < this._numRenderBuffers; i++)
{
this._colorTextures[i] = new Texture(cgl, {
"name": "fb2 " + this.name + " " + i,
"isFloatingPointTexture": this._options.isFloatingPointTexture,
"anisotropic": this._options.anisotropic || 0,
"pixelFormat": this._options.pixelFormat,
"filter": this._options.filter,
"wrap": this._options.wrap,
});
}
let fil = Texture.FILTER_NEAREST;
if (this._options.shadowMap) fil = Texture.FILTER_LINEAR;
const defaultTexSize = 512;
if (this._options.depth)
{
this._textureDepth = new Texture(cgl,
{
"name": "fb2 depth " + this.name,
"isDepthTexture": true,
"filter": fil,
"shadowMap": this._options.shadowMap || false,
"width": w || defaultTexSize,
"height": h || defaultTexSize,
});
}
if (cgl.aborted) return;
this.setSize(w || defaultTexSize, h || defaultTexSize);
this._cgl.printError("framebuffer2 constructor");
};
Framebuffer2.prototype.getWidth = function ()
{
return this._width;
};
Framebuffer2.prototype.getHeight = function ()
{
return this._height;
};
Framebuffer2.prototype.getGlFrameBuffer = function ()
{
return this._frameBuffer;
};
Framebuffer2.prototype.getDepthRenderBuffer = function ()
{
return this._depthRenderbuffer;
};
Framebuffer2.prototype.getTextureColor = function ()
{
return this._colorTextures[0];
};
Framebuffer2.prototype.getTextureColorNum = function (i)
{
return this._colorTextures[i];
};
Framebuffer2.prototype.getTextureDepth = function ()
{
return this._textureDepth;
};
Framebuffer2.prototype.setFilter = function (f)
{
for (let i = 0; i < this._numRenderBuffers; i++)
{
this._colorTextures[i].filter = f;
this._colorTextures[i].setSize(this._width, this._height);
}
};
Framebuffer2.prototype.delete = Framebuffer2.prototype.dispose = function ()
{
this._disposed = true;
let i = 0;
for (i = 0; i < this._numRenderBuffers; i++) this._colorTextures[i].delete();
// this._texture.delete();
if (this._textureDepth) this._textureDepth.delete();
for (i = 0; i < this._numRenderBuffers; i++) this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffers[i]);
this._cgl.gl.deleteRenderbuffer(this._depthRenderbuffer);
this._cgl.gl.deleteFramebuffer(this._frameBuffer);
this._cgl.gl.deleteFramebuffer(this._textureFrameBuffer);
};
Framebuffer2.prototype.setSize = function (w, h)
{
if (this._disposed) return this._log.warn("disposed framebuffer setsize...");
this._cgl.profileData.addHeavyEvent("framebuffer resize", this.name);
let i = 0;
this._width = this._cgl.checkTextureSize(w);
this._height = this._cgl.checkTextureSize(h);
this._cgl.profileData.profileFrameBuffercreate++;
if (this._frameBuffer)
{
for (i = 0; i < this._numRenderBuffers; i++) this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffers[i]);
// this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffer);
this._cgl.gl.deleteRenderbuffer(this._depthRenderbuffer);
this._cgl.gl.deleteFramebuffer(this._frameBuffer);
this._cgl.gl.deleteFramebuffer(this._textureFrameBuffer);
}
this._frameBuffer = this._cgl.gl.createFramebuffer();
this._textureFrameBuffer = this._cgl.gl.createFramebuffer();
const depth = this._options.depth;
for (i = 0; i < this._numRenderBuffers; i++)
{
this._colorTextures[i].setSize(this._width, this._height);
}
for (i = 0; i < this._numRenderBuffers; i++)
{
const renderBuffer = this._cgl.gl.createRenderbuffer();
// color renderbuffer
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, renderBuffer);
const info = Texture.setUpGlPixelFormat(this._cgl, this._options.pixelFormat);
let internFormat = info.glInternalFormat;
// if (this._options.isFloatingPointTexture)
// {
if (CGL.Texture.isPixelFormatHalfFloat(info.pixelFormat))
{
if (!this._cgl.enableExtension("OES_texture_float_linear"))
{
this._options.filter = Texture.FILTER_NEAREST;
this.setFilter(this._options.filter);
}
}
else if (CGL.Texture.isPixelFormatFloat(info.pixelFormat))
{
if (!this._cgl.enableExtension("OES_texture_float_linear"))
{
this._log.warn("no linear pixelformat,using nearest");
this._options.filter = Texture.FILTER_NEAREST;
this.setFilter(this._options.filter);
}
}
// else if (info.pixelFormat == Texture.PFORMATSTR_RGBA32F || info.pixelFormat == Texture.PFORMATSTR_R11FG11FB10F
// else if (info.pixelFormat == Texture.PFORMATSTR_RGBA32F || info.pixelFormat == Texture.PFORMATSTR_R11FG11FB10F
// else if (info.pixelFormat == Texture.PFORMATSTR_RG16F)
// {
// const extcb = this._cgl.enableExtension("EXT_color_buffer_float");
// if (!this._cgl.enableExtension("OES_texture_float_linear"))
// {
// console.log("no linear pixelformat,switching to nearest");
// this._options.filter = Texture.FILTER_NEAREST;
// this.setFilter(this._options.filter);
// }
// }
// }
if (this._options.multisampling && this._options.multisamplingSamples)
{
this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, internFormat, this._width, this._height);
}
else
{
this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, internFormat, this._width, this._height);
}
this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.RENDERBUFFER, renderBuffer);
this._colorRenderbuffers[i] = renderBuffer;
}
// this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._textureFrameBuffer);
for (i = 0; i < this._numRenderBuffers; i++)
{
this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
}
if (this._options.depth)
{
this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.TEXTURE_2D, this._textureDepth.tex, 0);
}
// depth renderbuffer
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
let depthType = this._cgl.gl.DEPTH_COMPONENT32F;
if (this._cgl.glSlowRenderer) depthType = this._cgl.gl.DEPTH_COMPONENT16;
if (depth)
{
this._textureDepth.setSize(this._width, this._height);
this._depthRenderbuffer = this._cgl.gl.createRenderbuffer();
this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
if (this._options.isFloatingPointTexture)
{
if (this._options.multisampling) this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, depthType, this._width, this._height);
else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, depthType, this._width, this._height);
}
else if (this._options.multisampling)
{
this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, depthType, this._width, this._height);
// this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,depthType, this._width, this._height);
}
else
{
this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, depthType, this._width, this._height);
}
this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
}
// this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
// this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._textureFrameBuffer);
this._drawTargetArray.length = 0;
for (i = 0; i < this._numRenderBuffers; i++) this._drawTargetArray.push(this._cgl.gl.COLOR_ATTACHMENT0 + i);
// this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
if (!this._cgl.gl.isFramebuffer(this._textureFrameBuffer)) this._log.warn("invalid framebuffer");// throw new Error("Invalid framebuffer");
const status = this._cgl.gl.checkFramebufferStatus(this._cgl.gl.FRAMEBUFFER);
if (status != this._cgl.gl.FRAMEBUFFER_COMPLETE)
{
this._log.error("framebuffer incomplete: " + this.name, this);
this._log.log("options", this._options);
this._log.log("options pixelformat", this._options.pixelFormat);
switch (status)
{
case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
this._log.warn("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...", this);
throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
this._log.warn("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
this._log.warn("FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
case this._cgl.gl.FRAMEBUFFER_UNSUPPORTED:
this._log.warn("FRAMEBUFFER_UNSUPPORTED");
throw new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");
default:
this.valid = false;
this._log.error("incomplete framebuffer", status, this._frameBuffer);
this._cgl.printError();
this._frameBuffer = null;
// debugger;
throw new Error("Incomplete framebuffer: " + status);
// throw("Incomplete framebuffer: " + status);
}
}
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);
// this._cgl.printError("fb setsize");
};
Framebuffer2.prototype.renderStart = function ()
{
if (this._disposed) return this._log.warn("disposed framebuffer renderStart...");
this._cgl.checkFrameStarted("fb2 renderstart");
this._cgl.pushModelMatrix(); // needed ??
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
this._cgl.pushGlFrameBuffer(this._frameBuffer);
this._cgl.pushFrameBuffer(this);
this._cgl.pushPMatrix();
this._cgl.pushViewPort(0, 0, this._width, this._height);
this._cgl.gl.drawBuffers(this._drawTargetArray);
if (this._options.clear)
{
this._cgl.gl.clearColor(0, 0, 0, 0);
this._cgl.gl.clear(this._cgl.gl.COLOR_BUFFER_BIT | this._cgl.gl.DEPTH_BUFFER_BIT);
}
};
Framebuffer2.prototype.clear = function ()
{
if (this._numRenderBuffers <= 1)
{
this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this._frameBuffer);
this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
}
else this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
this._cgl.gl.drawBuffers(this._drawTargetArray);
for (let i = 0; i < this._numRenderBuffers; i++)
{
this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, i, this.clearColors[i]);
}
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
};
Framebuffer2.prototype.renderEnd = function ()
{
if (this._disposed) return this._log.warn("disposed framebuffer renderEnd...");
this._cgl.popPMatrix();
this._cgl.profileData.profileFramebuffer++;
if (this._numRenderBuffers <= 1)
{
this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this._frameBuffer);
this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
this._cgl.gl.blitFramebuffer(0, 0, this._width, this._height, 0, 0, this._width, this._height, this._cgl.gl.COLOR_BUFFER_BIT | this._cgl.gl.DEPTH_BUFFER_BIT, this._cgl.gl.NEAREST);
}
else
{
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.TEXTURE_2D, this._textureDepth.tex, 0);
for (let i = 0; i < this._numRenderBuffers; i++)
{
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.RENDERBUFFER, this._colorRenderbuffers[i]);
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
// this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, i, [0.0, 0.0, 0.0, 1.0]);
let flags = this._cgl.gl.COLOR_BUFFER_BIT;
if (i == 0) flags |= this._cgl.gl.DEPTH_BUFFER_BIT;
this._cgl.gl.blitFramebuffer(0, 0, this._width, this._height, 0, 0, this._width, this._height, flags, this._cgl.gl.NEAREST);
}
}
this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.popGlFrameBuffer());
this._cgl.popFrameBuffer();
this._cgl.popModelMatrix();
// this._cgl.resetViewPort();
this._cgl.popViewPort();
if (this._colorTextures[0].filter == Texture.FILTER_MIPMAP)
{
for (let i = 0; i < this._numRenderBuffers; i++)
{
this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex);
this._colorTextures[i].updateMipMap();
this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
}
}
};
export { Framebuffer2 };
/// ///////