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:
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:
&coord = mlt(C, 8);
LATT.RECT[&coord]{
R
}
The coordinate expression and the body are required. Geometry and blend are optional and default to
RECTandQUINTIC, soLATT[coordinate]{ expression }is shorthand forLATT.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:
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:
&noise = LATT.RECT.QUINTIC[mlt(C, 8)]{
R
};
2D Perlin noise treats R only as a direction and compares it to the displacement:
&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:
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:
&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:
&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:
&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:
LATT.RECT[mlt(C, 4)]{ R }
LATT.RECT[mlt(C, 16)]{ R }
and offsets move through the lattice:
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:
&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:
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 |