3.6 KiB
3.6 KiB
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
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
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
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
// 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 callsspriteBatchBufferfor each glyph and requires a finalspriteBatchFlush()after drawing. - UI frames (
uiFrameDraw) push 9 quads to the batch without flushing -- the caller oruitextboxDrawis responsible for the flush. - ECS renderables of type
ENTITY_RENDERABLE_TYPE_SPRITEBATCHare drawn via the spritebatch in the scene render pipeline.
Notes
spriteBatchBufferchanges the batch'sshaderandmaterialfields. If you mix different shaders or textures in one batch, add an explicitspriteBatchFlush()call between groups to avoid draws with the wrong material.- The vertex buffer is a static global --
SPRITEBATCH_VERTICESmust not be written from multiple threads.