134 lines
3.6 KiB
Markdown
134 lines
3.6 KiB
Markdown
# 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.
|