pixijs-filters

Use this skill when applying visual effects to PixiJS v8 containers via the filter pipeline. Covers built-in filters (AlphaFilter, BlurFilter,…

INSTALLATION
npx skills add https://github.com/pixijs/pixijs-skills --skill pixijs-filters
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

Related skills: pixijs-custom-rendering (shader internals, uniform types), pixijs-blend-modes (composing with filters), pixijs-performance (filter tuning, filterArea).

Core Patterns

Built-in filters

import {

  AlphaFilter,

  BlurFilter,

  ColorMatrixFilter,

  DisplacementFilter,

  NoiseFilter,

  Assets,

  Sprite,

} from "pixi.js";

// Alpha (uniform transparency without per-child layering)

const alpha = new AlphaFilter({ alpha: 0.5 });

// Blur — strength/quality are uniform; strengthX/strengthY split axes;

// kernelSize must be odd (5, 7, 9, ... 15); repeatEdgePixels avoids transparent edges

const blur = new BlurFilter({

  strength: 4,

  quality: 4,

  kernelSize: 5,

  repeatEdgePixels: false,

});

// Color matrix — brightness is one of many presets. Others: tint, hue,

// contrast, saturate, desaturate, greyscale/grayscale, blackAndWhite,

// negative, sepia, technicolor, polaroid, kodachrome, browni, vintage,

// colorTone, night, predator, lsd, reset. Direct access via

// `colorMatrix.matrix` (20-element array) and `colorMatrix.alpha` (blend

// between original and transformed).

const colorMatrix = new ColorMatrixFilter();

colorMatrix.brightness(1.5, false);

colorMatrix.contrast(0.5, true); // multiply stacks on top of existing matrix

colorMatrix.alpha = 0.7; // blend at 70% strength

// Displacement — scale is a number or PointData

const displacementTexture = await Assets.load("displacement_map.png");

const displacementSprite = new Sprite(displacementTexture);

const displacement = new DisplacementFilter({

  sprite: displacementSprite,

  scale: { x: 20, y: 10 },

});

// Noise — seed is an arbitrary number that determines the noise pattern; same seed reproduces the same pattern

const noise = new NoiseFilter({ noise: 0.5, seed: Math.random() });

sprite.filters = [blur, colorMatrix];

Custom filter with Filter.from()

The simplest way to create a custom filter. Only a fragment shader is needed; PixiJS provides a default vertex shader.

import { Filter } from "pixi.js";

const filter = Filter.from({

  gl: {

    fragment: `

            in vec2 vTextureCoord;

            out vec4 finalColor;

            uniform sampler2D uTexture;

            uniform float uTime;

            void main() {

                vec2 uv = vTextureCoord;

                uv.x += sin(uv.y * 10.0 + uTime) * 0.02;

                finalColor = texture(uTexture, uv);

            }

        `,

  },

  resources: {

    timeUniforms: {

      uTime: { value: 0, type: "f32" },

    },

  },

});

sprite.filters = filter;

app.ticker.add((ticker) => {

  filter.resources.timeUniforms.uniforms.uTime += 0.04 * ticker.deltaTime;

});

For more control, construct GlProgram/GpuProgram objects directly:

import { Filter, GlProgram } from "pixi.js";

const glProgram = GlProgram.from({ fragment: fragmentSrc, vertex: vertexSrc });

const filter = new Filter({

  glProgram,

  resources: {

    timeUniforms: {

      uTime: { value: 0, type: "f32" },

    },

  },

});

Key points:

  • Use out vec4 finalColor in fragment shaders, not gl_FragColor (GLSL ES 3.0).
  • Use texture() to sample, not texture2D.
  • glProgram for WebGL, gpuProgram for WebGPU. Omitting one skips that renderer.
  • Textures go in resources, not uniforms. The filter system auto-provides uTexture (the input).
  • Access uniform values via filter.resources.{groupName}.uniforms.{name}.

Filter options

import { Filter, GlProgram, Rectangle } from "pixi.js";

const filter = new Filter({

  glProgram: GlProgram.from({ fragment }),

  resources: {},

  resolution: 0.5, // default 1. Lower = faster, blurrier

  padding: 10, // default 0. Extra pixels for effects that extend bounds

  antialias: "off", // default 'off'. 'on' | 'off' | 'inherit'

  blendMode: "normal", // default 'normal'

  blendRequired: false, // default false. true if shader samples uBackTexture

  clipToViewport: true, // default true

});

// Optimization: set known bounds to avoid per-frame measurement

container.filterArea = new Rectangle(0, 0, 800, 600);

// Toggle without rebuilding the filter array

filter.enabled = false;

// Share one filter instance across many display objects

sprite1.filters = [filter];

sprite2.filters = [filter];

Community filters (pixi-filters)

import { AdjustmentFilter } from "pixi-filters/adjustment";

import { GlowFilter } from "pixi-filters/glow";

sprite.filters = [

  new AdjustmentFilter({ brightness: 1.2, contrast: 1.1 }),

  new GlowFilter({ distance: 15, outerStrength: 2 }),

];

For v8, community filters use pixi-filters/{name} imports, not the old @pixi/filter-* packages.

Advanced blend modes

Advanced blend modes (color-burn, overlay, hard-light, etc.) are powered by the filter system and must be imported before use. They also require useBackBuffer: true on WebGL; see the pixijs-blend-modes skill for the full list.

import "pixi.js/advanced-blend-modes";

await app.init({ useBackBuffer: true });

sprite.blendMode = "color-burn";

Common Mistakes

[CRITICAL] Using old Filter constructor (vertex, fragment, uniforms)

Wrong:

import { Filter } from "pixi.js";

const filter = new Filter(vertex, fragment, { uTime: 0 });

Correct:

import { Filter, GlProgram } from "pixi.js";

const filter = new Filter({

  glProgram: GlProgram.from({ fragment, vertex }),

  resources: {

    timeUniforms: { uTime: { value: 0, type: "f32" } },

  },

});

v8 uses an options object. Shaders must be wrapped in GlProgram.from() or GpuProgram.from(). Uniforms are grouped in resources with explicit types. Textures are resources, not uniforms.

[HIGH] Using @pixi/filter-* packages for v8

Wrong:

import { AdjustmentFilter } from "@pixi/filter-adjustment";

Correct:

import { AdjustmentFilter } from "pixi-filters/adjustment";

@pixi/filter-* packages are v7 only. For v8, the community filters package restructured to pixi-filters/{name}.

[HIGH] Using too many filters without containerizing

Each filter application requires a framebuffer switch, bounds measurement, and render-to-texture pass. One filter on a parent container is much cheaper than the same filter on each child.

Wrong:

for (const child of container.children) {

  child.filters = [new BlurFilter({ strength: 4 })];

}

Correct:

container.filters = [new BlurFilter({ strength: 4 })];

[HIGH] Using a blendRequired filter without useBackBuffer on WebGL

Custom filters and most advanced community filters that set blendRequired: true sample the back buffer. On WebGL that only works if the renderer was initialized with useBackBuffer: true; otherwise PixiJS logs a warning and the filter silently falls back:

await app.init({ useBackBuffer: true });

WebGPU enables the back buffer unconditionally, so this only affects WebGL.

[MEDIUM] Not setting filterArea for known-size containers

Without filterArea, PixiJS measures the container bounds every frame via getGlobalBounds(), which recursively walks all children. For containers with known dimensions, set filterArea to avoid this cost:

import { Rectangle } from "pixi.js";

container.filterArea = new Rectangle(0, 0, 800, 600);

container.filters = [someFilter];

API Reference

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card