---
title: LATT
navTitle: LATT
slug: manual/LATT
kind: guide
section: Manual
order: 214
status: active
summary: Lattice-sampling and gradient noise interpolation
---

# LATT

`LATT` is Utomata's lattice-sampling construct. Given a coordinate, it evaluates an expression at the lattice points surrounding that coordinate and interpolates the results into a single value.

The lattice itself stores nothing. It has no dimensions, no persistent values, and no state of its own: its points are generated implicitly from the coordinate being evaluated, and the body expression runs only at the points required for that sample. This is what distinguishes `LATT` from Utomata's other sampling constructs. A field lookup retrieves data already stored in a field; a reducer visits and combines stored field cells; `LATT` generates its sampling points procedurally and requires no stored data at all.

Its main use is constructing procedural functions — value noise, gradient noise, and structures built from them — directly in an expression, without first building a field to contain them.

## Definition

The general syntax is:

```uto
LATT.GEOMETRY.BLEND[coordinate]{
  expression
}
```

The geometry determines which lattice points surround the evaluation position, the body expression determines what each of those points contributes, and the blend determines how the contributions are interpolated into the final value.

The coordinate expression defines a position in **lattice space**. It is independent of field resolution and need not correspond directly to `C`. Scaling it changes the frequency of the resulting pattern; offsetting it moves through the lattice. There is no separate frequency property — the scale and movement of the coordinate expression *are* the scale and movement of the lattice:

```uto
&coord = mlt(C, 8);

LATT.RECT[&coord]{
  R
}
```
> The coordinate expression and the body are required. Geometry and blend are optional and default to `RECT` and `QUINTIC`, so `LATT[coordinate]{ expression }` is shorthand for `LATT.RECT.QUINTIC[coordinate]{ expression }`. A blend can only be named after a geometry — `LATT.QUINTIC[C]{ R }` is invalid, because the blend would occupy the geometry position.

## Lattice Built-ins

Three values are available inside the lattice body, and only there:

| Name | Role | Description |
| --- | --- | --- |
| `P` | Position | coordinate of the current lattice point |
| `D` | Displacement | vector from the current lattice point to the evaluation position |
| `R` | Random value | deterministic random vector associated with the current lattice point |

`P` is the integer lattice position currently being visited. Although represented as a vector value, its active components correspond to integer coordinates in lattice space.

`D` is the displacement from that lattice point to the position being sampled:

```uto
D = coordinate - P
```

Its direction points **from the lattice point toward the evaluation position**.

`R` is a deterministic random three-component value in the range `-1` to `1`, belonging to the lattice point itself. Sampling the same lattice point under the same project seed always yields the same `R`. A lattice does not generate new randomness on every step; procedural patterns animate only when their input coordinates move.

These three primitives are enough to construct the classic procedural noises.

**Value noise** uses `R` directly — each lattice point contributes its random value, and the blend interpolates between them:

```uto
&noise = LATT.RECT.QUINTIC[mlt(C, 8)]{
  R
};
```

**2D Perlin noise** treats `R` only as a direction and compares it to the displacement:

```uto
&noise = LATT.RECT.QUINTIC[mlt(C, 8)]{
  dot(nrm(R), D)
};
```

The lattice machinery is identical in both cases; only the contribution computed at each point changes. `LATT` is not any particular noise algorithm — it provides the spatial structure, the deterministic randomness, and the interpolation, and the body determines the function being constructed.

## Geometries

The geometry determines which points surround the evaluation position, and therefore how many times the body is evaluated per sample. Utomata currently provides two.

### RECT

`RECT`, the default, is a two-dimensional rectangular lattice. Each evaluation uses the four corners of the lattice cell containing the sample position:

```text
P ───── P
│       │
│   x   │
│       │
P ───── P
```

The four body results are interpolated first along x, then along y.

Because `RECT` is two-dimensional, lattice-point positions use x and y while `P.z` remains `0`. One consequence is worth noting: `D` is still calculated from the complete three-component input coordinate, so any non-zero z in the coordinate remains present in `D.z`. For ordinary 2D coordinates this makes no difference, but it matters when constructing animated coordinates. To animate a `RECT` lattice, move its x or y coordinates and leave z at zero:

```uto
&time = mlt(step, 0.01);
&coord = add(mlt(C, 4), (0, &time, 0));

&noise = LATT.RECT[&coord]{
  dot(nrm(R), D)
};
```

If z should act as a genuine third lattice dimension, use `CUBE`.

### CUBE

`CUBE` extends the same model into three dimensions. Each evaluation uses the eight corners of the cubic lattice cell surrounding the coordinate, interpolated along x, y, and z.

`CUBE` describes the dimensionality of the **lattice**, not of the field or formation in which it appears. A 2D field can sample a 3D lattice:

```uto
&time = mlt(step, 0.01);

&noise = LATT.CUBE.QUINTIC[
  (mlt(C.x, 4), mlt(C.y, 4), &time)
]{
  dot(nrm(R), D)
};
```

Here x and y come from the field coordinates while z moves through the lattice over time: the field remains two-dimensional, but each frame samples a different 2D cross-section of a three-dimensional procedural function. The same construct works inside a true 3D field, where all three components of `C` vary spatially.

| Geometry | Dimensions | Samples per evaluation | Interpolation |
| --- | ---: | ---: | --- |
| `RECT` *(default)* | 2D | 4 | bilinear |
| `CUBE` | 3D | 8 | trilinear |

Because the body runs once for every contributing point, geometry also sets the computational cost: `CUBE` evaluates its body eight times per result, while `RECT` only needs to evaluate four.

## Blend Modes

The blend mode determines how the contributions from the surrounding points change as the evaluation position moves between them. It does not change the geometry or which points are visited — only the interpolation curve.

| Blend | Interpolation | Character |
| --- | --- | --- |
| `LINEAR` | `t` | constant rate of transition; lattice boundaries may remain visible |
| `CUBIC` | `3t² - 2t³` | smoothstep; flattens toward each lattice point |
| `QUINTIC` *(default)* | `6t⁵ - 15t⁴ + 10t³` | smoothest transition, with smooth derivatives across boundaries |

With `LINEAR`, the direction of change shifts abruptly when a sample crosses from one lattice cell into another, which can make the cell structure visible. `CUBIC` removes the abrupt transitions; `QUINTIC` additionally smooths the derivatives, which is particularly valuable for gradient noise, where discontinuities in the interpolation curve would otherwise expose the rectangular or cubic structure of the underlying lattice. This is why `QUINTIC` is the default.

## Composing Lattices

`LATT` returns an ordinary Utomata vector value and combines freely with operators, macros, fields, and other expressions. LATT calls can also be called directly in formation properties, bypassing field computation alltogether. A common pattern is to define the lattice as a macro and run it in a field:

```uto
&coord = mlt(C, 8);

&noise = LATT.RECT.QUINTIC[&coord]{
  dot(nrm(R), D)
};

#A {
  dim = (256, 256, 1);
  run = &noise;
}
```

The coordinate expression is the primary control over the resulting pattern. Increasing its scale increases lattice frequency:

```uto
LATT.RECT[mlt(C, 4)]{ R }
LATT.RECT[mlt(C, 16)]{ R }
```

and offsets move through the lattice:

```uto
LATT.RECT[add(mlt(C, 8), (0, &time, 0))]{
  R
}
```

Higher-level procedural structures are built by composing ordinary `LATT` expressions rather than through dedicated settings. There is no built-in octave or fractal-noise property; a fractal pattern is simply a sum of lattices at different frequencies:

```uto
&o1 = LATT.RECT[mlt(C, 4)]{
  dot(nrm(R), D)
};

&o2 = LATT.RECT[mlt(C, 8)]{
  dot(nrm(R), D)
};

&o3 = LATT.RECT[mlt(C, 16)]{
  dot(nrm(R), D)
};

&noise = add(
  &o1,
  mlt(&o2, 0.5),
  mlt(&o3, 0.25)
);
```

## Determinism and Numeric Mode

`R` is derived deterministically from the integer lattice position and the global project seed. The same lattice expression sampled at the same coordinates therefore produces the same result across evaluations; changing `step` changes nothing unless `step` alters the coordinate being sampled. The same project seed governs Utomata's other seeded random behavior, keeping procedural results reproducible from the program and its seed.

`LATT` operates in floating-point mode only. If a field configured for integer execution contains a lattice expression, the field is evaluated in floating-point mode instead. The restriction applies to the lattice computation itself; `LATT` is otherwise accepted in field and formation expressions wherever ordinary Utomata expressions are.

## Reference

General syntax:

```uto
LATT.GEOMETRY.BLEND[coordinate]{
  expression
}
```

`LATT[coordinate]{ expression }` is equivalent to `LATT.RECT.QUINTIC[coordinate]{ expression }`.

### Geometry

| Name | Role | Description |
| --- | --- | --- |
| `RECT` *(default)* | geometry | 2D rectangular lattice; evaluates four surrounding corners |
| `CUBE` | geometry | 3D cubic lattice; evaluates eight surrounding corners |

### Blend Modes

| Name | Role | Description |
| --- | --- | --- |
| `LINEAR` | blend | linear interpolation |
| `CUBIC` | blend | cubic smoothstep interpolation |
| `QUINTIC` *(default)* | blend | quintic interpolation |
| `SMOOTH` | alias | alias for `QUINTIC` |

### Lattice Built-ins

| Name | Role | Description |
| --- | --- | --- |
| `P` | coordinate | current integer lattice-point position |
| `D` | displacement | vector from `P` to the evaluation coordinate |
| `R` | value | deterministic random vector at `P`, in the range `-1` to `1` |

