$npx -y skills add pixijs/pixijs-skills --skill pixijs-filtersUse this skill when applying visual effects to PixiJS v8 containers via the filter pipeline. Covers built-in filters (AlphaFilter, BlurFilter, ColorMatrixFilter, DisplacementFilter, NoiseFilter), custom Filter.from() with GLSL/WGSL, options (resolution, padding, antialias, blendR
| 1 | Attach visual effects by assigning one filter (or an array for chaining) to `container.filters`. Built-in filters cover blur, color matrix, displacement, alpha, and noise; custom filters wrap a GLSL/WGSL fragment shader via `Filter.from(...)`. |
| 2 | |
| 3 | ## Quick Start |
| 4 | |
| 5 | ```ts |
| 6 | const sprite = new Sprite(await Assets.load("hero.png")); |
| 7 | app.stage.addChild(sprite); |
| 8 | |
| 9 | const blur = new BlurFilter({ strength: 4, quality: 4 }); |
| 10 | const colorMatrix = new ColorMatrixFilter(); |
| 11 | colorMatrix.brightness(1.2, false); |
| 12 | |
| 13 | sprite.filters = [blur, colorMatrix]; |
| 14 | |
| 15 | const container = new Container(); |
| 16 | container.filters = [new BlurFilter({ strength: 2 })]; |
| 17 | container.filterArea = new Rectangle(0, 0, 800, 600); |
| 18 | app.stage.addChild(container); |
| 19 | ``` |
| 20 | |
| 21 | **Related skills:** `pixijs-custom-rendering` (shader internals, uniform types), `pixijs-blend-modes` (composing with filters), `pixijs-performance` (filter tuning, filterArea). |
| 22 | |
| 23 | ## Core Patterns |
| 24 | |
| 25 | ### Built-in filters |
| 26 | |
| 27 | ```ts |
| 28 | import { |
| 29 | AlphaFilter, |
| 30 | BlurFilter, |
| 31 | ColorMatrixFilter, |
| 32 | DisplacementFilter, |
| 33 | NoiseFilter, |
| 34 | Assets, |
| 35 | Sprite, |
| 36 | } from "pixi.js"; |
| 37 | |
| 38 | // Alpha (uniform transparency without per-child layering) |
| 39 | const alpha = new AlphaFilter({ alpha: 0.5 }); |
| 40 | |
| 41 | // Blur — strength/quality are uniform; strengthX/strengthY split axes; |
| 42 | // kernelSize must be odd (5, 7, 9, ... 15); repeatEdgePixels avoids transparent edges |
| 43 | const blur = new BlurFilter({ |
| 44 | strength: 4, |
| 45 | quality: 4, |
| 46 | kernelSize: 5, |
| 47 | repeatEdgePixels: false, |
| 48 | }); |
| 49 | |
| 50 | // Color matrix — brightness is one of many presets. Others: tint, hue, |
| 51 | // contrast, saturate, desaturate, greyscale/grayscale, blackAndWhite, |
| 52 | // negative, sepia, technicolor, polaroid, kodachrome, browni, vintage, |
| 53 | // colorTone, night, predator, lsd, reset. Direct access via |
| 54 | // `colorMatrix.matrix` (20-element array) and `colorMatrix.alpha` (blend |
| 55 | // between original and transformed). |
| 56 | const colorMatrix = new ColorMatrixFilter(); |
| 57 | colorMatrix.brightness(1.5, false); |
| 58 | colorMatrix.contrast(0.5, true); // multiply stacks on top of existing matrix |
| 59 | colorMatrix.alpha = 0.7; // blend at 70% strength |
| 60 | |
| 61 | // Displacement — scale is a number or PointData |
| 62 | const displacementTexture = await Assets.load("displacement_map.png"); |
| 63 | const displacementSprite = new Sprite(displacementTexture); |
| 64 | const displacement = new DisplacementFilter({ |
| 65 | sprite: displacementSprite, |
| 66 | scale: { x: 20, y: 10 }, |
| 67 | }); |
| 68 | |
| 69 | // Noise — seed is an arbitrary number that determines the noise pattern; same seed reproduces the same pattern |
| 70 | const noise = new NoiseFilter({ noise: 0.5, seed: Math.random() }); |
| 71 | |
| 72 | sprite.filters = [blur, colorMatrix]; |
| 73 | ``` |
| 74 | |
| 75 | ### Custom filter with Filter.from() |
| 76 | |
| 77 | The simplest way to create a custom filter. Only a fragment shader is needed; PixiJS provides a default vertex shader. |
| 78 | |
| 79 | ```ts |
| 80 | import { Filter } from "pixi.js"; |
| 81 | |
| 82 | const filter = Filter.from({ |
| 83 | gl: { |
| 84 | fragment: ` |
| 85 | in vec2 vTextureCoord; |
| 86 | out vec4 finalColor; |
| 87 | uniform sampler2D uTexture; |
| 88 | uniform float uTime; |
| 89 | |
| 90 | void main() { |
| 91 | vec2 uv = vTextureCoord; |
| 92 | uv.x += sin(uv.y * 10.0 + uTime) * 0.02; |
| 93 | finalColor = texture(uTexture, uv); |
| 94 | } |
| 95 | `, |
| 96 | }, |
| 97 | resources: { |
| 98 | timeUniforms: { |
| 99 | uTime: { value: 0, type: "f32" }, |
| 100 | }, |
| 101 | }, |
| 102 | }); |
| 103 | |
| 104 | sprite.filters = filter; |
| 105 | |
| 106 | app.ticker.add((ticker) => { |
| 107 | filter.resources.timeUniforms.uniforms.uTime += 0.04 * ticker.deltaTime; |
| 108 | }); |
| 109 | ``` |
| 110 | |
| 111 | For more control, construct `GlProgram`/`GpuProgram` objects directly: |
| 112 | |
| 113 | ```ts |
| 114 | import { Filter, GlProgram } from "pixi.js"; |
| 115 | |
| 116 | const glProgram = GlProgram.from({ fragment: fragmentSrc, vertex: vertexSrc }); |
| 117 | |
| 118 | const filter = new Filter({ |
| 119 | glProgram, |
| 120 | resources: { |
| 121 | timeUniforms: { |
| 122 | uTime: { value: 0, type: "f32" }, |
| 123 | }, |
| 124 | }, |
| 125 | }); |
| 126 | ``` |
| 127 | |
| 128 | Key points: |
| 129 | |
| 130 | - Use `out vec4 finalColor` in fragment shaders, not `gl_FragColor` (GLSL ES 3.0). |
| 131 | - Use `texture()` to sample, not `texture2D`. |
| 132 | - `glProgram` for WebGL, `gpuProgram` for WebGPU. Omitting one skips that renderer. |
| 133 | - Textures go in `resources`, not uniforms. The filter system auto-provides `uTexture` (the input). |
| 134 | - Access uniform values via `filter.resources.{groupName}.uniforms.{name}`. |
| 135 | |
| 136 | ### Filter options |
| 137 | |
| 138 | ```ts |
| 139 | import { Filter, GlProgram, Rectangle } from "pixi.js"; |
| 140 | |
| 141 | const filter = new Filter({ |
| 142 | glProgram: GlProgram.from({ fragment }), |
| 143 | resources: {}, |
| 144 | resolution: 0.5, // default 1. Lower = faster, blurrier. 'inherit' matches the render target resolution |
| 145 | padding: 10, // default 0. Extra pixels for e |