# `CauldronGPU.Billboards`
[🔗](https://github.com/jaman/cauldron/blob/v0.3.3/cauldron_gpu/lib/cauldron_gpu/billboards.ex#L1)

Flat pictures turned to face the camera — sprites, particles, beams seen side on — as
one mesh, rebuilt each tick and put under the same mesh id.

    {mesh, keys} = CauldronGPU.Billboards.mesh(boards, camera)
    materials = Enum.map(keys, &Map.fetch!(materials_by_key, &1))
    [{:mesh, handle.id, mesh}, {:instance, 7, %CauldronGPU.Instance{mesh: handle, materials: materials, shadows: false}}]

A board is a map:

  * `:at` — `{x, y, z}` in the renderer's frame (+Y up), the board's anchor point
  * `:size` — `{width, height}` in the same units
  * `:key` — what the board is drawn with; boards sharing a key share a mesh part, and
    `mesh/2` answers the keys in part order so the caller can give one material each
  * `:uv` — `{u0, v0, u1, v1}`, the part of the texture shown, `u0` on the left and `v0`
    at the top. Default `{0.0, 0.0, 1.0, 1.0}`; `u0 > u1` mirrors the picture
  * `:anchor` — `:centre` (default), the board centred on `:at`; or `:bottom`, its
    bottom edge centred on `:at`
  * `:upright` — `true` keeps the board's up along +Y, turning it only about the vertical
    (a standing sprite); `false` (default) faces the camera fully
  * `:color` — `{r, g, b, a}` bytes the board's material colour is multiplied by
    (`CauldronGPU.Mesh`'s `colors`); when no board has one the mesh has no colours
  * `:offset` — `{right, up}`, where the anchor sits on the board from its centre or
    bottom, in the board's own units. Default `{0.0, 0.0}`

The mesh is `nil` when there are no boards.

# `board`

```elixir
@type board() :: %{
  :at =&gt; {number(), number(), number()},
  :size =&gt; {number(), number()},
  :key =&gt; term(),
  optional(:uv) =&gt; {number(), number(), number(), number()},
  optional(:anchor) =&gt; :centre | :bottom,
  optional(:upright) =&gt; boolean(),
  optional(:offset) =&gt; {number(), number()},
  optional(:color) =&gt; {byte(), byte(), byte(), byte()}
}
```

# `mesh`

```elixir
@spec mesh([board()], CauldronGPU.Camera.t()) ::
  {CauldronGPU.Mesh.t() | nil, [term()]}
```

The boards as one mesh facing `camera`, with one part per key, and the keys in part order.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
