Skip to content

Point Emitter ​

Turns a points or shape source into births over time. Every frame it outputs only the particles born on that frame — each with a lifespan and an initial velocity. Feed a Point Solver inside a Solver to keep them alive and moving.

Category: Points Menu path: Points > Point Emitter

Ports ​

PortTypeDirectionDescription
sourcepoints (a shape connects too)inputEmission sites. Points: every point is a site and each birth picks one. Shape: emitFrom chooses Fill / Path / Points. Disconnected: a single site at the comp centre — the menu item alone gives you a fountain.
velocity_invectorFieldinputPer-birth initial velocity, sampled at the birth position. Only read when velocityMode is Field.
density_inscalarFieldinputOptional. Where births appear, as a 0–1 field read at each candidate site — an image's luminance through ImageSample, a Noise or Gradient field, a DistanceField. Fill: a candidate is kept with probability = the field there (rejection sampling). A points source, or Points: the site pick is weighted by the field at each site. Path: weighted along the outline. Never changes how many particles are born. Unwired: the plain emitter. See Density.
outpointsoutputThe births of the current frame only — see the output contract below. Each birth carries velocity (px per frame), age (its sub-frame birth offset, 0–1), life (frames) and, with Inherit Attributes on, the site's own attributes.

Parameters ​

ParamTypeDefaultDescription
emitFromenumFillWhere on a shape source births appear: Fill (inside the shape), Path (along the outline), Points (at its vertices). Shown only while a shape is wired to source — a points source has no fill or outline to choose from, so the row hides (swapping a Grid in for a shape used to leave it behind).
ratescalar, keyframeable30Births per second. Keyframed rates integrate exactly — the number born by frame f is the running integral of the rate curve, so ramping the rate never drops or doubles a birth.
burstscalar, keyframeable0Shot size, in particles, outside the rate integral. Rate is a flow measured per second; Burst is a shot of N fired on a schedule.
burstOn (UI: "Burst On")enumSourceThe schedule. Source — whenever the source has sites to fire from. Start — once, on the simulation's first frame. Every Nth — every burstEvery frames. See Burst.
burstEvery (UI: "Every")scalar, keyframeable15Interval in frames for Every Nth, counted from the layer start so the rhythm survives moving the clip.
lifescalar, keyframeable60Lifespan in frames. The solver removes a particle when its age reaches its life.
lifeVariationscalar00–1 fraction. Each birth's life is life × (1 ± lifeVariation × random), so 0.5 means anywhere from half to one-and-a-half the base life.
velocityModeenumDirectionHow each birth gets its starting velocity. Direction — a cone around direction, spread wide. Outward — away from the source, in all three of its shapes: along the outward normal on a Path source, away from the centre for a spread-out cloud, and in every direction from a single point (a died stream is usually one death at a time, so this is the firework). Field — sample velocity_in at the birth position. Inherit — inheritVelocity × the site's own velocity attribute, plus the same direction cone, so a spark can carry its parent's momentum and still scatter.
speedscalar, keyframeable200Starting speed in px per second. In Inherit mode this is the burst added on top of the inherited velocity — set it to 0 for pure inheritance.
speedVariationscalar00–1 fraction, same rule as Life Variation.
directionscalar, keyframeable−90Direction mode only. Degrees in y-down comp space: −90 is straight up, 0 is right, 90 is down.
spreadscalar, keyframeable30Direction and Inherit modes. Total cone width in degrees (30 = ±15° around direction; 360 = every direction, which is the one you want for embers).
inheritVelocity (UI: "Carry Over")scalar, keyframeable1Inherit mode. How much of the site's own velocity a birth keeps, 0–1. 1 carries the parent's momentum in full, 0 drops it and leaves only the burst. Distinct from inheritMotion, which is about the emitter moving.
inheritMotionscalar, keyframeable0.20–1. When the source itself moves (a shape or points pushed by an upstream Transform2D, tracked points, another solver's particles), this fraction of the emitter's own velocity is added to every birth's starting velocity. 1 = births leave at full emitter speed, like water from a moving hose; 0 = births ignore the emitter's motion. See Moving emitters.
subFramePositioningbooleanonSpread a frame's births along the path the emission site travelled during that frame instead of stacking them all at its current position. A fast-moving emitter then draws a continuous stream rather than one clump per frame. No effect on a static source.
seedscalar0Random seed for site choice, life/speed jitter, direction jitter and sub-frame timing.
inheritAttributesbooleanonCopy the chosen site's attributes onto each birth — color from a coloured Grid, glyphIndex from TextToPoints, scale from PointAttributes. Off: births carry only velocity, age, life.

Formerly Boundary / Vertices. Emit From's Path and Points were called Boundary and Vertices before September 2026 — older tutorials mean the same thing, and saved projects pick up the new names on load.

Expose Channels ​

When enabled (E button on node header), adds input ports that override params via edge connections:

PortTypeOverrides
burst_inscalarburst
rate_inscalarrate
life_inscalarlife
speed_inscalarspeed (absent in Inherit mode)
direction_inscalardirection (Direction mode only)
spread_inscalarspread (Direction mode only)
inheritMotion_inscalarinheritMotion
seed_inscalarseed

The mode-dependent ports come and go with velocityMode: switching to Outward removes direction_in / spread_in (and any edge into them) because the engine no longer reads those params. Switch back and the ports return — the edges do not.

How It Works ​

Output contract — births this frame. The emitter is stateless. Its output at frame f is exactly the set of particles born on frame f: nothing from earlier frames, nothing that will be born later. It has no memory and does no motion. Wired straight to DrawPoints you see a thin spray that is replaced every frame — occasionally useful (a flicker of new sparks), but normally the emitter feeds a Point Solver's emit port inside a Solver, and the Solver keeps the population from there. Two consecutive frames' births are different particles; the ids on the emitter's output are local and meaningless — the solver assigns the real, stable @id on ingestion.

Births per frame. With rate in births per second and the comp at fps, the number born on frame f is floor(C(f)) − floor(C(f − 1)), where C is the cumulative integral of rate / fps from the simulation start. A constant 30/s at 30 fps is one birth per frame; 45/s alternates one and two; a keyframed ramp integrates exactly. burst adds to the first frame.

Each birth gets a site (a point of the source, or a sample of the shape per emitFrom), a life (life with lifeVariation), a velocity per velocityMode (speed with speedVariation), and a uniform sub-frame offset within the frame so high rates produce a smooth stream instead of beads on a string. The solver pre-integrates that offset.

Moving emitters. When the source itself moves — a shape or points carried by an upstream Transform2D, tracked features, another solver's particles — the emitter looks at where each emission site was one frame earlier and does two things with that motion:

  • Inherit Motion adds inheritMotion × the site's own velocity (its displacement over that frame, in px per frame) to every birth's starting velocity, on top of whatever velocityMode produced. At the default 0.2 a fast pan gives the stream a gentle drift in the emitter's direction; at 1.0 births fly off at the emitter's full speed, like sparks off a grinder or water from a swung hose; at 0 they ignore the emitter entirely.
  • Sub-frame Positioning places each birth at the point along the site's path that matches its sub-frame offset (lerp(previous, current, u)), so a frame's births are spread along the distance the site travelled instead of appearing as one clump per frame. The solver's usual sub-frame pre-integration then carries them forward from there. The result is a continuous ribbon behind a fast-moving emitter rather than beads.

How a site is matched to its previous position: a points source matches by point id (a point that did not exist last frame gets no motion); a shape source re-samples the previous outline with the same per-birth randoms — the same vertex, the same arc-length fraction along the boundary, the same fill sample — so under translation and scaling the correspondence is exact; under rotation a fill sample's match is bounded by how much the shape's bounding box changed that frame and falls back to the shape's overall (bounding-box centre) motion when it cannot be established. With a static source both features are exact no-ops: the births are bit-for-bit what they would be with the features off. The previous frame is not consulted on the layer's first frame (or during a solver Pre-Roll, which runs before it), so those births carry no inherited motion.

Density. With a field on density_in, each birth's site is chosen through the field (clamped to 0–1): a points source or Points picks each site with probability proportional to the field value there; Path spreads births along the outline in proportion to the field (sampled every ~2 px of arc); Fill draws a candidate inside the shape and keeps it with probability equal to the field there, trying up to 64 candidates per birth — if none passes (a black region, a black image) the last candidate that was inside the shape is used, so the emitter never stalls and still births its rate. A field that is flat everywhere (or entirely zero on a points source or a Points / Path shape source) behaves exactly like no field. The density is read at the site, before Sub-frame Positioning moves the birth along the site's path.

Deterministic. Every random draw for a birth is a hash of seed and that birth's global index, so the births at frame f are a pure function of (f, params, source at f and at f − 1). Scrubbing, exporting, and rebuilding a solver's history all reproduce the same births. The simulation clock is layer time — slide the clip and the particles slide with it.

Usage Examples ​

Basic: Fountain ​

Choose Points > Point Emitter with auto-wire on. You get PointEmitter → [Solver In → PointSolver → Solver Out] → DrawPoints → Output and a stream of white dots rising from the comp centre. On the solver set gravity to (0, 800): the stream arcs and falls. On the emitter try spread 20, speed 600, life 90.

Emit from text ​

Text → TextToShape → PointEmitter (emitFrom: Path, velocityMode: Outward, speed: 60) feeding a particle system. Particles peel off the letter outlines. Use Fill to boil the letters from inside, or TextToPoints on source to emit one stream per glyph.

Emit where an image is bright ​

ImageSource → ImageSample (channel: Luminance, coord space: Comp) → PointEmitter.density_in, with a Rectangle the size of the image on source (emitFrom: Fill). Births appear in proportion to brightness — dense in the highlights, none in the black — and follow the image frame by frame (a video works the same way). Invert the image upstream to emit from the shadows instead; a Remap or Threshold between ImageSample and the emitter reshapes the response. The same port on Point Scatter gives the static version.

Without the port you can approximate a hard-edged version with existing nodes — Grid (dense) → PointDelete (mask_in: the field, Compare: Less Than 0.5) → PointEmitter.source — but that is a binary cutoff at grid resolution, not a density: a 60 % grey region is either all in or all out, births sit on the grid lattice, and it needs a Random + FieldMath pair on top to fake grey levels. Use density_in.

Sparks off particles (Inherit) ​

Take an existing particle system A and connect its Solver Out to a second emitter's source, with velocityMode: Inherit, rate 300, life 10, inheritAttributes on. Give that emitter its own particle system B (a second Solver) drawn with a small DrawPoints. Every live particle of A now sheds short-lived sparks that start with A's velocity and colour. Merge both DrawPoints, or put them on separate layers.

Give the sparks motion of their own. On its own, Inherit hands each spark its parent's velocity and nothing else, so the sparks simply fly along with it. Raise speed and set spread to 360 and each birth gets a burst in a random direction on top; lower inheritVelocity to let go of the parent's momentum. speed 0 with inheritVelocity 1 is pure inheritance, speed 400 with inheritVelocity 0 is an omnidirectional pop that ignores the parent entirely.

Burst where a particle dies ​

PointSolver.died → PointEmitter.source, velocityMode: Inherit, spread 360, speed 400, inheritVelocity around 0.3, feeding a second Point Solver in the same Solver (see Embers on impact for the wiring). Each particle that dies throws a short-lived puff of sparks that keeps a little of its momentum and scatters the rest. Filter by cause with a downstream Apply To of diedOnCollision for impacts only.

Size over life ​

… → Solver Out → PointAttributes (target: Scale, source: Age, Curve: 1 → 0) → DrawPoints. Age normalises each particle's age by its own life, so every dot shrinks to nothing exactly as it dies. Use target Opacity for a fade, or Color with a ramp for a hot-to-cold colour change.

Trails ​

Solver Out → PointTrail (trailLength 20, fade 1) → DrawShape (stroke only). Ids are stable from birth to death, so each particle drags its own trail, and the trail leaves with it.

Bounce inside the comp ​

On the solver: boundary: Bounce, bounce 0.6, gravity (0, 1200). Particles drop, bounce off the bottom edge and settle. Wrap sends what leaves one side back in on the other; Kill removes anything that exits.

A burst on every beat ​

Audio Source.amplitude → Trigger (Rising, output 200) → Point Emitter.burst_in, with rate at 0. Two hundred particles are born on the frame the track crosses the threshold, and none in between. Wire it through rate_in instead and you get a stream while the signal is loud, which is the other thing you might want.

Use Burst, not Rate: rate is integrated over the frame, so two hundred particles through Rate means typing a rate of six thousand.

Honest spray ​

PointEmitter → DrawPoints with rate 600: a fresh scatter of dots every frame, no persistence. Handy as a sparkle texture — everything else wants the solver.

Burst ​

Rate is a flow, Burst is a shot. Rate is measured per second and integrates exactly across a keyframed curve; Burst is a plain count of particles added on the frames its schedule fires.

The schedule is burstOn:

  • Source (default) fires on every frame — and an emitter whose Source is wired but empty births nothing, so this needs no configuration to mean "once per event". Feed it PointSolver.died and it bursts once per death. Feed it a static Grid and it bursts every frame, which is just a rate in disguise, so watch the Births readout.
  • Start fires once, on the simulation's first frame. The one-shot explosion: Rate 0, Burst 500, Burst On Start.
  • Every Nth fires every burstEvery frames, counted from the layer start so the rhythm moves with the clip rather than with the comp.

Driving it. burst_in overrides the count; the schedule still decides when. They compose with no special rule, so a driven count under Every Nth is a steady tempo of varying size, and a Trigger under Source decides the timing itself, because a driven count of zero is not a burst.

An Oscillate wired straight in gives a swell rather than a pulse, since a smoothly varying count is a smoothly varying number of particles per frame. For discrete shots put a Trigger between them. Oscillate's scalar sits around −1 to 1 by default, which as a count rounds to nothing, so set its Amplitude and Offset (250 and 250 gives a clean 0 to 500).

Readout ​

The emitter reports Births — how many particles it actually made this frame — on the node face and in Properties. The consequence of a count is otherwise invisible until the viewport stalls, since the only hard stop is a cap at a million births per frame. Flip Burst On to Source over a dense Grid and the number tells you immediately.

Tips ​

  • Rates are per second, durations are frames: at 30 fps, rate 30 with life 60 holds about 60 live particles at steady state (rate × life / fps).
  • Keyframe rate down to 0 to stop emitting — particles already alive keep going until their life runs out.
  • Animate the emitter with a geometry Transform2D between the source and the emitter (Grid → Transform2D → PointEmitter), not with a texture transform after DrawPoints — only then does the emitter see the motion that Inherit Motion and Sub-frame Positioning use. Trailing sparks: inheritMotion 1, spread 180, a little drag on the solver.
  • Outward on a Circle with Emit From Path is a radial burst; on a Fill source it pushes away from the shape's centre; on a single point it scatters over the full circle, since every direction is outward from a point. It does not read direction or spread in any of those cases — that cone is what Direction is for.
  • Two emitters into one solver: MergePoints → emit. The solver re-ids on ingestion, so the merge is harmless there.
  • Anything that must follow one particle over time — trails, labels, a Select group — should read the Solver's output, never the emitter's: only the solver's @id is stable.
  • Per-particle randomness that stays fixed for a particle's whole life lives on PointAttributes (source: Random) or the @rand01 intrinsic, not on a Random field — a field is positional and changes as the particle moves.
  • Properties: Emit From appears only while a shape is wired to source; Speed hides in Inherit mode; Direction and Spread show only in Direction mode.