Pylinka
A GPU-driven, node-based particle system for PixiJS. Wire a typed dataflow graph, and it compiles to GPU programs — particles live and update entirely on the GPU. WebGPU first, WebGL2 fallback, built for slot games on real phones.
Why Pylinka
- The GPU owns the particles. State lives in GPU buffers and never round-trips to the CPU while running. Per frame, per system: one emit pass, one update pass, one instanced draw.
- Every number is live. Inline values are lowered to uniforms, so changing any value updates the running effect on the next frame — no recompile. Promote any value to a named knob your game drives at runtime.
- A typed dataflow graph. Connect nodes like
shape.point,field.gravity,gen.colorOverLifeandoutput.writeColor. The graph compiles to a backend-neutral IR, then to WGSL or GLSL. - Backend follows the host. A PixiJS WebGL app gets the WebGL2 simulation in the same GL context; a WebGPU app shares the device. Particles interleave correctly with your scene — behind symbols, above the background.
A trail in a few lines
Attach a particle system to a static VFX layer and let a moving target drive the emitter:
import { createPylinka } from '@pylinka/core';
import project from './coin-spark-trail.pylinka.json';
const pylinka = await createPylinka(project, { renderer });
vfxLayer.addChild(pylinka.systems.sparks.view);
// follow a flying coin — sparks hang and fade in world space
pylinka.systems.sparks.follow(coinSprite);
// live knob, no recompile
pylinka.params.set('windPower', 40);
app.ticker.add((t) => pylinka.update(t.deltaMS / 1000)); Scope
Pylinka is 2D only — simulation state is vec2; there is no vec3. It is a
particle compiler, not a general GPGPU framework, and has no physics solver: analytic force
fields and simple bounds only. See Core concepts for the model, and the
node reference for what you can wire.
New here? Start with Getting started, then skim Core concepts.