API reference
Every public class, method, and event in @codexo/exojs. Generated from source.
classUpdateModule
Per-frame, per-batch mutator. Operates on the system's SoA storage directly — typically a single tight loop over `[0, system.liveCount)` that reads/writes the relevant `Float32Array`s. Implementations must always provide a CPU `apply()`. To make a module GPU-eligible (executed inside the system's composite compute shader on WebGPU backends), additionally implement wgsl and writeUniforms. Modules that declare a WgslContribution may also opt to declare a 1D texture binding via the `textures` field (used by `Curve` / `ColorGradient`-driven modules) — in which case uploadTextures runs once at compile time to upload the data. Implementation pattern (CPU-only module): ```ts class MyModule extends UpdateModule { apply(system, dt) { const { velX, velY, liveCount } = system; for (let i = 0; i < liveCount; i++) { velX[i] *= 0.99; velY[i] *= 0.99; } } } ``` Implementation pattern (GPU-eligible module): ```ts class MyForce extends UpdateModule { constructor(public ax: number, public ay: number) { super(); } apply(system, dt) { const { velX, velY, liveCount } = system; for (let i = 0; i < liveCount; i++) { velX[i] += this.ax * dt; velY[i] += this.ay * dt; } } wgsl(): WgslContribution { return { key: 'MyForce', uniforms: [{ name: 'ax', type: 'f32' }, { name: 'ay', type: 'f32' }], body: `velX[idx] += u_MyForce.ax * dt; velY[idx] += u_MyForce.ay * dt;`, }; } writeUniforms(view, offset) { view.setFloat32(offset + 0, this.ax, true); view.setFloat32(offset + 4, this.ay, true); } } ``` If *any* registered update module on a system lacks `wgsl()`, the system forces CPU mode regardless of backend — preserving the contract that `apply()` is always honoured. Built-in modules ship both implementations; custom modules can opt into GPU acceleration at their authors' discretion. Update modules run after integration each frame. Multiple modules execute in registration order; later modules see the effects of earlier ones.
import { UpdateModule } from '@codexo/exojs-particles' Per-frame, per-batch mutator. Operates on the system's SoA storage directly — typically a single tight loop over `[0, system.liveCount)` that reads/writes the relevant `Float32Array`s.
Implementations must always provide a CPU `apply()`. To make a module GPU-eligible (executed inside the system's composite compute shader on WebGPU backends), additionally implement wgsl and writeUniforms. Modules that declare a WgslContribution may also opt to declare a 1D texture binding via the `textures` field (used by `Curve` / `ColorGradient`-driven modules) — in which case uploadTextures runs once at compile time to upload the data.
Implementation pattern (CPU-only module):
```ts class MyModule extends UpdateModule { apply(system, dt) { const { velX, velY, liveCount } = system; for (let i = 0; i \< liveCount; i++) { velX[i] *= 0.99; velY[i] *= 0.99; } } } ```
Implementation pattern (GPU-eligible module):
```ts class MyForce extends UpdateModule { constructor(public ax: number, public ay: number) { super(); }
apply(system, dt) { const { velX, velY, liveCount } = system; for (let i = 0; i \< liveCount; i++) { velX[i] += this.ax * dt; velY[i] += this.ay * dt; } }
wgsl(): WgslContribution { return { key: 'MyForce', uniforms: [{ name: 'ax', type: 'f32' }, { name: 'ay', type: 'f32' }], body: `velX[idx] += u_MyForce.ax * dt; velY[idx] += u_MyForce.ay * dt;`, }; }
writeUniforms(view, offset) { view.setFloat32(offset + 0, this.ax, true); view.setFloat32(offset + 4, this.ay, true); } } ```
If *any* registered update module on a system lacks `wgsl()`, the system forces CPU mode regardless of backend — preserving the contract that `apply()` is always honoured. Built-in modules ship both implementations; custom modules can opt into GPU acceleration at their authors' discretion.
Update modules run after integration each frame. Multiple modules execute in registration order; later modules see the effects of earlier ones.
new(): UpdateModule apply(system: ParticleSystem, dt: number): void destroy(): void uploadTextures(device: GPUDevice, textures: ReadonlyMap<string, GPUTexture>): void wgsl(): WgslContribution writeUniforms(view: DataView, byteOffset: number, dt: number): void