Documentation
    Preparing search index...

    Interface ParticleEmitterOptions

    §36 emitter options, MVP tier. Every field except maxParticles is optional; the defaults are listed per field and are all constants, never clocks or Math.random (§33).

    Options are read once, in the constructor. Runtime re-authoring (emitter.emissionRate = 20) is staged (2026-08-02, WP-9.1): the derived cone basis, the burst schedule, and the emission accumulator would all need invalidation rules, and §36 gives none. Build a new emitter, or call ParticleEmitter.emit for one-off bursts.

    interface ParticleEmitterOptions {
        alignToVelocity?: boolean;
        bursts?: readonly ParticleBurst[];
        collisionPlaneY?: number;
        collisions?: ParticleCollisionMode;
        color?: ParticleLifetimeRamp<ParticleColor>;
        direction?: Vector3;
        emissionRate?: number;
        fields?: readonly ParticleForceField[];
        gravity?: Vector3;
        initialSpeed?: ParticleRange;
        lifetime?: ParticleRange;
        maxParticles: number;
        position?: Vector3;
        restitution?: number;
        seed?: number;
        simulation?: ParticleSimulationMode;
        size?: ParticleLifetimeRamp<number>;
        softness?: number;
        spreadAngle?: number;
        texture?: ParticleTexture;
        trail?: ParticleTrailOptions;
    }
    Index
    alignToVelocity?: boolean

    Rotate each billboard by atan2(vy, vx) of the particle's velocity (R-32). Default false. Opts into the wide instance stream.

    bursts?: readonly ParticleBurst[]

    One-shot bursts, each fired the first time emitter-local elapsed time reaches its time. Default none. Copied at construction; declaration order is the firing order within a step.

    collisionPlaneY?: number

    World y of an infinite horizontal collision plane, or omitted for no collision (§36 collision, MVP tier — see ParticleEmitter.collisionPlaneY).

    §36 collision mode. "depth-buffer" kills (CPU) or rests (GPU stub) particles below the ground y — collisionPlaneY, or 0. Default "none" (the existing collisionPlaneY bounce still applies on CPU when that field is set and this is omitted).

    Straight RGBA at age 0 and at age = lifetime, linearly interpolated per component (§36 "color over lifetime"). Default opaque white at both ends.

    direction?: Vector3

    Cone axis. Copied and normalized at construction; default (0, 1, 0) — +Y, because the world is Y-up in both 2D and 3D (§7a). A zero-length direction falls back to (0, 1, 0) rather than throwing, so new Vector3() is a usable default in authoring code.

    emissionRate?: number

    Continuous emission in particles per second. Default 0. Fractional rates are honoured through an accumulator, so 2.5 emits 2, 3, 2, 3, … across steps rather than truncating to 2.

    fields?: readonly ParticleForceField[]

    §27 force fields, sampled once per particle per step and summed in this order, after gravity. The array is copied at construction. WP-9.1 applies fields; WP-9.2 implements them (see types.ts).

    gravity?: Vector3

    Constant acceleration in units/s² applied to every particle, e.g. (0, −9.81, 0). Copied at construction; default none (zero). Summed before the fields.

    initialSpeed?: ParticleRange

    Initial speed range in units/s along the spawn direction, drawn per particle. Default { min: 0, max: 0 }. Negative bounds are legal and mean "backwards along the cone axis".

    lifetime?: ParticleRange

    Lifetime range in seconds, drawn per particle. Default { min: 1, max: 1 }. Both bounds must be finite and > 0.

    maxParticles: number

    Pool capacity — the most particles that can be live at once. A non-negative safe integer. Spawns beyond it are dropped and counted (ParticleEmitter.droppedCount); see the draw-order note for why this value is part of the determinism contract.

    position?: Vector3

    World position particles spawn at. Copied at construction; default the origin. Not spec text — WP-9.1 addition, because an emitter that can only spawn at the origin cannot be tested against a moving frame and scene attachment does not arrive until WP-9.4.

    restitution?: number

    Normal restitution of the collision plane: the fraction of downward speed returned by a bounce. Default DEFAULT_PARTICLE_RESTITUTION (0, i.e. the particle stops descending and slides). Values above 1 add energy and are not rejected.

    seed?: number

    Seed for this emitter's stream (§33). Default DEFAULT_PARTICLE_SEED — a constant, so the default is still reproducible; there is deliberately no clock- or entropy-derived default.

    Who integrates (§36's simulation option). Default "cpu". "gpu" requires a subsequent ParticleEmitter.bindGpuSimulation before the first step()/emit(), refuses non-radial fields and bounce-only collisionPlaneY (module header, "GPU mode"), and requires maxParticles > 0 (a zero-capacity device buffer cannot exist, so a zero-capacity GPU emitter could never bind — refused where it was written).

    size?: ParticleLifetimeRamp<number>

    Size at age 0 and at age = lifetime, linearly interpolated (§36 "size over lifetime"). Default { start: 1, end: 1 }.

    softness?: number

    Soft-particle fade in [0, 1] (R-32). 0 / omitted keeps the default 8-float stream. Backends fade by depth difference vs a bound scene depth texture; when none is bound, the honest fallback is saturate(1 − |viewZ| · softness).

    spreadAngle?: number

    Cone half-angle in radians (§7a), in [0, π]. Default 0 — every particle exactly along direction. π/2 is a hemisphere, π the whole sphere. Directions are uniform over the spherical cap, not over the angle.

    texture?: ParticleTexture

    Texture-like handle or true (R-32). Truthy opts into the wide instance stream and tells the backend to sample map like an unlit sprite.

    Optional position-history trail (§36). CPU simulation only; refused when simulation: "gpu". Omit for no trail.