UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

921 lines (766 loc) 31.8 kB
/** * @author Richard Davey <rich@phaser.io> * @copyright 2013-2025 Phaser Studio Inc. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ var BlendModes = require('../../BlendModes'); var CenterOn = require('../../../geom/rectangle/CenterOn'); var Class = require('../../../utils/Class'); var ColorMatrixFS = require('../shaders/ColorMatrix-frag'); var GetFastValue = require('../../../utils/object/GetFastValue'); var MultiPipeline = require('./MultiPipeline'); var PostFXFS = require('../shaders/PostFX-frag'); var Rectangle = require('../../../geom/rectangle/Rectangle'); var RenderTarget = require('../RenderTarget'); var SingleQuadFS = require('../shaders/Single-frag'); var SingleQuadVS = require('../shaders/Single-vert'); var WebGLPipeline = require('../WebGLPipeline'); /** * @classdesc * The Pre FX Pipeline is a special kind of pipeline designed specifically for applying * special effects to Game Objects before they are rendered. Where-as the Post FX Pipeline applies an effect _after_ the * object has been rendered, the Pre FX Pipeline allows you to control the rendering of * the object itself - passing it off to its own texture, where multi-buffer compositing * can take place. * * You can only use the PreFX Pipeline on the following types of Game Objects, or those * that extend from them: * * Sprite * Image * Text * TileSprite * RenderTexture * Video * * @class PreFXPipeline * @extends Phaser.Renderer.WebGL.WebGLPipeline * @memberof Phaser.Renderer.WebGL.Pipelines * @constructor * @since 3.60.0 * * @param {Phaser.Types.Renderer.WebGL.WebGLPipelineConfig} config - The configuration options for this pipeline. */ var PreFXPipeline = new Class({ Extends: MultiPipeline, initialize: function PreFXPipeline (config) { var fragShader = GetFastValue(config, 'fragShader', PostFXFS); var vertShader = GetFastValue(config, 'vertShader', SingleQuadVS); var drawShader = GetFastValue(config, 'drawShader', PostFXFS); var defaultShaders = [ { name: 'DrawSprite', fragShader: SingleQuadFS, vertShader: SingleQuadVS }, { name: 'CopySprite', fragShader: fragShader, vertShader: vertShader }, { name: 'DrawGame', fragShader: drawShader, vertShader: SingleQuadVS }, { name: 'ColorMatrix', fragShader: ColorMatrixFS } ]; var configShaders = GetFastValue(config, 'shaders', []); config.shaders = defaultShaders.concat(configShaders); if (!config.vertShader) { config.vertShader = vertShader; } config.batchSize = 1; MultiPipeline.call(this, config); this.isPreFX = true; this.customMainSampler = null; /** * A reference to the Draw Sprite Shader belonging to this Pipeline. * * This shader is used when the sprite is drawn to this fbo (or to the game if drawToFrame is false) * * This property is set during the `boot` method. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#drawSpriteShader * @type {Phaser.Renderer.WebGL.WebGLShader} * @default null * @since 3.60.0 */ this.drawSpriteShader; /** * A reference to the Copy Shader belonging to this Pipeline. * * This shader is used when you call the `copySprite` method. * * This property is set during the `boot` method. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#copyShader * @type {Phaser.Renderer.WebGL.WebGLShader} * @default null * @since 3.60.0 */ this.copyShader; /** * A reference to the Game Draw Shader belonging to this Pipeline. * * This shader draws the fbo to the game. * * This property is set during the `boot` method. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#gameShader * @type {Phaser.Renderer.WebGL.WebGLShader} * @default null * @since 3.60.0 */ this.gameShader; /** * A reference to the Color Matrix Shader belonging to this Pipeline. * * This property is set during the `boot` method. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#colorMatrixShader * @type {Phaser.Renderer.WebGL.WebGLShader} * @since 3.60.0 */ this.colorMatrixShader; /** * Raw byte buffer of vertices used specifically during the copySprite method. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#quadVertexData * @type {ArrayBuffer} * @readonly * @since 3.60.0 */ this.quadVertexData; /** * The WebGLBuffer that holds the quadVertexData. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#quadVertexBuffer * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} * @readonly * @since 3.60.0 */ this.quadVertexBuffer; /** * Float32 view of the quad array buffer. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#quadVertexViewF32 * @type {Float32Array} * @since 3.60.0 */ this.quadVertexViewF32; /** * A temporary Rectangle object re-used internally during sprite drawing. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#spriteBounds * @type {Phaser.Geom.Rectangle} * @private * @since 3.60.0 */ this.spriteBounds = new Rectangle(); /** * A temporary Rectangle object re-used internally during sprite drawing. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#targetBounds * @type {Phaser.Geom.Rectangle} * @private * @since 3.60.0 */ this.targetBounds = new Rectangle(); /** * The full-screen Render Target that the sprite is first drawn to. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#fsTarget * @type {Phaser.Renderer.WebGL.RenderTarget} * @since 3.60.0 */ this.fsTarget; /** * The most recent Game Object drawn. * * @name Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#tempSprite * @type {Phaser.GameObjects.Sprite} * @private * @since 3.60.0 */ this.tempSprite; if (this.renderer.isBooted) { this.manager = this.renderer.pipelines; this.boot(); } }, boot: function () { WebGLPipeline.prototype.boot.call(this); var shaders = this.shaders; var renderer = this.renderer; this.drawSpriteShader = shaders[0]; this.copyShader = shaders[1]; this.gameShader = shaders[2]; this.colorMatrixShader = shaders[3]; // Our full-screen target (exclusive to this pipeline) this.fsTarget = new RenderTarget(renderer, renderer.width, renderer.height, 1, 0, true, true); // Copy by reference the RTs in the PipelineManager, plus add our fsTarget this.renderTargets = this.manager.renderTargets.concat(this.fsTarget); // 6 verts * 28 bytes var data = new ArrayBuffer(168); this.quadVertexData = data; this.quadVertexViewF32 = new Float32Array(data); this.quadVertexBuffer = renderer.createVertexBuffer(data, this.gl.STATIC_DRAW); this.onResize(renderer.width, renderer.height); // So calls to set uniforms in onPreRender target the right shader: this.currentShader = this.copyShader; this.set2f('uResolution', renderer.width, renderer.height); }, /** * Handles the resizing of the quad vertex data. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#onResize * @since 3.60.0 * * @param {number} width - The new width of the quad. * @param {number} height - The new height of the quad. */ onResize: function (width, height) { var vertexViewF32 = this.quadVertexViewF32; // vertexBuffer indexes: // Each vert: [ x, y, u, v, unit, mode, tint ] // 0 - 6 - vert 1 - x0/y0 // 7 - 13 - vert 2 - x1/y1 // 14 - 20 - vert 3 - x2/y2 // 21 - 27 - vert 4 - x0/y0 // 28 - 34 - vert 5 - x2/y2 // 35 - 41 - vert 6 - x3/y3 // Verts vertexViewF32[1] = height; // y0 vertexViewF32[22] = height; // y0 vertexViewF32[14] = width; // x2 vertexViewF32[28] = width; // x2 vertexViewF32[35] = width; // x3 vertexViewF32[36] = height; // y3 }, /** * Adds the vertices data into the batch and flushes if full. * * Assumes 6 vertices in the following arrangement: * * ``` * 0----3 * |\ B| * | \ | * | \ | * | A \| * | \ * 1----2 * ``` * * Where x0 / y0 = 0, x1 / y1 = 1, x2 / y2 = 2 and x3 / y3 = 3 * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#batchQuad * @since 3.60.0 * * @param {(Phaser.GameObjects.GameObject|null)} gameObject - The Game Object, if any, drawing this quad. * @param {number} x0 - The top-left x position. * @param {number} y0 - The top-left y position. * @param {number} x1 - The bottom-left x position. * @param {number} y1 - The bottom-left y position. * @param {number} x2 - The bottom-right x position. * @param {number} y2 - The bottom-right y position. * @param {number} x3 - The top-right x position. * @param {number} y3 - The top-right y position. * @param {number} u0 - UV u0 value. * @param {number} v0 - UV v0 value. * @param {number} u1 - UV u1 value. * @param {number} v1 - UV v1 value. * @param {number} tintTL - The top-left tint color value. * @param {number} tintTR - The top-right tint color value. * @param {number} tintBL - The bottom-left tint color value. * @param {number} tintBR - The bottom-right tint color value. * @param {(number|boolean)} tintEffect - The tint effect for the shader to use. * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [texture] - Texture that will be assigned to the current batch if a flush occurs. * * @return {boolean} `true` if this method caused the batch to flush, otherwise `false`. */ batchQuad: function (gameObject, x0, y0, x1, y1, x2, y2, x3, y3, u0, v0, u1, v1, tintTL, tintTR, tintBL, tintBR, tintEffect, texture) { var bx = Math.min(x0, x1, x2, x3); var by = Math.min(y0, y1, y2, y3); var br = Math.max(x0, x1, x2, x3); var bb = Math.max(y0, y1, y2, y3); var bw = br - bx; var bh = bb - by; var bounds = this.spriteBounds.setTo(bx, by, bw, bh); var padding = (gameObject) ? gameObject.preFX.padding : 0; var width = bw + (padding * 2); var height = bh + (padding * 2); var maxDimension = Math.abs(Math.max(width, height)); var target = this.manager.getRenderTarget(maxDimension); var targetBounds = this.targetBounds.setTo(0, 0, target.width, target.height); // targetBounds is the same size as the fbo and centered on the spriteBounds // so we can use it when we re-render this back to the game CenterOn(targetBounds, Math.round(bounds.centerX), Math.round(bounds.centerY)); this.tempSprite = gameObject; // Now draw the quad var gl = this.gl; var renderer = this.renderer; renderer.clearStencilMask(); this.setShader(this.drawSpriteShader); this.set1i('uMainSampler', 0); this.set2f('uResolution', renderer.width, renderer.height); this.flipProjectionMatrix(true); if (gameObject) { this.onDrawSprite(gameObject, target); gameObject.preFX.onFX(this); } var fsTarget = this.fsTarget; this.flush(); gl.viewport(0, 0, renderer.width, renderer.height); gl.bindFramebuffer(gl.FRAMEBUFFER, fsTarget.framebuffer.webGLFramebuffer); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fsTarget.texture.webGLTexture, 0); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); this.setTexture2D(texture); this.batchVert(x0, y0, u0, v0, 0, tintEffect, tintTL); this.batchVert(x1, y1, u0, v1, 0, tintEffect, tintBL); this.batchVert(x2, y2, u1, v1, 0, tintEffect, tintBR); this.batchVert(x0, y0, u0, v0, 0, tintEffect, tintTL); this.batchVert(x2, y2, u1, v1, 0, tintEffect, tintBR); this.batchVert(x3, y3, u1, v0, 0, tintEffect, tintTR); this.flush(); this.flipProjectionMatrix(false); // Now we've got the sprite drawn to our screen-sized fbo, copy the rect we need to our target gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, target.texture.webGLTexture); gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, targetBounds.x, targetBounds.y, targetBounds.width, targetBounds.height); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.bindTexture(gl.TEXTURE_2D, null); // We've drawn the sprite to the target (using our pipeline shader) // we can pass it to the pipeline in case they want to do further // manipulations with it, post-fx style, then we need to draw the // results back to the game in the correct position this.onBatch(gameObject); // Set this here, so we can immediately call the set uniform functions and it'll work on the correct shader this.currentShader = this.copyShader; this.onDraw(target, this.manager.getSwapRenderTarget(), this.manager.getAltSwapRenderTarget()); return true; }, /** * This callback is invoked when a sprite is drawn by this pipeline. * * It will fire after the shader has been set, but before the sprite has been drawn, * so use it to set any additional uniforms you may need. * * Note: Manipulating the Sprite during this callback will _not_ change how it is drawn to the Render Target. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#onDrawSprite * @since 3.60.0 * * @param {Phaser.GameObjects.Sprite} gameObject - The Sprite being drawn. * @param {Phaser.Renderer.WebGL.RenderTarget} target - The Render Target the Sprite will be drawn to. */ onDrawSprite: function () { }, /** * This callback is invoked when you call the `copySprite` method. * * It will fire after the shader has been set, but before the source target has been copied, * so use it to set any additional uniforms you may need. * * Note: Manipulating the Sprite during this callback will _not_ change the Render Targets. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#onCopySprite * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The source Render Target being copied from. * @param {Phaser.Renderer.WebGL.RenderTarget} target - The target Render Target that will be copied to. * @param {Phaser.GameObjects.Sprite} gameObject - The Sprite being copied. */ onCopySprite: function () { }, /** * Copy the `source` Render Target to the `target` Render Target. * * No target resizing takes place. If the `source` Render Target is larger than the `target`, * then only a portion the same size as the `target` dimensions is copied across. * * Calling this method will invoke the `onCopySprite` handler and will also call * the `onFXCopy` callback on the Sprite. Both of these happen prior to the copy, allowing you * to use them to set shader uniforms and other values. * * You can optionally pass in a ColorMatrix. If so, it will use the ColorMatrix shader * during the copy, allowing you to manipulate the colors to a fine degree. * See the `ColorMatrix` class for more details. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#copySprite * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The source Render Target being copied from. * @param {Phaser.Renderer.WebGL.RenderTarget} target - The target Render Target that will be copied to. * @param {boolean} [clear=true] - Clear the target before copying? * @param {boolean} [clearAlpha=true] - Clear the alpha channel when running `gl.clear` on the target? * @param {boolean} [eraseMode=false] - Erase source from target using ERASE Blend Mode? * @param {Phaser.Display.ColorMatrix} [colorMatrix] - Optional ColorMatrix to use when copying the Sprite. * @param {Phaser.Renderer.WebGL.WebGLShader} [shader] - The shader to use to copy the target. Defaults to the `copyShader`. */ copySprite: function (source, target, clear, clearAlpha, eraseMode, colorMatrix, shader) { if (clear === undefined) { clear = true; } if (clearAlpha === undefined) { clearAlpha = true; } if (eraseMode === undefined) { eraseMode = false; } if (shader === undefined) { shader = this.copyShader; } var gl = this.gl; var sprite = this.tempSprite; if (colorMatrix) { shader = this.colorMatrixShader; } this.currentShader = shader; var wasBound = this.setVertexBuffer(this.quadVertexBuffer); shader.bind(wasBound, false); var renderer = this.renderer; this.set1i('uMainSampler', 0); this.set2f('uResolution', renderer.width, renderer.height); sprite.preFX.onFXCopy(this); this.onCopySprite(source, target, sprite); if (colorMatrix) { this.set1fv('uColorMatrix', colorMatrix.getData()); this.set1f('uAlpha', colorMatrix.alpha); } gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, source.texture.webGLTexture); if (source.height > target.height) { gl.viewport(0, 0, source.width, source.height); this.setTargetUVs(source, target); } else { var diff = target.height - source.height; gl.viewport(0, diff, source.width, source.height); this.resetUVs(); } gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer.webGLFramebuffer); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target.texture.webGLTexture, 0); if (clear) { gl.clearColor(0, 0, 0, Number(!clearAlpha)); gl.clear(gl.COLOR_BUFFER_BIT); } if (eraseMode) { var blendMode = this.renderer.currentBlendMode; this.renderer.setBlendMode(BlendModes.ERASE); } gl.bufferData(gl.ARRAY_BUFFER, this.quadVertexData, gl.STATIC_DRAW); gl.drawArrays(gl.TRIANGLES, 0, 6); if (eraseMode) { this.renderer.setBlendMode(blendMode); } gl.bindFramebuffer(gl.FRAMEBUFFER, null); }, /** * Draws the `source` Render Target to the `target` Render Target. * * This is done using whatever the currently bound shader is. This method does * not set a shader. All it does is bind the source texture, set the viewport and UVs * then bind the target framebuffer, clears it and draws the source to it. * * At the end a null framebuffer is bound. No other clearing-up takes place, so * use this method carefully. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#copy * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The source Render Target. * @param {Phaser.Renderer.WebGL.RenderTarget} target - The target Render Target. */ copy: function (source, target) { var gl = this.gl; this.set1i('uMainSampler', 0); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, source.texture.webGLTexture); // source and target must always be the same size gl.viewport(0, 0, source.width, source.height); this.setUVs(0, 0, 0, 1, 1, 1, 1, 0); gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer.webGLFramebuffer); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target.texture.webGLTexture, 0); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.bufferData(gl.ARRAY_BUFFER, this.quadVertexData, gl.STATIC_DRAW); gl.drawArrays(gl.TRIANGLES, 0, 6); gl.bindFramebuffer(gl.FRAMEBUFFER, null); }, /** * Draws the `source1` and `source2` Render Targets to the `target` Render Target * using a linear blend effect, which is controlled by the `strength` parameter. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#blendFrames * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source1 - The first source Render Target. * @param {Phaser.Renderer.WebGL.RenderTarget} source2 - The second source Render Target. * @param {Phaser.Renderer.WebGL.RenderTarget} [target] - The target Render Target. * @param {number} [strength=1] - The strength of the blend. * @param {boolean} [clearAlpha=true] - Clear the alpha channel when running `gl.clear` on the target? */ blendFrames: function (source1, source2, target, strength, clearAlpha) { this.manager.blendFrames(source1, source2, target, strength, clearAlpha); }, /** * Draws the `source1` and `source2` Render Targets to the `target` Render Target * using an additive blend effect, which is controlled by the `strength` parameter. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#blendFramesAdditive * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source1 - The first source Render Target. * @param {Phaser.Renderer.WebGL.RenderTarget} source2 - The second source Render Target. * @param {Phaser.Renderer.WebGL.RenderTarget} [target] - The target Render Target. * @param {number} [strength=1] - The strength of the blend. * @param {boolean} [clearAlpha=true] - Clear the alpha channel when running `gl.clear` on the target? */ blendFramesAdditive: function (source1, source2, target, strength, clearAlpha) { this.manager.blendFramesAdditive(source1, source2, target, strength, clearAlpha); }, /** * This method will copy the given Render Target to the game canvas using the `copyShader`. * * This applies the results of the copy shader during the draw. * * If you wish to copy the target without any effects see the `copyToGame` method instead. * * This method should be the final thing called in your pipeline. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#drawToGame * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The Render Target to draw to the game. */ drawToGame: function (source) { this.currentShader = null; this.setShader(this.copyShader); this.bindAndDraw(source); }, /** * This method will copy the given Render Target to the game canvas using the `gameShader`. * * Unless you've changed it, the `gameShader` copies the target without modifying it, just * ensuring it is placed in the correct location on the canvas. * * If you wish to draw the target with and apply the fragment shader at the same time, * see the `drawToGame` method instead. * * This method should be the final thing called in your pipeline. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#copyToGame * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The Render Target to copy to the game. */ copyToGame: function (source) { this.currentShader = null; this.setShader(this.gameShader); this.bindAndDraw(source); }, /** * This method is called by `drawToGame` and `copyToGame`. It takes the source Render Target * and copies it back to the game canvas, or the next frame buffer in the stack, and should * be considered the very last thing this pipeline does. * * You don't normally need to call this method, or override it, however it is left public * should you wish to do so. * * Note that it does _not_ set a shader. You should do this yourself if invoking this. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#bindAndDraw * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The Render Target to draw to the game. */ bindAndDraw: function (source) { var gl = this.gl; var renderer = this.renderer; this.set1i('uMainSampler', 0); if (this.customMainSampler) { this.setTexture2D(this.customMainSampler); } else { this.setTexture2D(source.texture); } var matrix = this._tempMatrix1.loadIdentity(); var x = this.targetBounds.x; var y = this.targetBounds.y; var xw = x + source.width; var yh = y + source.height; var x0 = matrix.getX(x, y); var x1 = matrix.getX(x, yh); var x2 = matrix.getX(xw, yh); var x3 = matrix.getX(xw, y); // Regular verts var y0 = matrix.getY(x, y); var y1 = matrix.getY(x, yh); var y2 = matrix.getY(xw, yh); var y3 = matrix.getY(xw, y); // Flip verts: // var y0 = matrix.getY(x, yh); // var y1 = matrix.getY(x, y); // var y2 = matrix.getY(xw, y); // var y3 = matrix.getY(xw, yh); var white = 0xffffff; this.batchVert(x0, y0, 0, 0, 0, 0, white); this.batchVert(x1, y1, 0, 1, 0, 0, white); this.batchVert(x2, y2, 1, 1, 0, 0, white); this.batchVert(x0, y0, 0, 0, 0, 0, white); this.batchVert(x2, y2, 1, 1, 0, 0, white); this.batchVert(x3, y3, 1, 0, 0, 0, white); renderer.restoreFramebuffer(false, true); if (!renderer.currentFramebuffer) { gl.viewport(0, 0, renderer.width, renderer.height); } renderer.restoreStencilMask(); this.flush(); // Clear the source framebuffer out, ready for the next pass // gl.clearColor(0, 0, 0, 0); // gl.bindFramebuffer(gl.FRAMEBUFFER, source.framebuffer.webGLFramebuffer); // gl.clear(gl.COLOR_BUFFER_BIT); // gl.bindFramebuffer(gl.FRAMEBUFFER, null); // No hanging references this.tempSprite = null; }, /** * This method is called every time the `batchSprite` method is called and is passed a * reference to the current render target. * * If you override this method, then it should make sure it calls either the * `drawToGame` or `copyToGame` methods as the final thing it does. However, you can do as * much additional processing as you like prior to this. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#onDraw * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} target - The Render Target to draw to the game. * @param {Phaser.Renderer.WebGL.RenderTarget} [swapTarget] - The Swap Render Target, useful for double-buffer effects. * @param {Phaser.Renderer.WebGL.RenderTarget} [altSwapTarget] - The Swap Render Target, useful for double-buffer effects. */ onDraw: function (target) { this.drawToGame(target); }, /** * Set the UV values for the 6 vertices that make up the quad used by the copy shader. * * Be sure to call `resetUVs` once you have finished manipulating the UV coordinates. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#setUVs * @since 3.60.0 * * @param {number} uA - The u value of vertex A. * @param {number} vA - The v value of vertex A. * @param {number} uB - The u value of vertex B. * @param {number} vB - The v value of vertex B. * @param {number} uC - The u value of vertex C. * @param {number} vC - The v value of vertex C. * @param {number} uD - The u value of vertex D. * @param {number} vD - The v value of vertex D. */ setUVs: function (uA, vA, uB, vB, uC, vC, uD, vD) { var vertexViewF32 = this.quadVertexViewF32; vertexViewF32[2] = uA; vertexViewF32[3] = vA; vertexViewF32[9] = uB; vertexViewF32[10] = vB; vertexViewF32[16] = uC; vertexViewF32[17] = vC; vertexViewF32[23] = uA; vertexViewF32[24] = vA; vertexViewF32[30] = uC; vertexViewF32[31] = vC; vertexViewF32[37] = uD; vertexViewF32[38] = vD; }, /** * Sets the vertex UV coordinates of the quad used by the copy shaders * so that they correctly adjust the texture coordinates for a blit frame effect. * * Be sure to call `resetUVs` once you have finished manipulating the UV coordinates. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#setTargetUVs * @since 3.60.0 * * @param {Phaser.Renderer.WebGL.RenderTarget} source - The source Render Target. * @param {Phaser.Renderer.WebGL.RenderTarget} target - The target Render Target. */ setTargetUVs: function (source, target) { var diff = (target.height / source.height); if (diff > 0.5) { diff = 0.5 - (diff - 0.5); } else { diff = 0.5 + (0.5 - diff); } this.setUVs(0, diff, 0, 1 + diff, 1, 1 + diff, 1, diff); }, /** * Resets the quad vertice UV values to their default settings. * * The quad is used by the copy shader in this pipeline. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#resetUVs * @since 3.60.0 */ resetUVs: function () { this.setUVs(0, 0, 0, 1, 1, 1, 1, 0); }, /** * Destroys all shader instances, removes all object references and nulls all external references. * * @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#destroy * @fires Phaser.Renderer.WebGL.Pipelines.Events#DESTROY * @since 3.60.0 * * @return {this} This WebGLPipeline instance. */ destroy: function () { this.renderer.deleteBuffer(this.quadVertexBuffer); this.drawSpriteShader = null; this.copyShader = null; this.gameShader = null; this.colorMatrixShader = null; this.quadVertexData = null; this.quadVertexBuffer = null; this.quadVertexViewF32 = null; this.fsTarget = null; this.tempSprite = null; MultiPipeline.prototype.destroy.call(this); return this; } }); module.exports = PreFXPipeline;