@awayjs/stage
Version:
Stage for AwayJS
145 lines (111 loc) • 3.84 kB
text/typescript
import { Point, Rectangle } from '@awayjs/core';
import { RenderTargetWebGL } from './RenderTargetWebGL';
export class RenderTargetWebGLMSAA extends RenderTargetWebGL {
public isMsaaTarget = true;
protected _color: WebGLRenderbuffer;
/*internal*/ _drawTarget: RenderTargetWebGL;
public get readBuffer() {
return this._drawTarget.readBuffer;
}
public get isValid() {
return this._framebuffer && this._drawTarget && this._drawTarget.isValid;
}
protected init() {
const gl = <WebGL2RenderingContext> this._context._gl;
const tex = this._context._texContext;
this._context.stats.counter.renderTarget++;
this._framebuffer = gl.createFramebuffer();
this._depthStencil = this._colorOnly ? null : gl.createRenderbuffer();
this._color = gl.createRenderbuffer();
const stencil = this._depthStencil;
const color = this._color;
const width = this.width;
const height = this.height;
const GL_MAX_MSAA = gl.getParameter(gl.MAX_SAMPLES);
const GL_RB = gl.RENDERBUFFER;
const GL_FB = gl.FRAMEBUFFER;
const GL_C_ATTACH = gl.COLOR_ATTACHMENT0;
const GL_DS_ATTACH = gl.DEPTH_STENCIL_ATTACHMENT;
const GL_RGBA8 = gl.RGBA8;
const GL_D24_S8 = gl.DEPTH24_STENCIL8;
const prevRT = tex.bindRenderTarget(this);
gl.bindRenderbuffer(GL_RB, color);
gl.framebufferRenderbuffer(GL_FB, GL_C_ATTACH, GL_RB, color);
gl.renderbufferStorageMultisample(GL_RB, GL_MAX_MSAA, GL_RGBA8, width, height);
this.memoryUsage = width * height * 8 * Math.sqrt(GL_MAX_MSAA);
if (stencil) {
gl.bindRenderbuffer(GL_RB, stencil);
// eslint-disable-next-line max-len
gl.framebufferRenderbuffer(GL_FB, GL_DS_ATTACH, GL_RB, stencil);
gl.renderbufferStorageMultisample(GL_RB, GL_MAX_MSAA, GL_D24_S8, width, height);
this.memoryUsage *= 2;
}
tex.bindRenderTarget(prevRT, true);
this._context.stats.memory.renderTarget += this.memoryUsage;
}
public linkTarget(target: RenderTargetWebGL | null) {
if (target === this) {
throw 'Framebuffer loop, linking to itself';
}
this._drawTarget = target;
}
public present(
target: RenderTargetWebGL = this._drawTarget,
sourceRect?: Rectangle,
targetPoint?: Point,
) {
if (!this._framebuffer) {
return;
}
if (target === this) {
throw 'Framebuffer loop, presenting to itself';
}
if (!target) return;
if (!target.isValid) return;
let sx = ~~sourceRect?.x || 0;
let sy = ~~sourceRect?.y || 0;
let sw = ~~sourceRect?.width || target.width;
let sh = ~~sourceRect?.height || target.height;
let tx = ~~targetPoint?.x || 0;
let ty = ~~targetPoint?.y || 0;
let dest = target;
const needOffset = tx || ty;
// we can't blit MSAA to noMSAA with offset
if (needOffset && !target.isMsaaTarget) {
dest = this._drawTarget;
sx = sy = tx = ty = 0;
sw = target.width;
sh = target.height;
}
const gl = <WebGL2RenderingContext> this._context._gl;
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._framebuffer);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dest._framebuffer);
//so, i think that not needed, because blit should clear all values
// gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 0.0]);
gl.blitFramebuffer(
sx, sy, sx + sw, sy + sh,
tx, ty, tx + sw, ty + sh,
gl.COLOR_BUFFER_BIT,
gl.NEAREST
);
// target can be MSAA (unpossible, because we have single MSAA render)
// dest.present();
if (needOffset && !target.isMsaaTarget) {
// copy pixel, because we can't blit MSAA with offset
this._drawTarget.present(target, sourceRect, targetPoint);
}
}
public linkTexture(_texture: WebGLTexture) {
throw 'Texture can\'t be linked to MSAA render target';
}
public dispose() {
// MSAA not pooled!
this.unload();
}
public unload() {
this._context._gl.deleteRenderbuffer(this._color);
this._color = null;
this._drawTarget = null;
super.unload();
}
}