# Display -- SpriteBatch Source: `src/dusk/display/spritebatch/` See also: `.claude/display-mesh.md`, `.claude/display-texture.md` --- ## Overview The SpriteBatch is the primary 2D rendering primitive. It accumulates axis-aligned quads (sprites) into a shared vertex buffer and draws them in batches. All 2D rendering in the engine -- UI frames, text, tilemaps, HUD -- goes through the global `SPRITEBATCH`. The batch flushes automatically when the per-flush limit is reached, or explicitly via `spriteBatchFlush()`. --- ## Limits | Constant | Value | Meaning | |----------|-------|---------| | `SPRITEBATCH_SPRITES_MAX` | 512 | Total sprites in the vertex buffer | | `SPRITEBATCH_FLUSH_COUNT` | 16 | Number of auto-flush segments | | `SPRITEBATCH_SPRITES_MAX_PER_FLUSH` | 32 | Sprites per auto-flush segment | | `SPRITEBATCH_VERTEX_COUNT` | 3072 | Total vertices (512 * QUAD_VERTEX_COUNT) | --- ## Sprite structure ```c typedef struct { vec3 min; // minimum XYZ corner of the quad in world/screen space vec3 max; // maximum XYZ corner of the quad in world/screen space vec2 uvMin; // minimum UV (top-left in [0,1] texture space) vec2 uvMax; // maximum UV (bottom-right in [0,1] texture space) } spritebatchsprite_t; ``` Z in `min` and `max` controls draw depth (further from camera = higher Z in a typical orthographic setup). For flat 2D, set `min.z = max.z = 0`. --- ## SpriteBatch struct ```c typedef struct { mesh_t mesh; int32_t spriteCount; int32_t spriteFlush; shader_t *shader; shadermaterial_t material; } spritebatch_t; extern spritebatch_t SPRITEBATCH; extern meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT]; ``` `SPRITEBATCH_VERTICES` is a separate global (not embedded in the struct) for platform alignment requirements. --- ## API ```c errorret_t spriteBatchInit(); errorret_t spriteBatchDispose(); // Clear the buffer and reset state. Call before starting a new batch. void spriteBatchClear(); // Append sprites to the buffer. Flushes automatically when the per-flush // segment fills. shader + material are used on the next flush. errorret_t spriteBatchBuffer( const spritebatchsprite_t *sprites, const uint32_t count, shader_t *shader, const shadermaterial_t material ); // Upload and draw all buffered sprites. Binds shader and applies // material if set. No-op if the buffer is empty. errorret_t spriteBatchFlush(); ``` --- ## Typical usage ```c // Beginning of a 2D render pass: spriteBatchClear(); // Build sprites (e.g. via tilesetTileGetUV, then fill spritebatchsprite_t): spritebatchsprite_t s; glm_vec3_copy((vec3){ x, y, 0 }, s.min); glm_vec3_copy((vec3){ x + w, y + h, 0 }, s.max); glm_vec2_copy(uvMin, s.uvMin); glm_vec2_copy(uvMax, s.uvMax); shadermaterial_t mat = { .unlit = { .texture = myTexture } }; spriteBatchBuffer(&s, 1, myShader, mat); // End of pass -- flush remaining sprites: spriteBatchFlush(); ``` --- ## Relationship to other systems - **Text rendering** (`textDraw`) internally calls `spriteBatchBuffer` for each glyph and requires a final `spriteBatchFlush()` after drawing. - **UI frames** (`uiFrameDraw`) push 9 quads to the batch without flushing -- the caller or `uitextboxDraw` is responsible for the flush. - **ECS renderables** of type `ENTITY_RENDERABLE_TYPE_SPRITEBATCH` are drawn via the spritebatch in the scene render pipeline. --- ## Notes - `spriteBatchBuffer` changes the batch's `shader` and `material` fields. If you mix different shaders or textures in one batch, add an explicit `spriteBatchFlush()` call between groups to avoid draws with the wrong material. - The vertex buffer is a static global -- `SPRITEBATCH_VERTICES` must not be written from multiple threads.