/** * A GPU-accelerated layer that draws large sets of circles and rectangles in a * couple of draw calls. Used by {@link Scene} (via `pointBackend: 'webgl'`) to * render `getBatchCircle()` / `getBatchRect()` entities — the point-cloud / * particle case where Canvas2D tops out at ~7 fps for 100k primitives. */ /** Per-frame and cumulative WebGL draw accounting. */ export interface WebGLDrawStats { /** Draw calls issued for the last completed frame. */ drawCalls: number; /** Cumulative draw calls since creation. */ totalDrawCalls: number; /** Cumulative mid-frame MSDF atlas switches, each costing an extra draw. */ atlasSwitches: number; /** Programs compiled at creation — a fixed capability, not a per-frame cost. */ programs: number; /** Textures currently allocated (colour atlas and/or MSDF atlas). */ textures: number; /** * Circles routed to the quad path rather than `gl.POINTS`, cumulatively. * * A circle takes the quad path when it could clip off-viewport or exceeds the * driver's maximum aliased point size. A high share means the POINTS fast path * is not being used and each circle costs four vertices instead of one. */ circleQuadFallbacks: number; /** Circles drawn through the `gl.POINTS` fast path, cumulatively. */ circlePoints: number; } export interface PointRenderer { /** Resize the backing buffer + GL viewport to a logical `w × h` (DPR applied). */ resize(width: number, height: number): void; /** * Cap on the effective device pixel ratio applied by {@link resize}. * `undefined` (default) uses the real, uncapped `devicePixelRatio`. Set * before calling `resize()` for it to take effect on that call (matches * {@link import('../tree/Scene').SceneOptions.maxDPR} — `Scene` sets this * once at construction and again before every `resize()` call, since a * factory function has no other way to receive the option: the WebGL point * layer's creator is a plain `(canvas) => PointRenderer` registered once by * `@vectojs/core`'s module init, with no room for a per-Scene constructor * argument). */ maxDPR?: number; /** Begin a frame: reset the accumulated primitive buffers. */ begin(): void; /** * Draw-call counters for the most recent frame, plus cumulative totals. * * Batching here is by primitive type — one draw per active type — so draw calls * and batches are the same number, and both are bounded at five plus one per * mid-frame atlas switch (MSDF or sprite). Those switches are the only * variable term and the only thing worth watching: each forces a commit of * glyphs/sprites batched against the previous atlas. */ stats?(): WebGLDrawStats; /** Add one circle in world (CSS-pixel) coordinates; `alpha` multiplies the color's. */ addCircle(x: number, y: number, radius: number, color: string, alpha?: number): void; /** * Add one rectangle: top-left at world `(x, y)`, `width × height` in world units, * rotated `rotation` radians about `(x, y)`; `alpha` multiplies the color's. */ addRect(x: number, y: number, width: number, height: number, color: string, alpha?: number, rotation?: number): void; /** * Upload a texture atlas used by {@link addSprite}. Pass any `TexImageSource` * (HTMLImageElement, HTMLCanvasElement, ImageBitmap, …). Call once (or whenever * the atlas changes) before adding sprites. */ setTexture(source: TexImageSource): void; /** * Add one textured sprite sampling the atlas region `[u0,v0]–[u1,v1]` (UVs in * `0..1`): top-left at world `(x, y)`, `width × height` in world units, rotated * `rotation` radians about `(x, y)`. `color` multiplies the sampled texel * (white = unchanged; use it to tint white glyphs); `alpha` multiplies further. * No-op until a texture is set via {@link setTexture}. */ addSprite(x: number, y: number, width: number, height: number, u0: number, v0: number, u1: number, v1: number, color?: string, alpha?: number, rotation?: number): void; /** * Upload an MSDF (multi-channel signed distance field) glyph atlas used by * {@link addGlyph}, kept separate from the {@link setTexture} atlas so both can * be active. `distanceRange` is the field's pixel range (the atlas JSON's * `atlas.distanceRange`) — it drives the shader's edge sharpness. Pair with * `MSDFFont.layout` to position the glyphs. */ setMSDFTexture(source: TexImageSource, distanceRange: number): void; /** * Add one MSDF glyph quad sampling `[u0,v0]–[u1,v1]` (UVs in `0..1`): top-left * at world `(x, y)`, `width × height` in world units. The fragment shader * reconstructs a crisp, resolution-independent edge from the distance field, so * glyphs stay sharp at any scale. `color` tints the glyph (default white); * `alpha` multiplies coverage. No-op until {@link setMSDFTexture} is called. */ addGlyph(x: number, y: number, width: number, height: number, u0: number, v0: number, u1: number, v1: number, color?: string, alpha?: number, rotation?: number): void; /** Clear the layer and draw all accumulated primitives. */ flush(): void; /** Release GL resources. */ destroy(): void; } /** * Create a WebGL2-backed {@link PointRenderer} on `canvas`, or `null` when WebGL2 * (or shader compilation) is unavailable — callers fall back to Canvas2D. * * @param canvas - A dedicated canvas (WebGL2 context); should be stacked over the * scene's 2D canvas. * @returns A point renderer, or `null` if WebGL2 isn't supported. */ export declare function createWebGLPointRenderer(canvas: HTMLCanvasElement): PointRenderer | null;