# Materials

> Reference for materials: all 16 built-in presets with colour, roughness and metalness, the MaterialInput and MaterialOptions types, engraving, definePreset and PresetSpec, useMaterial, useMaterialInput, useMaterialOverrides, createMaterial and PresetMaterial.

```ts
import { createMaterial, definePreset, PresetMaterial, useMaterial, useMaterialInput, useMaterialOverrides } from "@apricot/react";
import type { MaterialInput, MaterialOptions, MaterialOverrides, PresetSpec } from "@apricot/react";
```

## `MaterialInput`

What a `material` prop accepts (on shapes, `Mesh`, `Instances`, and as values in `<Model materials>`):

```ts
type MaterialInput =
  | string // a preset name: "chrome"
  | ({ preset: string; transition?: number } & MaterialOptions) // { preset: "car-paint", color: "#1f4fd1" }
  | THREE.Material; // your own three.js material, used as is and never disposed
```

Colour, roughness and metalness changes **animate** over `transition` seconds (default `0.4`) without rebuilding the shader. Changing anything else (an image, `side`, `engrave`) builds a new material. Unknown preset names throw an error listing the known ones.

## Built-in presets

| Preset | Colour | Roughness | Metalness | Also |
| --- | --- | --- | --- | --- |
| `standard` | `#cfd3d8` | 0.5 | 0 | The default: light, slightly glossy grey |
| `car-paint` | `#a8102a` | 0.32 | 0.55 | Clearcoat, metallic flakes |
| `paint` | `#1d3f8f` | 0.45 | 0 | Clearcoat |
| `gloss-black` | `#0b0c0e` | 0.1 | 0 | Clearcoat (piano black) |
| `chrome` | `#eceef1` | 0.04 | 1 | |
| `brushed-metal` | `#c9cdd3` | 0.3 | 1 | Streaks along the mesh's U direction |
| `aluminium` | `#d5d8dc` | 0.2 | 1 | |
| `gold` | `#e9bd63` | 0.18 | 1 | |
| `rose-gold` | `#eab09a` | 0.2 | 1 | |
| `glass` | `#f4f8fb` | 0.04 | 0 | Clear: transmission 1, ior 1.5 |
| `tinted-glass` | `#ffffff` | 0.04 | 0 | Transmission with a dark tint (car windows) |
| `rubber` | `#1c1d1f` | 0.9 | 0 | |
| `plastic` | `#2a2c30` | 0.5 | 0 | |
| `matte` | `#2b2d32` | 0.7 | 0 | |
| `clay` | `#d9d4cc` | 0.9 | 0 | |
| `light` | `#ffffff` | 0.3 | 0 | Glows in its own colour (emissive, intensity 2): lamps, screens, LEDs |

> [!NOTE]
> Metals (`metalness` 1) reflect their surroundings and look dark without something to reflect. Give the scene an `environment` (for example `look="none" environment="studio"`). Glass shows what is behind it, so it needs a background with detail (`<Backdrop>`, other objects).

## `MaterialOptions`

| Option | Type | Description |
| --- | --- | --- |
| `color` | colour | Overrides the preset's colour. Animates |
| `roughness` | 0–1 | 0 mirror, 1 fully diffuse. Animates |
| `metalness` | 0–1 | Animates |
| `map` | `THREE.Texture \| null` | A colour image (from `useTexture`). Multiplies `color`, so use `color: "#ffffff"` to show it true. Its alpha cuts out or fades the material |
| `uv` | TSL `vec2` node | Texture coordinates for the image, brushed streaks and engraving (default: the mesh's UVs) |
| `engrave` | `Engraving \| null` | Engraving, etching or printing from a mask |
| `side` | `"front" \| "back" \| "double"` | Which faces show (default `"front"`). `"double"` for thin things seen from both sides |
| `vertexColors` | `boolean` | Multiplies the colour by the geometry's per-vertex colours (default `false`) |
| `physical` | `Partial<MeshPhysicalNodeMaterialParameters>` | Any other three.js physical-material property, for full control |

### `Engraving`

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `mask` | `THREE.Texture` | required | Opaque where engraved (its alpha is read) |
| `color` | colour | the preset's colour | Colour of the engraved area |
| `roughness` | number | preset's + 0.3 | Roughness of the engraved area |
| `metalness` | number | the preset's | Metalness of the engraved area |
| `uv` | TSL `vec2` node | the mesh's UVs | Where to read the mask |
| `weight` | TSL `float` node | | Multiplies the mask, for example to engrave one side only |

## `definePreset(name, spec)`

Registers a preset, usable anywhere a preset name is accepted. Registering an existing name replaces it. Call it once at startup, before scenes using it mount.

### `PresetSpec`

| Field | Type | Description |
| --- | --- | --- |
| `color` | colour | Required |
| `roughness` | number | Required |
| `metalness` | number | Required |
| `clearcoat`, `clearcoatRoughness` | number | Clear lacquer on top (car paint, piano black) |
| `brushed` | boolean | Directional highlights and fine streaks along U |
| `flakes` | boolean | Metallic sparkle under the lacquer |
| `transmission` | number | See-through: 1 is clear glass |
| `ior`, `thickness` | number | Glass refraction (defaults 1.5 and 0.05) |
| `attenuationColor`, `attenuationDistance` | colour, number | Tint picked up through glass, and how fast (smaller is darker) |
| `emissive` | colour or `"color"` | Glows by itself; `"color"` glows in the material's own (live) colour |
| `emissiveIntensity` | number | Default 1 |

## Hooks

| Hook | Returns | Use |
| --- | --- | --- |
| `useMaterial(preset, options?)` | `THREE.Material` | A preset material for your own meshes. Components asking for the same preset and values share one (one shader build). Colour changes animate. Freed when the last user unmounts. Options: `MaterialOptions & { transition? }` |
| `useMaterialInput(material, color?)` | `THREE.Material` | Resolves a `MaterialInput` prop (plus a colour shortcut) the way shapes do. Default `"standard"` |
| `useMaterialOverrides(object, overrides, resolve?)` | `void` | Assigns `{ selector: MaterialInput }` overrides to the parts of a three.js object, as `<Model materials>` does. Restores the originals on change and unmount. Warns for a selector that matches nothing |

All three must run inside `<Scene>`.

## Outside React

`createMaterial(preset, options?)` returns a standalone `THREE.Material` (not shared, not animated). Dispose it yourself.

`new PresetMaterial(preset, options?)` gives a handle you can drive by hand:

| Member | Description |
| --- | --- |
| `material` | The three.js material |
| `preset` | The preset name |
| `values` | The current `{ color, roughness, metalness }` |
| `set({ color?, roughness?, metalness? })` | Changes them at once |
| `animateTo(target, seconds = 0.4)` | Starts a smooth change; drive it with `step` |
| `step(delta)` | Advances `animateTo`. Returns `true` while still changing |
| `dispose()` | Frees the material |

## Related

- [Shapes and materials](https://matthiasbrandolin.dev/apricot/guides/shapes-and-materials).
- [Textures](https://matthiasbrandolin.dev/apricot/guides/textures).
- [Model reference](https://matthiasbrandolin.dev/apricot/reference/model): `materials` overrides and selectors.
