WebGL Particle Engine for JavaScript – Quartz Particles

Category: Animation , Javascript | November 10, 2026
AuthorSharkPool-SP
Last UpdateNovember 10, 2026
LicenseMIT
Views0 views
WebGL Particle Engine for JavaScript – Quartz Particles

Quartz Particles is a JavaScript particle engine that renders textured effects on a WebGL canvas.

It supports multiple emitters, custom particle textures, and controls for movement, size, color, and lifetime.

Features

  • Emission rates and particle-count limits for each emitter.
  • Random variation in spawn position, speed, and direction.
  • Gravity, radial and tangential acceleration, and wave motion.
  • Size, rotation, stretch, fade, and RGB color transitions.
  • Support for existing canvases and engine-created canvases.

How To Use It

Installation

Import Quartz Particles as an ES module, using the hosted file below or a local copy from the GitHub repository. It imports TWGL 4 from a CDN and uses structuredClone() for default emitter settings.

Basic Usage

Initialize the engine on a canvas and create an emitter. An emitter created with no image URL uses the built-in white-square texture.

<canvas id="particles" width="640" height="360"></canvas>
<script type="module">
  import QuartzParticles from "https://cdn.jsdelivr.net/gh/SharkPool-SP/Quartz-Particles/src/lib/quartz-particles.min.js";
  const engine = new QuartzParticles();
  engine.initializeFromCanvas(document.getElementById("particles"));
  engine.createEmitter("spark");
  function animate() {
    engine.updateEngine();
    animationId = requestAnimationFrame(animate);
  }
  let animationId = requestAnimationFrame(animate);
</script>

Let The Engine Create A Canvas

initialize() creates the canvas and accepts its width and height. Append the canvas to the document and use the same emitter and update methods shown above.

const secondEngine = new QuartzParticles();
secondEngine.initialize({ width: 640, height: 360 });
document.body.appendChild(secondEngine.engine.canvas);
secondEngine.createEmitter("second");

Customize An Emitter

Change an emitter’s opts to adjust a few settings. Each property uses val for its base value and inf for the random offset applied when a particle spawns.

const options = engine.emitters.get("spark").opts;
options.maxP.val = 120;
options.emission.val = 3;
options.speed = { val: 18, inf: 6 };
options.sCol.val = [255, 190, 60];
options.eCol.val = [255, 40, 30];

Use A Custom Particle Texture

Pass an image URL as the third argument. You can also supply { texture, tWidth, tHeight } with a WebGLTexture created in the engine’s WebGL context and numeric texture dimensions. Images on another origin need CORS access.

engine.createEmitter("glow", [100, -40], "/images/glow.png");

Emitter Configuration Reference

These are the default emitter settings when you omit the fourth argument to createEmitter().

OptionDefault and purpose
maxP{ val: 50, inf: 0 }. Particle-count threshold for spawning. An emission batch can exceed it.
emission{ val: 1, inf: 0 }. Particles emitted per update frame.
time{ val: 0.4, inf: 0.1 }. Lifetime value, reduced by 0.01 per update when delta is 1.
speed{ val: 15, inf: 0 }. Initial speed.
xPos{ val: 10, inf: 0 }. Horizontal spawn offset.
yPos{ val: 0, inf: 0 }. Vertical spawn offset.
gravX{ val: 0, inf: 0 }. Horizontal gravity.
gravY{ val: -1.5, inf: 0 }. Vertical gravity.
sDir{ val: 0, inf: 25 }. Starting direction in degrees.
eDir{ val: 0, inf: 0 }. Direction at the end of the lifetime.
sSpin{ val: 0, inf: 0 }. Starting rotation in degrees.
eSpin{ val: 45, inf: 135 }. Ending rotation in degrees.
sSize{ val: 25, inf: 10 }. Starting size as a percentage of texture dimensions.
eSize{ val: 15, inf: 5 }. Ending size as a percentage of texture dimensions.
sStreX{ val: 100, inf: 0 }. Starting horizontal stretch, percent.
eStreX{ val: 100, inf: 0 }. Ending horizontal stretch, percent.
sStreY{ val: 100, inf: 0 }. Starting vertical stretch, percent.
eStreY{ val: 100, inf: 0 }. Ending vertical stretch, percent.
accelRad{ val: 0, inf: 0 }. Radial acceleration.
accelTan{ val: 0, inf: 0 }. Tangential acceleration.
sinW{ val: 0, inf: 0 }. Sine-wave displacement strength.
cosW{ val: 0, inf: 0 }. Cosine-wave displacement strength.
sinS{ val: 1, inf: 0 }. Sine-wave frequency.
cosS{ val: 1, inf: 0 }. Cosine-wave frequency.
fIn{ val: 0, inf: 5 }. Fade-in interval in update ticks.
fOut{ val: 15, inf: 2 }. Fade-out interval in update ticks.
sCol{ val: [255, 0, 255], inf: 0 }. Starting RGB color.
eCol{ val: [0, 0, 255], inf: 0 }. Ending RGB color.

Engine Initialization And Methods

MethodPurpose
new QuartzParticles()Creates an engine instance. Call an initialization method before creating emitters.
initialize(scale)Creates a canvas and initializes rendering. scale supplies width and height. Default: 480 × 360.
initializeFromCanvas(canvas, optScale)Initializes rendering on the supplied canvas. Optional optScale sets its width and height. By default, the canvas dimensions are used.
createEmitter(name, position, texturePath, options)Creates a named emitter. Position defaults to [0, 0]. Texture accepts an image URL or { texture, tWidth, tHeight }. A supplied options object replaces the defaults and must include every configuration key.
updateEngine(delta)Advances and renders a frame. delta is a frame multiplier, default 1.
resetEngineFlow()Resets emitter frame counters. Existing particles are retained.
disposeEmitter(name)Removes a named emitter and deletes its loaded texture.
disposeEngine()Releases engine resources, removes the canvas, and clears the emitters map.

Cleanup

Stop the animation loop before calling disposeEngine(). It also removes the canvas passed through initializeFromCanvas().

cancelAnimationFrame(animationId);
engine.disposeEngine();

Alternatives And Related Resources

You Might Be Interested In:


Leave a Reply