UNPKG

pixi.js

Version:

<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">

1 lines 48.5 kB
{"version":3,"file":"FilterSystem.mjs","sources":["../../src/filters/FilterSystem.ts"],"sourcesContent":["import { ExtensionType } from '../extensions/Extensions';\nimport { Matrix } from '../maths/matrix/Matrix';\nimport { type PointData } from '../maths/point/PointData';\nimport { type Rectangle } from '../maths/shapes/Rectangle';\nimport { BindGroup } from '../rendering/renderers/gpu/shader/BindGroup';\nimport { Geometry } from '../rendering/renderers/shared/geometry/Geometry';\nimport { UniformGroup } from '../rendering/renderers/shared/shader/UniformGroup';\nimport { Texture } from '../rendering/renderers/shared/texture/Texture';\nimport { TexturePool } from '../rendering/renderers/shared/texture/TexturePool';\nimport { type Renderer, RendererType } from '../rendering/renderers/types';\nimport { Bounds } from '../scene/container/bounds/Bounds';\nimport { getGlobalRenderableBounds } from '../scene/container/bounds/getRenderableBounds';\nimport { warn } from '../utils/logging/warn';\n\nimport type { WebGLRenderer } from '../rendering/renderers/gl/WebGLRenderer';\nimport type { WebGPURenderer } from '../rendering/renderers/gpu/WebGPURenderer';\nimport type { Instruction } from '../rendering/renderers/shared/instructions/Instruction';\nimport type { Renderable } from '../rendering/renderers/shared/Renderable';\nimport type { RenderTarget } from '../rendering/renderers/shared/renderTarget/RenderTarget';\nimport type { RenderSurface } from '../rendering/renderers/shared/renderTarget/RenderTargetSystem';\nimport type { System } from '../rendering/renderers/shared/system/System';\nimport type { Container } from '../scene/container/Container';\nimport type { Sprite } from '../scene/sprite/Sprite';\nimport type { Filter } from './Filter';\nimport type { FilterEffect } from './FilterEffect';\n\nconst quadGeometry = new Geometry({\n attributes: {\n aPosition: {\n buffer: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),\n format: 'float32x2',\n stride: 2 * 4,\n offset: 0,\n },\n },\n indexBuffer: new Uint32Array([0, 1, 2, 0, 2, 3]),\n});\n\n/**\n * The filter pipeline is responsible for applying filters scene items!\n *\n * KNOWN BUGS:\n * 1. Global bounds calculation is incorrect if it is used when flip flopping filters. The maths can be found below\n * eg: filters [noiseFilter, blurFilter] noiseFilter will calculate the global bounds incorrectly.\n *\n * 2. RenderGroups do not work with filters. This is because the renderGroup matrix is not currently taken into account.\n *\n * Implementation notes:\n * 1. Gotcha - nesting filters that require blending will not work correctly. This creates a chicken and egg problem\n * the complexity and performance required to do this is not worth it i feel.. but lets see if others agree!\n *\n * 2. Filters are designed to be changed on the fly, this is means that changing filter information each frame will\n * not trigger an instruction rebuild. If you are constantly turning a filter on and off.. its therefore better to set\n * enabled to true or false on the filter. Or setting an empty array.\n *\n * 3. Need to look at perhaps aliasing when flip flopping filters. Really we should only need to antialias the FIRST\n * Texture we render too. The rest can be non aliased. This might help performance.\n * Currently we flip flop with an antialiased texture if antialiasing is enabled on the filter.\n * @internal\n */\nexport interface FilterInstruction extends Instruction\n{\n renderPipeId: 'filter',\n action: 'pushFilter' | 'popFilter',\n container?: Container,\n renderables?: Renderable[],\n filterEffect: FilterEffect,\n}\n\n/**\n * Class representing the data required for applying filters.\n * This class holds various properties that are used during the filter application process.\n * @internal\n */\nclass FilterData\n{\n /**\n * Indicates whether the filter should be skipped.\n * @type {boolean}\n */\n public skip = false;\n\n /**\n * The texture to which the filter is applied.\n * @type {Texture}\n */\n public inputTexture: Texture = null;\n\n /**\n * The back texture used for blending, if required.\n * @type {Texture | null}\n */\n public backTexture?: Texture = null;\n\n /**\n * The list of filters to be applied.\n * @type {Filter[]}\n */\n public filters: Filter[] = null;\n\n /**\n * The bounds of the filter area.\n * @type {Bounds}\n */\n public bounds = new Bounds();\n\n /**\n * The container to which the filter is applied.\n * @type {Container}\n */\n public container: Container = null;\n\n /**\n * Indicates whether blending is required for the filter.\n * @type {boolean}\n */\n public blendRequired: boolean = false;\n\n /**\n * The render surface where the output of the filter is rendered.\n * @type {RenderSurface}\n */\n public outputRenderSurface: RenderSurface = null;\n\n /**\n * The offset of the output render surface.\n * @type {PointData}\n */\n public outputOffset: PointData = { x: 0, y: 0 };\n\n /**\n * The global frame of the filter area.\n * @type {{ x: number, y: number, width: number, height: number }}\n */\n public globalFrame = { x: 0, y: 0, width: 0, height: 0 };\n\n /**\n * Indicates whether antialiasing is enabled for the filter.\n * @type {boolean}\n */\n public antialias: boolean;\n\n /**\n * The resolution of the filter.\n * @type {number}\n */\n public resolution: number;\n}\n\n/**\n * System that manages the filter pipeline\n * @category rendering\n * @advanced\n */\nexport class FilterSystem implements System\n{\n /** @ignore */\n public static extension = {\n type: [\n ExtensionType.WebGLSystem,\n ExtensionType.WebGPUSystem,\n ],\n name: 'filter',\n } as const;\n\n public readonly renderer: Renderer;\n\n private _filterStackIndex = 0;\n private _filterStack: FilterData[] = [];\n\n private readonly _filterGlobalUniforms = new UniformGroup({\n uInputSize: { value: new Float32Array(4), type: 'vec4<f32>' },\n uInputPixel: { value: new Float32Array(4), type: 'vec4<f32>' },\n uInputClamp: { value: new Float32Array(4), type: 'vec4<f32>' },\n uOutputFrame: { value: new Float32Array(4), type: 'vec4<f32>' },\n uGlobalFrame: { value: new Float32Array(4), type: 'vec4<f32>' },\n uOutputTexture: { value: new Float32Array(4), type: 'vec4<f32>' },\n });\n\n private readonly _globalFilterBindGroup: BindGroup = new BindGroup({});\n private _activeFilterData: FilterData;\n\n constructor(renderer: Renderer)\n {\n this.renderer = renderer;\n }\n\n /**\n * The back texture of the currently active filter. Requires the filter to have `blendRequired` set to true.\n * @readonly\n */\n public get activeBackTexture(): Texture | undefined\n {\n return this._activeFilterData?.backTexture;\n }\n\n /**\n * Pushes a filter instruction onto the filter stack.\n * @param instruction - The instruction containing the filter effect and container.\n * @internal\n */\n public push(instruction: FilterInstruction)\n {\n const renderer = this.renderer;\n\n const filters = instruction.filterEffect.filters;\n\n // get a filter data from the stack. They can be reused multiple times each frame,\n // so we don't need to worry about overwriting them in a single pass.\n const filterData = this._pushFilterData();\n\n filterData.skip = false;\n\n filterData.filters = filters as Filter[];\n filterData.container = instruction.container;\n filterData.outputRenderSurface = renderer.renderTarget.renderSurface;\n\n const colorTextureSource = renderer.renderTarget.renderTarget.colorTexture.source;\n\n const rootResolution = colorTextureSource.resolution;\n const rootAntialias = colorTextureSource.antialias;\n\n // if there are no filters, we skip the pass\n if (filters.length === 0)\n {\n filterData.skip = true;\n\n return;\n }\n\n const bounds = filterData.bounds;\n\n // this path is used by the blend modes mostly!\n // they collect all renderables and push them into a list.\n // this list is then used to calculate the bounds of the filter area\n if (instruction.renderables)\n {\n getGlobalRenderableBounds(instruction.renderables, bounds);\n }\n // if a filterArea is provided, we save our selves some measuring and just use that area supplied\n else if (instruction.filterEffect.filterArea)\n {\n bounds.clear();\n\n // transform the filterArea into global space..\n bounds.addRect(instruction.filterEffect.filterArea);\n\n // new for v8, we transform the bounds into the space of the container\n bounds.applyMatrix(instruction.container.worldTransform);\n }\n // classic filter path, we get the bounds of the container and use it by recursively\n // measuring.\n else\n {\n // we want to factor render layers to get the real visual bounds of this container.\n // so the last param is true..\n instruction.container.getFastGlobalBounds(true, bounds);\n }\n\n if (instruction.container)\n {\n // When a container is cached as a texture, its filters need to be applied relative to its\n // cached parent's coordinate space rather than world space. This transform adjustment ensures\n // filters are applied in the correct coordinate system.\n const renderGroup = instruction.container.renderGroup || instruction.container.parentRenderGroup;\n const filterFrameTransform = renderGroup.cacheToLocalTransform;\n\n if (filterFrameTransform)\n {\n bounds.applyMatrix(filterFrameTransform);\n }\n }\n\n this._calculateFilterBounds(filterData, renderer.renderTarget.rootViewPort, rootAntialias, rootResolution, 1);\n\n if (filterData.skip)\n {\n return;\n }\n\n const previousFilterData = this._getPreviousFilterData();\n\n let globalResolution = rootResolution;\n let offsetX = 0;\n let offsetY = 0;\n\n if (previousFilterData)\n {\n offsetX = previousFilterData.bounds.minX;\n offsetY = previousFilterData.bounds.minY;\n globalResolution = previousFilterData.inputTexture.source._resolution;\n }\n\n filterData.outputOffset.x = bounds.minX - offsetX;\n filterData.outputOffset.y = bounds.minY - offsetY;\n\n const globalFrame = filterData.globalFrame;\n\n globalFrame.x = offsetX * globalResolution;\n globalFrame.y = offsetY * globalResolution;\n globalFrame.width = colorTextureSource.width * globalResolution;\n globalFrame.height = colorTextureSource.height * globalResolution;\n\n // set all the filter data\n\n filterData.backTexture = Texture.EMPTY;\n\n if (filterData.blendRequired)\n {\n renderer.renderTarget.finishRenderPass();\n // this actually forces the current commandQueue to render everything so far.\n // if we don't do this, we won't be able to copy pixels for the background\n const renderTarget = renderer.renderTarget.getRenderTarget(filterData.outputRenderSurface);\n\n filterData.backTexture = this.getBackTexture(renderTarget, bounds, previousFilterData?.bounds);\n }\n\n /// ///\n // bind...\n // get a P02 texture from our pool...\n filterData.inputTexture = TexturePool.getOptimalTexture(\n bounds.width,\n bounds.height,\n filterData.resolution,\n filterData.antialias,\n );\n\n renderer.renderTarget.bind(filterData.inputTexture, true);\n // set the global uniforms to take into account the bounds offset required\n\n renderer.globalUniforms.push({\n offset: bounds,\n });\n }\n\n /**\n * Applies filters to a texture.\n *\n * This method takes a texture and a list of filters, applies the filters to the texture,\n * and returns the resulting texture.\n * @param {object} params - The parameters for applying filters.\n * @param {Texture} params.texture - The texture to apply filters to.\n * @param {Filter[]} params.filters - The filters to apply.\n * @returns {Texture} The resulting texture after all filters have been applied.\n * @example\n *\n * ```ts\n * // Create a texture and a list of filters\n * const texture = new Texture(...);\n * const filters = [new BlurFilter(), new ColorMatrixFilter()];\n *\n * // Apply the filters to the texture\n * const resultTexture = filterSystem.applyToTexture({ texture, filters });\n *\n * // Use the resulting texture\n * sprite.texture = resultTexture;\n * ```\n *\n * Key Points:\n * 1. padding is not currently supported here - so clipping may occur with filters that use padding.\n * 2. If all filters are disabled or skipped, the original texture is returned.\n */\n public generateFilteredTexture({ texture, filters }: {texture: Texture, filters: Filter[]}): Texture\n {\n // get a filter data from the stack. They can be reused multiple times each frame,\n // so we don't need to worry about overwriting them in a single pass.\n const filterData = this._pushFilterData();\n\n this._activeFilterData = filterData;\n filterData.skip = false;\n\n filterData.filters = filters;\n\n const colorTextureSource = texture.source;\n\n const rootResolution = colorTextureSource.resolution;\n const rootAntialias = colorTextureSource.antialias;\n\n // if there are no filters, we skip the pass\n if (filters.length === 0)\n {\n filterData.skip = true;\n\n return texture;\n }\n\n const bounds = filterData.bounds;\n\n // this path is used by the blend modes mostly!\n // they collect all renderables and push them into a list.\n // this list is then used to calculate the bounds of the filter area\n\n bounds.addRect(texture.frame);\n\n this._calculateFilterBounds(filterData, bounds.rectangle, rootAntialias, rootResolution, 0);\n\n if (filterData.skip)\n {\n return texture;\n }\n\n const globalResolution = rootResolution;\n const offsetX = 0;\n const offsetY = 0;\n\n filterData.outputOffset.x = -bounds.minX;\n filterData.outputOffset.y = -bounds.minY;\n\n const globalFrame = filterData.globalFrame;\n\n globalFrame.x = offsetX * globalResolution;\n globalFrame.y = offsetY * globalResolution;\n globalFrame.width = colorTextureSource.width * globalResolution;\n globalFrame.height = colorTextureSource.height * globalResolution;\n\n /// /////////\n\n // set all the filter data\n // get a P02 texture from our pool...\n filterData.outputRenderSurface = TexturePool.getOptimalTexture(\n bounds.width,\n bounds.height,\n filterData.resolution,\n filterData.antialias,\n );\n\n filterData.backTexture = Texture.EMPTY;\n\n /// ///\n // bind...\n // TODO this might need looking at for padding!\n filterData.inputTexture = texture;\n\n /// ////////////// PART 2 POP //////////////////////\n\n const renderer = this.renderer;\n\n // TODO required? check with AA\n renderer.renderTarget.finishRenderPass();\n\n // get a BufferResource from the uniformBatch.\n // this will batch the shader uniform data and give us a buffer resource we can\n // set on our globalUniform Bind Group\n this._applyFiltersToTexture(filterData, true);\n\n const outputTexture = filterData.outputRenderSurface as Texture;\n\n outputTexture.source.alphaMode = 'premultiplied-alpha';\n\n return outputTexture;\n }\n\n /** @internal */\n public pop()\n {\n const renderer = this.renderer;\n\n const filterData = this._popFilterData();\n\n // if we are skipping this filter then we just do nothing :D\n if (filterData.skip)\n {\n return;\n }\n\n renderer.globalUniforms.pop();\n\n renderer.renderTarget.finishRenderPass();\n\n this._activeFilterData = filterData;\n\n this._applyFiltersToTexture(filterData, false);\n\n // if we made a background texture, lets return that also\n if (filterData.blendRequired)\n {\n TexturePool.returnTexture(filterData.backTexture);\n }\n\n // return the texture to the pool so we can reuse the next frame\n TexturePool.returnTexture(filterData.inputTexture);\n }\n\n /**\n * Copies the last render surface to a texture.\n * @param lastRenderSurface - The last render surface to copy from.\n * @param bounds - The bounds of the area to copy.\n * @param previousBounds - The previous bounds to use for offsetting the copy.\n */\n public getBackTexture(lastRenderSurface: RenderTarget, bounds: Bounds, previousBounds?: Bounds)\n {\n const backgroundResolution = lastRenderSurface.colorTexture.source._resolution;\n\n const backTexture = TexturePool.getOptimalTexture(\n bounds.width,\n bounds.height,\n backgroundResolution,\n false,\n );\n\n let x = bounds.minX;\n let y = bounds.minY;\n\n if (previousBounds)\n {\n x -= previousBounds.minX;\n y -= previousBounds.minY;\n }\n\n x = Math.floor(x * backgroundResolution);\n y = Math.floor(y * backgroundResolution);\n\n const width = Math.ceil(bounds.width * backgroundResolution);\n const height = Math.ceil(bounds.height * backgroundResolution);\n\n this.renderer.renderTarget.copyToTexture(\n lastRenderSurface,\n backTexture,\n { x, y },\n { width, height },\n { x: 0, y: 0 }\n );\n\n return backTexture;\n }\n\n /**\n * Applies a filter to a texture.\n * @param filter - The filter to apply.\n * @param input - The input texture.\n * @param output - The output render surface.\n * @param clear - Whether to clear the output surface before applying the filter.\n */\n public applyFilter(filter: Filter, input: Texture, output: RenderSurface, clear: boolean)\n {\n const renderer = this.renderer;\n\n const filterData = this._activeFilterData;\n\n const outputRenderSurface = filterData.outputRenderSurface;\n\n const filterUniforms = this._filterGlobalUniforms;\n const uniforms = filterUniforms.uniforms;\n\n const outputFrame = uniforms.uOutputFrame;\n const inputSize = uniforms.uInputSize;\n const inputPixel = uniforms.uInputPixel;\n const inputClamp = uniforms.uInputClamp;\n const globalFrame = uniforms.uGlobalFrame;\n const outputTexture = uniforms.uOutputTexture;\n\n // are we rendering back to the original surface?\n if (outputRenderSurface === output)\n {\n outputFrame[0] = filterData.outputOffset.x;\n outputFrame[1] = filterData.outputOffset.y;\n }\n else\n {\n outputFrame[0] = 0;\n outputFrame[1] = 0;\n }\n\n outputFrame[2] = input.frame.width;\n outputFrame[3] = input.frame.height;\n\n inputSize[0] = input.source.width;\n inputSize[1] = input.source.height;\n inputSize[2] = 1 / inputSize[0];\n inputSize[3] = 1 / inputSize[1];\n\n inputPixel[0] = input.source.pixelWidth;\n inputPixel[1] = input.source.pixelHeight;\n inputPixel[2] = 1.0 / inputPixel[0];\n inputPixel[3] = 1.0 / inputPixel[1];\n\n inputClamp[0] = 0.5 * inputPixel[2];\n inputClamp[1] = 0.5 * inputPixel[3];\n inputClamp[2] = (input.frame.width * inputSize[2]) - (0.5 * inputPixel[2]);\n inputClamp[3] = (input.frame.height * inputSize[3]) - (0.5 * inputPixel[3]);\n\n globalFrame[0] = filterData.globalFrame.x;\n globalFrame[1] = filterData.globalFrame.y;\n\n globalFrame[2] = filterData.globalFrame.width;\n globalFrame[3] = filterData.globalFrame.height;\n\n // we are going to overwrite resource we can set it to null!\n if (output instanceof Texture) output.source.resource = null;\n\n // set the output texture - this is where we are going to render to\n const renderTarget = this.renderer.renderTarget.getRenderTarget(output);\n\n renderer.renderTarget.bind(output, !!clear);\n\n if (output instanceof Texture)\n {\n outputTexture[0] = output.frame.width;\n outputTexture[1] = output.frame.height;\n }\n else\n {\n // this means a renderTarget was passed directly\n outputTexture[0] = renderTarget.width;\n outputTexture[1] = renderTarget.height;\n }\n\n outputTexture[2] = renderTarget.isRoot ? -1 : 1;\n\n filterUniforms.update();\n\n // TODO - should prolly use a adaptor...\n if ((renderer as WebGPURenderer).renderPipes.uniformBatch)\n {\n const batchUniforms = (renderer as WebGPURenderer).renderPipes.uniformBatch\n .getUboResource(filterUniforms);\n\n this._globalFilterBindGroup.setResource(batchUniforms, 0);\n }\n else\n {\n this._globalFilterBindGroup.setResource(filterUniforms, 0);\n }\n\n // now lets update the output texture...\n\n // set bind group..\n this._globalFilterBindGroup.setResource(input.source, 1);\n this._globalFilterBindGroup.setResource(input.source.style, 2);\n\n filter.groups[0] = this._globalFilterBindGroup;\n\n renderer.encoder.draw({\n geometry: quadGeometry,\n shader: filter,\n state: filter._state,\n topology: 'triangle-list'\n });\n\n // WebGPU blit's automatically, but WebGL does not!\n if (renderer.type === RendererType.WEBGL)\n {\n renderer.renderTarget.finishRenderPass();\n }\n }\n\n /**\n * Multiply _input normalized coordinates_ to this matrix to get _sprite texture normalized coordinates_.\n *\n * Use `outputMatrix * vTextureCoord` in the shader.\n * @param outputMatrix - The matrix to output to.\n * @param {Sprite} sprite - The sprite to map to.\n * @returns The mapped matrix.\n */\n public calculateSpriteMatrix(outputMatrix: Matrix, sprite: Sprite): Matrix\n {\n const data = this._activeFilterData;\n\n const mappedMatrix = outputMatrix.set(\n data.inputTexture._source.width,\n 0, 0,\n data.inputTexture._source.height,\n data.bounds.minX, data.bounds.minY\n );\n\n const worldTransform = sprite.worldTransform.copyTo(Matrix.shared);\n\n const renderGroup = sprite.renderGroup || sprite.parentRenderGroup;\n\n if (renderGroup && renderGroup.cacheToLocalTransform)\n {\n // get the matrix relative to the render group..\n worldTransform.prepend(renderGroup.cacheToLocalTransform);\n }\n\n worldTransform.invert();\n mappedMatrix.prepend(worldTransform);\n mappedMatrix.scale(\n 1.0 / sprite.texture.frame.width,\n 1.0 / sprite.texture.frame.height\n );\n\n mappedMatrix.translate(sprite.anchor.x, sprite.anchor.y);\n\n return mappedMatrix;\n }\n\n public destroy(): void\n {\n // BOOM!\n }\n\n private _applyFiltersToTexture(filterData: FilterData, clear: boolean)\n {\n const inputTexture = filterData.inputTexture;\n\n const bounds = filterData.bounds;\n\n const filters = filterData.filters;\n\n // get a BufferResource from the uniformBatch.\n // this will batch the shader uniform data and give us a buffer resource we can\n // set on our globalUniform Bind Group\n\n // update the resources on the bind group...\n this._globalFilterBindGroup.setResource(inputTexture.source.style, 2);\n this._globalFilterBindGroup.setResource(filterData.backTexture.source, 3);\n\n if (filters.length === 1)\n {\n // render a single filter...\n filters[0].apply(this, inputTexture, filterData.outputRenderSurface, clear);\n }\n else\n {\n let flip = filterData.inputTexture;\n\n const tempTexture = TexturePool.getOptimalTexture(\n bounds.width,\n bounds.height,\n flip.source._resolution,\n false\n );\n\n // get another texture that we will render the next filter too\n let flop = tempTexture;\n\n let i = 0;\n\n // loop and apply the filters, omitting the last one as we will render that to the final target\n for (i = 0; i < filters.length - 1; ++i)\n {\n const filter = filters[i];\n\n filter.apply(this, flip, flop, true);\n const t = flip;\n\n flip = flop;\n flop = t;\n }\n\n filters[i].apply(this, flip, filterData.outputRenderSurface, clear);\n\n // return those textures for later!\n TexturePool.returnTexture(tempTexture);\n }\n }\n\n private _calculateFilterBounds(\n filterData: FilterData,\n viewPort: Rectangle,\n rootAntialias: boolean,\n rootResolution: number,\n // a multiplier padding for the bounds calculation\n // this prop is used when applying filters to textures\n // as the should have padding applied to them already (until we fix padding when applying them to textures)\n // set to 0 to remove padding from the bounds calculation\n paddingMultiplier: number\n )\n {\n const renderer = this.renderer;\n\n const bounds = filterData.bounds;\n const filters = filterData.filters;\n\n // get GLOBAL bounds of the item we are going to apply the filter to\n\n // next we get the settings for the filter\n // we need to find the LOWEST resolution for the filter list\n let resolution = Infinity;\n // Padding is additive to add padding to our padding\n let padding = 0;\n // if this is true for all filter, it should be true, and otherwise false\n let antialias = true;\n // true if any filter requires the previous render target\n let blendRequired = false;\n // true if any filter in the list is enabled\n let enabled = false;\n // false if any filter in the list has false\n let clipToViewport = true;\n\n for (let i = 0; i < filters.length; i++)\n {\n const filter = filters[i];\n\n resolution = Math.min(resolution, filter.resolution === 'inherit'\n ? rootResolution : filter.resolution);\n padding += filter.padding;\n\n if (filter.antialias === 'off')\n {\n antialias = false;\n }\n else if (filter.antialias === 'inherit')\n {\n antialias &&= rootAntialias;\n }\n\n if (!filter.clipToViewport)\n {\n clipToViewport = false;\n }\n\n const isCompatible = !!(filter.compatibleRenderers & renderer.type);\n\n if (!isCompatible)\n {\n enabled = false;\n break;\n }\n\n if (filter.blendRequired && !((renderer as WebGLRenderer).backBuffer?.useBackBuffer ?? true))\n {\n // #if _DEBUG\n // eslint-disable-next-line max-len\n warn('Blend filter requires backBuffer on WebGL renderer to be enabled. Set `useBackBuffer: true` in the renderer options.');\n // #endif\n\n enabled = false;\n break;\n }\n\n enabled = filter.enabled || enabled;\n blendRequired ||= filter.blendRequired;\n }\n\n // if no filters are enabled lets skip!\n if (!enabled)\n {\n filterData.skip = true;\n\n return;\n }\n\n // here we constrain the bounds to the viewport we will render too\n // this should not take into account the x, y offset of the viewport - as this is\n // handled by the viewport on the gpu.\n if (clipToViewport)\n {\n bounds.fitBounds(0, viewPort.width / rootResolution, 0, viewPort.height / rootResolution);\n }\n\n // round the bounds to the nearest pixel\n bounds\n .scale(resolution)\n .ceil()\n .scale(1 / resolution)\n .pad((padding | 0) * paddingMultiplier);\n\n // skip if the bounds are negative or zero as this means they are\n // not visible on the screen\n if (!bounds.isPositive)\n {\n filterData.skip = true;\n\n return;\n }\n\n // set the global frame to the root texture\n\n // get previous bounds.. we must take into account skipped filters also..\n\n // // to find the previous resolution we need to account for the skipped filters\n // // the following will find the last non skipped filter...\n\n // store the values that will be used to apply the filters\n filterData.antialias = antialias;\n filterData.resolution = resolution;\n filterData.blendRequired = blendRequired;\n }\n\n private _popFilterData(): FilterData\n {\n this._filterStackIndex--;\n\n return this._filterStack[this._filterStackIndex];\n }\n\n private _getPreviousFilterData(): FilterData | null\n {\n let previousFilterData: FilterData;\n\n let index = this._filterStackIndex - 1;\n\n while (index > 1)\n {\n index--;\n previousFilterData = this._filterStack[index];\n\n if (!previousFilterData.skip)\n {\n break;\n }\n }\n\n return previousFilterData;\n }\n\n private _pushFilterData(): FilterData\n {\n let filterData = this._filterStack[this._filterStackIndex];\n\n if (!filterData)\n {\n filterData = this._filterStack[this._filterStackIndex] = new FilterData();\n }\n\n this._filterStackIndex++;\n\n return filterData;\n }\n}\n\n"],"names":[],"mappings":"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"}