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>):
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 disposedColour, 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 |
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.
- Textures.
- Model reference:
materialsoverrides and selectors.