API reference
Every public class, method, and event in @codexo/exojs. Generated from source.
classPixelReader
A standing, non-blocking readback of one rectangle of one render texture, for callers who read repeatedly: a picker, an analysis pass, a shader that produces data rather than pixels. ```ts const probe = app.rendering.createPixelReader(app.frameTexture, { region: cursorRect }); let pending: PixelRead | null = null; update() { if (clicked) pending = probe.request(); if (pending?.ready) { pick(pending.data!); pending.release(); pending = null; } } ``` Nothing blocks and nothing is allocated per read: each of the reader's slots owns a staging buffer and a destination array for the reader's lifetime, and a read copies into the slot it was given. The price is latency, the pixels arrive a frame or more after the request, on both backends alike. A caller that needs the pixels within the frame that drew them should keep that data CPU-side instead; for a screenshot or any other single read, RenderingContext.readPixels is the simpler call. `request()` refuses with `null` when every slot is held, rather than queueing or stalling, so a consumer that reads faster than the GPU delivers sees that as it happens instead of as growing latency. # Ownership The reader owns its slots and their arrays and nothing else; the source is the caller's. Destroy the reader when the reads stop. A read whose consumer went away still completes into its slot, so the worst case is the reader's own fixed footprint, never a leak. Context loss fails the reads in flight and the reader recovers on its own; resizing the source fails them too, and a whole-texture reader follows the new size.
import { PixelReader } from '@codexo/exojs'A standing, non-blocking readback of one rectangle of one render texture, for callers who read repeatedly: a picker, an analysis pass, a shader that produces data rather than pixels.
```ts const probe = app.rendering.createPixelReader(app.frameTexture, { region: cursorRect }); let pending: PixelRead | null = null;
update() { if (clicked) pending = probe.request();
if (pending?.ready) { pick(pending.data!); pending.release(); pending = null; } } ```
Nothing blocks and nothing is allocated per read: each of the reader's slots owns a staging buffer and a destination array for the reader's lifetime, and a read copies into the slot it was given. The price is latency, the pixels arrive a frame or more after the request, on both backends alike. A caller that needs the pixels within the frame that drew them should keep that data CPU-side instead; for a screenshot or any other single read, RenderingContext.readPixels is the simpler call.
`request()` refuses with `null` when every slot is held, rather than queueing or stalling, so a consumer that reads faster than the GPU delivers sees that as it happens instead of as growing latency.
# Ownership
The reader owns its slots and their arrays and nothing else; the source is the caller's. Destroy the reader when the reads stop. A read whose consumer went away still completes into its slot, so the worst case is the reader's own fixed footprint, never a leak. Context loss fails the reads in flight and the reader recovers on its own; resizing the source fails them too, and a whole-texture reader follows the new size.
new(backend: RenderBackend, source: RenderTextureAn off-screen render target that can also be sampled as a texture. Combines RenderTarget (framebuffer attachment) with the sampler parameters of a Texture (sca…, options: PixelReaderOptionsOptions for RenderingContext.createPixelReader.): PixelReaderdestroy(): voidslots: numberheight: numberinFlight: numberisDestroyed: booleanwidth: number