@aethervtt/shard-sprite 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,202 @@
1
+ import { type AssetRef, type Entity, type World } from '@aethervtt/shard-core';
2
+ import { GpuBuffer, type GpuContext } from '@aethervtt/shard-gpu';
3
+ import { type CameraData, type NodeContext, type NodeDescriptor } from '@aethervtt/shard-render';
4
+ import { type Texture } from '@aethervtt/shard-texture';
5
+ /** Floats per sprite record: affine rows (12), uv rect (4), size (2), anchor (2), color, flags, pad. */
6
+ export declare const SPRITE_FLOATS = 24;
7
+ /** Sprites sharing a texture, blend, and space: one draw per contiguous run in sorted order. */
8
+ export interface SpriteBatch {
9
+ index: number;
10
+ texture: Texture;
11
+ /** The normal map lit views sample (2D lighting), or null. */
12
+ normal: Texture | null;
13
+ blend: number;
14
+ space: number;
15
+ count: number;
16
+ }
17
+ /** A draw: `count` sprites of one batch from `first` in the sorted order. */
18
+ interface Run {
19
+ batch: SpriteBatch;
20
+ first: number;
21
+ count: number;
22
+ layer: number;
23
+ }
24
+ /**
25
+ * Persistent sprite records: each Sprite entity owns a slot, rewritten when its components or
26
+ * transform change and uploaded in coalesced runs. Draw order is a sorted slot list, rebuilt only
27
+ * when a sort key or batch changes: layer, then depth (z, or −y), then batch, so sprites sharing
28
+ * a layer and depth group into as few draws as their textures allow.
29
+ */
30
+ export declare class SpriteStore {
31
+ capacity: number;
32
+ high: number;
33
+ f32: Float32Array<ArrayBuffer>;
34
+ u32: Uint32Array<ArrayBuffer>;
35
+ /** Batch per slot, or -1 (hidden, freed, or waiting on an asset). */
36
+ batchOf: Int32Array<ArrayBuffer>;
37
+ keyHi: Uint32Array<ArrayBuffer>;
38
+ keyLo: Uint32Array<ArrayBuffer>;
39
+ entities: Float64Array<ArrayBuffer>;
40
+ private readonly free;
41
+ private dirty;
42
+ private dirtyLo;
43
+ private dirtyHi;
44
+ /** Slots waiting for a texture or atlas to load. */
45
+ readonly pending: Set<number>;
46
+ readonly batches: SpriteBatch[];
47
+ private readonly byTexture;
48
+ order: Uint32Array<ArrayBuffer>;
49
+ orderCount: number;
50
+ orderDirty: boolean;
51
+ readonly runs: Run[];
52
+ runCount: number;
53
+ /** Sprites per layer in the last sort. */
54
+ readonly perLayer: Map<number, number>;
55
+ /** Bytes of sprite records uploaded this frame. */
56
+ uploadedBytes: number;
57
+ sorts: number;
58
+ readonly records: GpuBuffer;
59
+ readonly orderBuffer: GpuBuffer;
60
+ private orderUploaded;
61
+ /** Hidden sprites per ECS table id, from the last visit. */
62
+ readonly tableSeen: number[];
63
+ private readonly gpu;
64
+ private generation;
65
+ constructor(gpu: GpuContext);
66
+ get live(): number;
67
+ private grow;
68
+ alloc(entity: Entity): number;
69
+ release(slot: number): void;
70
+ markDirty(slot: number): void;
71
+ /** The batch for a texture, normal map, blend, and space, made on first use. */
72
+ batchFor(texture: Texture, blend: number, space: number, normal?: Texture | null): SpriteBatch;
73
+ assign(slot: number, batch: number): void;
74
+ setKey(slot: number, hi: number, lo: number): void;
75
+ private sortA;
76
+ private sortB;
77
+ private readonly counts;
78
+ /** Sorts drawable slots by (keyHi, keyLo): four 16-bit LSD radix passes. Then builds runs. */
79
+ sort(): void;
80
+ /** Uploads dirty records in coalesced runs, and the order when it changed. */
81
+ upload(): void;
82
+ }
83
+ export declare const Sprites: import("@aethervtt/shard-core").ResourceDef<SpriteStore>;
84
+ /**
85
+ * Assigns sprite slots, rewrites the records of sprites whose components or transform changed,
86
+ * retries sprites waiting on assets, re-sorts when a key changed, and uploads.
87
+ */
88
+ export declare const prepareSprites: import("@aethervtt/shard-core").SystemDef<{
89
+ q: import("@aethervtt/shard-core").Query;
90
+ atlasVersions: Map<unknown, number>;
91
+ textureVersions: Map<Texture, number>;
92
+ }>;
93
+ /** Frees a sprite's slot when the Sprite goes away (including on despawn). */
94
+ export declare function observeSpriteRemovals(world: World): void;
95
+ interface LayerGpu {
96
+ buffer: GpuBuffer;
97
+ chunksX: number;
98
+ chunksY: number;
99
+ cursor: number;
100
+ base: number;
101
+ params: GpuBuffer;
102
+ }
103
+ interface TilemapGpu {
104
+ entity: Entity;
105
+ data: unknown;
106
+ version: number;
107
+ chunkSize: number;
108
+ layers: LayerGpu[];
109
+ regions: GpuBuffer;
110
+ regionKey: string;
111
+ remap: GpuBuffer;
112
+ remapData: Uint32Array;
113
+ layer: number;
114
+ tileSize: [number, number];
115
+ affine: Float32Array;
116
+ /** World bounds per chunk per layer (minX, minY, minZ, maxX, maxY, maxZ). */
117
+ bounds: Float32Array[];
118
+ atlas: AssetRef<'TextureAtlas'> | null;
119
+ texture: Texture | undefined;
120
+ /** The atlas's normal map (2D lighting), or null. */
121
+ normal: Texture | null;
122
+ lit: boolean;
123
+ }
124
+ /** Tilemaps on the GPU, and chunk uploads in the last frame (for describe and tests). */
125
+ export declare class TilemapStore {
126
+ readonly maps: Map<number, TilemapGpu>;
127
+ chunkUploads: number;
128
+ /** Per view: chunks drawn, chunks in total. */
129
+ readonly drawn: Map<string, {
130
+ visible: number;
131
+ total: number;
132
+ draws: number;
133
+ }>;
134
+ }
135
+ export declare const Tilemaps: import("@aethervtt/shard-core").ResourceDef<TilemapStore>;
136
+ interface DrawCaches {
137
+ generation: number;
138
+ layouts?: {
139
+ view: GPUBindGroupLayout;
140
+ sprites: GPUBindGroupLayout;
141
+ tilemap: GPUBindGroupLayout;
142
+ texture: GPUBindGroupLayout;
143
+ /** Lit views: the texture group plus a normal map. */
144
+ litTexture: GPUBindGroupLayout;
145
+ };
146
+ /** A 1×1 flat normal for lit batches without a normal map. */
147
+ flatNormal?: GPUTextureView;
148
+ pipelines: Map<string, GPURenderPipeline>;
149
+ groups: Map<string, {
150
+ key: string;
151
+ group: GPUBindGroup;
152
+ }>;
153
+ views: Map<string, {
154
+ uniform: GpuBuffer;
155
+ chunks: GpuBuffer;
156
+ }>;
157
+ batchParams: Map<SpriteBatch, GpuBuffer>;
158
+ samplers?: {
159
+ linear: GPUSampler;
160
+ nearest: GPUSampler;
161
+ };
162
+ }
163
+ /** Pipelines, bind groups, and buffers of the sprite passes, per world. */
164
+ export declare const SpriteDrawCaches: import("@aethervtt/shard-core").ResourceDef<DrawCaches>;
165
+ /** World sprites into the picking pass (a PickDrawer): texels under half opacity don't pick. */
166
+ export declare function drawSpritePicks(ctx: NodeContext, cam: CameraData): void;
167
+ /** World sprites and tilemaps: after opaque 3D and the sky, before transparent 3D. */
168
+ export declare function spriteNode(world: World): NodeDescriptor;
169
+ /** Screen sprites: over the finished image, after tonemapping and anti-aliasing. */
170
+ export declare function overlayNode(world: World): NodeDescriptor;
171
+ /** The sprites section of `render.describe`. */
172
+ export declare function describeSprites(world: World): {
173
+ sprites: number;
174
+ drawn: number;
175
+ pending: number;
176
+ batches: number;
177
+ drawCalls: number;
178
+ perLayer: {
179
+ [k: string]: number;
180
+ };
181
+ uploadedBytes: number;
182
+ sorts: number;
183
+ lighting: {
184
+ occluders: number;
185
+ tileLayers: number;
186
+ segments: number;
187
+ chunkRebuilds: number;
188
+ views: Record<string, import("./lights2d.js").LightViewStats>;
189
+ } | undefined;
190
+ tilemaps: {
191
+ maps: number;
192
+ chunkUploads: number;
193
+ views: {
194
+ [k: string]: {
195
+ visible: number;
196
+ total: number;
197
+ draws: number;
198
+ };
199
+ };
200
+ } | undefined;
201
+ } | undefined;
202
+ export {};