---
# System prepended metadata

title: anemoia spritebatching

---

# SPRITEBATCHING

` all code here is psuedocode, and this idea / proposal is in no way final`

---

Rendering large amounts of sprites individually can severely tank performance.<br>
Each sprite would typically need its own draw call, which can introduce a lot of overhead (switching textures, submitting geometry). <br>
This makes draw calls relatively expensive when not used sparingly.

The objective of spritebatching is to reduce draw calls by grouping multiple sprites into one larger draw call.<br>
This is achieved by combining all necessary geometry of multiple sprites into one compound mesh, which is then submitted to the GPU.

---

## basics 1.0 : batch data

---
The core of the spritebatching system for Anemoia revolves around `BatchData` and `BatchContainer`.

Batch data contains all necessary data for a batch. (shocker)

```csharp
struct BatchData() {
    public Entity[] Entities;
    public Mesh BatchMesh;
}
```

`Entities` is a buffer that stores all the entities / sprites that belong to this batch (consequentially their components as well).<br>

`Mesh` is the "compound mesH" that was mentioned before, it contains the vertices, indices, and texture coordinates of all the sprites in a batch.<br> 
This is what is actually sent to the GPU to be rendered.

### notes
#### a more complete impl could include:
- Material: A reference to a material used for rendering the batch. Typically contains shader uniforms and textures. 
  Could potentially batch by material.
- Layer: A layer Id or mask, used for controlling rendering depth and order.

### why not a component?  
- Components are associated with individual entities, whereas `BatchData` represents a *group* of them.

---

## basics 1.1 : batch containers

---

`BatchContainer`s act as central repositories for all active batches. Its... a container.

```csharp
struct BatchContainer() : IComponent {
    public Dictionary<uint, BatchData> Batches;
}
```

`Batches` is a dictionary that stores all active `BatchData`s. It is keyed by a `uint` that uniquely identifies a batch.<br>
The key could be derived from sprites material ID, layer ID, or a combination of both.

`BatchContainer` is a "Global Component" meaning it does not belong to any entity in particular.
This makes it easy to access and modify from any other system.

---

## systems 1.0 : batch orchestration

---

This is responsible for initializing `BatchContainer`as a global component.

```csharp
GlobalWorld.Add(new BatchContainer()); 
```

No explanation needed, this is very straightforward.

---

## systems 1.1 : batch population

---

This is the core of the batching system. It will iterate through all entities that 
contain both a Sprite and Transform component, and adds them to the appropriate batch.

### process:
- Iterate through eligible entities.
- Get material and layer of entities.
- Generate a key based on material and layer identifiers.
- Get batches, or create them if they dont exist.
- Add entities to the buffer of an appropriate batch.

```csharp
/*
    if entity does not have needed components, cancel
*/
var layer = entity.Get<Sprite>().Layer;
var material = entity.Get<Sprite>().Material;
var key = GetBatchKey(material.Id, layer.Id);
/*
    look for batches, if an appropriate batch doesnt exist, create one
    and add valid entities to id
*/
```

---

## systems 1.2 : batch rendering

---

This system is responsible for taking the populated batches, and rendering them to the screen.
### process:
- Iterate through batches.
- For each batch, update its compound mesh.
- Set layer and materials.
- Render the batch.

```csharp
var batchesToKill = new List<uint>();
var batches = container.Batches;

/*
    iterate through batches
    create compound mesh if it doesnt exist
    look for batches that have no entities, add them to the kill pool
*/

/*
    iterate through entities in batches
    get its components, sprite, transform etc
    create vertices and indices accordingly
    push them to the compound mesh
    send batches to geometry pass to be rendered
    dispose all batches in kill pool
*/
```