Apply Multiple Filters in Pixi.js

In Pixi.js, applying multiple visual effects to a single display object—such as a Sprite, Container, or Graphics object—is achieved by assigning an array of filter instances to the object’s filters property. This article explains how to instantiate, combine, and order multiple filters (like Blur, ColorMatrix, or custom shaders) to create complex visual styles in your WebGL applications, alongside essential performance considerations for filter stacking.

The filters Property

Every display object in Pixi.js inherits from PIXI.Container, which contains a filters property. By default, this property is set to null. To apply filters, you assign an array containing one or more filter instances to this property.

Pixi.js processes these filters sequentially. The output of the first filter in the array is passed as the input to the second, and so on, until the final filtered image is rendered to the screen.

Step-by-Step Implementation

Here is a direct example of how to instantiate and stack a blur filter and a color matrix filter onto a single sprite.

1. Instantiate the Filters

First, create the individual filter instances you want to use. You can configure their properties during or after instantiation.

// Create a Blur Filter and set its strength
const blurFilter = new PIXI.filters.BlurFilter();
blurFilter.blur = 5;

// Create a Color Matrix Filter and apply a grayscale effect
const grayFilter = new PIXI.filters.ColorMatrixFilter();
grayFilter.greyscale(0.8);

2. Apply the Filters Array to the Display Object

Assign the filters to your target display object’s filters property inside an array.

// Create your sprite or container
const sprite = PIXI.Sprite.from('path/to/image.png');

// Stack the filters by placing them in the array
sprite.filters = [blurFilter, grayFilter];

The Importance of Filter Order

Because Pixi.js executes filters in the order they are defined in the array, changing the sequence can drastically alter the final visual outcome.

Always order your array from the first effect you want applied to the last.

Dynamic Updates

You can modify the properties of active filters at any time. The rendering pipeline will automatically reflect these changes on the next frame.

// Dynamically adjust the blur strength in an animation loop
app.ticker.add(() => {
    blurFilter.blur = Math.sin(Date.now() * 0.005) * 10;
});

To remove all filters and restore the original appearance of the display object, simply reassign the property to null:

sprite.filters = null;

Performance Considerations

Stacking multiple filters requires Pixi.js to perform extra render passes behind the scenes. Each filter in the array typically draws the object to an off-screen texture before passing it to the next shader.

To maintain a high frame rate: * Limit the number of filters: Avoid stacking more than three or four complex filters on a single object. * Use padding wisely: If your filters cut off at the edges of the object, adjust the filter.padding property, but keep it as small as possible to save GPU memory. * Disable unused filters: Set filter.enabled = false instead of recreating arrays if you need to toggle effects on and off frequently.