# `Ascii.Kit.Scene`
[🔗](https://github.com/houllette/ascii_art/blob/main/lib/ascii/kit/scene.ex#L1)

The shading helpers every upstream scene defines, word for word: `clamp`,
`smooth` (smoothstep from `a` to `b`), `mix`, and value noise and fBm over
`Ascii.Kit.Hash.scene/2`.

`clamp/1`, `smooth/3` and `mix/3` run for nearly every cell of every
frame, and a call to another module cannot be inlined, so a scene that
uses them in its frame keeps local copies with `@compile :inline`, as each
upstream scene keeps its own; these are the reference, and serve `init`.

`noise/3` wraps every `period` lattice cells in x when `period` is not 0;
with 0 it is the scenes' two-argument `noise`, and `fbm/4` with period 0
their three-argument `fbm`. (desert-night's fBm shifts each octave and
keeps its own.)

# `clamp`

```elixir
@spec clamp(v :: number()) :: number()
```

`v < 0 ? 0 : v > 1 ? 1 : v`.

# `fbm`

```elixir
@spec fbm(x :: number(), y :: number(), octaves :: pos_integer(), period :: number()) ::
  float()
```

Fractal noise: `octaves` of `noise/3`, each twice the frequency and half the weight.

# `mix`

```elixir
@spec mix(a :: number(), b :: number(), k :: number()) :: number()
```

`a + (b - a) * k`.

# `noise`

```elixir
@spec noise(x :: number(), y :: number(), period :: number()) :: float()
```

Value noise, wrapping every `period` lattice cells in x when `period` is not 0.

# `smooth`

```elixir
@spec smooth(a :: number(), b :: number(), v :: number()) :: number()
```

Smoothstep from `a` to `b`: `k = clamp((v - a) / (b - a)); k * k * (3 - 2 * k)`.

---

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