Material fallbacks

Tell the renderer what an unsupported material should look like. Your own shader keeps running in the viewport.

Declare a fallback

Put the physical values on the material's userData. Here a GLSL shader fakes brushed metal in the browser, and the fallback says what it is.

const brushed = new ShaderMaterial({
  vertexShader,
  fragmentShader,
  uniforms: { uTint: { value: new Color('#8a8f98') } },
});

brushed.userData.bakery3 = {
  fallback: {
    color: '#8a8f98',
    metalness: 1,
    roughness: 0.35,
    anisotropy: 0.8,
  },
};

check() no longer reports an error for it. The render uses a physical material with exactly the values you gave.

Declare it in React Three Fiber

import { Bakery3Material } from '@oeave/bakery3/r3f';

<Bakery3Material
  web={<CarPaintShader />}
  render={
    <meshPhysicalMaterial
      color="#830000"
      metalness={0.9}
      roughness={0.14}
      clearcoat={1}
    />
  }
/>

web is what the browser draws. render is never mounted. Only its props are read, and only the fields in the table below.

Apply it to every use of a material, or to one object

// Covers every mesh that uses this material.
material.userData.bakery3 = { fallback: { color: '#1b2a4a', metalness: 0.9 } };

// Covers this object only.
mesh.userData.bakery3 = { fallback: { color: '#1b2a4a', metalness: 0.9 } };

The material is checked first, then the object. A fallback on an object changes only that object: other meshes that share the material keep it.

Every field

All fields are optional. A field you leave out takes its MeshPhysicalMaterial default, for example roughness: 1 and metalness: 0.

FieldType
colorCSS hex string
metalness0-1
roughness0-1
clearcoat0-1
clearcoatRoughness0-1
transmission0-1
thicknessmeters
iorindex of refraction, for example 1.45
emissiveCSS hex string
emissiveIntensitynumber
opacity0-1
sheen0-1
sheenColorCSS hex string
iridescence0-1. Does not render yet
anisotropy0-1

See which fallbacks were used

check() reports every fallback as info, and the devtools panel shows it with the other issues. The fallback is saved with the render, so rendering again later gives the same image.

{
  code: 'material_fallback_used',
  severity: 'info',
  message: 'ShaderMaterial "holo" renders with your declared fallback.',
  path: '<Product>/<Panel>/<Holo>',
  materialType: 'ShaderMaterial',
}

When to use TSL instead

A fallback is one set of values for the whole surface. If your material has a pattern, such as a weave, a gradient or noise, a fallback flattens it to a single color.

Port it to TSL instead, and the pattern renders. See Custom shaders.

Remove a fallback

Delete the fallback key. check() reports the material as unsupported again.