UNPKG

@awayjs/stage

Version:
145 lines (111 loc) 3.84 kB
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(); } }