pixi-shader-effect
v0.1.5
Published
Manifest-driven PIXI.js mesh shader player that follows display objects
Readme
pixi-shader-effect
Manifest-driven PIXI.js mesh shader player. Attach animated GLSL effects to display objects, drive uniforms from a JSON manifest, and let the effect follow targets as the scene moves or resizes.
Peer dependency: pixi.js ^7.4.0 (your app must install it).
Install
npm install pixi-shader-effect pixi.jsQuick start
import { ShaderEffect } from 'pixi-shader-effect';
import manifest from './myEffect.json';
import fragShader from './myEffect.frag.js';
const effect = new ShaderEffect({
manifest,
fragShader,
getSize: () => ({ width: app.renderer.width, height: app.renderer.height }),
getTarget: () => mySprite,
zIndex: 3,
});
effect.resize(); // attach, build meshes, start tickerOn window resize:
effect.resize();On teardown:
effect.destroy();What you provide
This package is the player only. It does not ship shader presets. You pass in:
| You provide | Format |
|-------------|--------|
| manifest | JSON with a shader layer and shaderSettings |
| fragShader | GLSL source string (e.g. export default from a .js file) |
The manifest and fragment shader must match — same effect type and uniforms. For example, a manifest with "shaderLayerDistortionType": "lava-crack" expects a lava-crack GLSL shader that declares uniforms like lavaColor, crackScale, etc.
Manifest keys like shaderLayerGlowColor map to GLSL uniforms (glowColor). Hex colors are converted to vec3 RGB automatically.
Manifest
The manifest is a JSON object with at least one visible shader layer:
{
"name": "My Effect",
"layers": [
{
"type": "shader",
"visible": true,
"shaderSettings": {
"shaderRectWidth": 200,
"shaderRectHeight": 100,
"shaderLayerGlowSpread": 0.02,
"shaderLayerGlowColor": "#ffad1f",
"shaderLayerFlowSpeed": 0.5
}
}
]
}Lifecycle
Typical integration pattern:
// 1. Create (does not render until resize/start)
const effect = new ShaderEffect({ manifest, fragShader, getSize, getTarget, zIndex: 3 });
// 2. Attach + build meshes + start ticker
effect.resize();
// 3. Call again on window resize or when layout changes
effect.resize();
// 4. Clean up when removing the effect
effect.destroy();getTarget is always required, even for background or fixed-position layouts — return the display object whose parent should host the effect (or use the parent option to attach elsewhere).
resize() is idempotent: safe to call on init and on every layout pass. Use destroy() before discarding; call stop() only if you want to halt updates but keep the instance.
The effect exposes effect.container (a PIXI Container) if you need direct access to the display object tree.
Settings overrides
Override manifest values at construction or at runtime. Overrides use the same keys as shaderSettings and always win over the manifest.
At construction — pass settings to replace or tweak manifest defaults:
const effect = new ShaderEffect({
manifest,
fragShader,
getSize: () => ({ width: app.renderer.width, height: app.renderer.height }),
getTarget: () => mySprite,
settings: {
shaderLayerGlowColor: '#ff0000',
shaderLayerFlowSpeed: 1.2,
shaderLayerGlowSpread: 0.05,
},
});At runtime — call setSettings() to merge new values and refresh layout/uniforms:
// dim the glow
effect.setSettings({ shaderLayerGlowIntensity: 0.5 });
// switch palette on a state change
effect.setSettings({
shaderLayerGlowColor: '#00ccff',
shaderLayerCoreColor: '#ffffff',
});Animate with GSAP
GSAP is not a dependency of this package. Tween a plain object and call setSettings() on each update to push manifest values into the shader:
import gsap from 'gsap';
import { ShaderEffect } from 'pixi-shader-effect';
const effect = new ShaderEffect({ manifest, fragShader, getSize, getTarget });
effect.resize();
const tweenState = {
shaderLayerGlowIntensity: 1.25,
shaderLayerFlowSpeed: 0.5,
};
gsap.to(tweenState, {
shaderLayerGlowIntensity: 2,
shaderLayerFlowSpeed: 1.5,
duration: 0.8,
ease: 'power2.out',
onUpdate: () => effect.setSettings(tweenState),
});Pulse loop:
gsap.to(tweenState, {
shaderLayerGlowIntensity: 2,
duration: 1,
yoyo: true,
repeat: -1,
ease: 'sine.inOut',
onUpdate: () => effect.setSettings(tweenState),
});Fade opacity — alpha lives on the effect instance (not manifest); the ticker picks it up each frame:
effect.alpha = 0;
gsap.to(effect, {
alpha: 1,
duration: 0.6,
ease: 'power2.out',
});Speed up / slow down the built-in time uniform the same way via timeScale:
gsap.to(effect, { timeScale: 0, duration: 0.5 }); // freeze
gsap.to(effect, { timeScale: 1, duration: 0.5 }); // resume normal speedConstructor options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| manifest | yes | — | Shader manifest JSON |
| fragShader | yes | — | Fragment shader GLSL source |
| getSize | yes | — | () => ({ width, height }) screen size |
| getTarget | yes | — | () => displayObject object to follow |
| parent | no | target's parent | Fixed container to render into |
| getTargetSize | no | target bounds | () => ({ width, height }) override |
| settings | no | {} | Runtime overrides (win over manifest) |
| shaderScale | no | 1 | Geometry size multiplier |
| pixiScale | no | 1 | Mesh transform scale |
| anchor | no | { x: 0.5, y: 0.5 } | Follow point on target (0–1) |
| outlineAlign | no | 1 | Outline stroke: 0 outside, 0.5 center, 1 inside |
| strokeAlign | no | — | Alias for outlineAlign |
| alpha | no | 1 | Opacity multiplier |
| time | no | 1 | Animation speed (1 = real time) |
| blendMode | no | add | normal, add, multiply, screen, or PIXI constant |
| zIndex | no | 1 | Draw order in parent |
| fps | no | 0 | Update cap (0 = every frame) |
| name | no | 'ShaderEffect' | Debug name on container |
Methods
resize()— Re-attach if needed, refresh layout and geometry.start()— Start ticker updates (also called viaresize()when not running).setSettings(settings)— Merge runtime settings and refresh layout.stop()— Stop ticker and destroy meshes.destroy()— Full cleanup (call when removing the effect).
Layout modes
- Follow target — Default when
getTarget()returns a sized display object. - Background — Set
shaderSourceType: "background"in manifest settings for full-screen. - Fixed position — Use
shaderRectWidth/shaderRectHeightand optionalemitterX/emitterY(percent) when no target layout applies. - Rect outline — Set
shaderRectMode: "outline"andshaderRectAsLines: truefor four-edge stroke rendering.
Advanced exports
Lower-level uniform helpers are also exported:
import {
ShaderEffect,
syncUniforms,
resolveSettings,
parseFragUniforms,
hexToRgb,
} from 'pixi-shader-effect';License
MIT
