Materials

See how each Three.js material renders, and check your own scene with bakery3.check() before you spend anything.

Check your scene's materials

check() runs in the browser and works offline. It uploads nothing and needs no account.

const report = bakery3.check();

report.score; // 0.97
report.counts; // { info: 1, warning: 2, error: 0 }
report.issues;

Each issue tells you which material, where it is and what happens to it.

{
  code: 'material_approximated',
  severity: 'warning',
  message: 'MeshPhongMaterial "chrome" is approximated. It renders as a fully rough…',
  path: '<Lamp>/<Shade>/<Chrome>',
  materialId: 'a1b2c3d4',
  materialName: 'chrome',
  materialType: 'MeshPhongMaterial',
  docs: 'https://bakery3.com/docs/materials',
}

These are the codes a material can get.

CodeSeverityWhat it means
material_approximatedwarningThe render shows a simpler version of the material. The message says what changes
material_map_ignoredwarningThe material uses a slot the render ignores. The message names each
material_custom_shadererrorA ShaderMaterial or RawShaderMaterial. It renders flat gray
material_unknownerrorA material type the render does not support
material_fallback_usedinfoYour fallback renders in place of the material

How each material renders

MaterialIn the render
MeshStandardMaterialSupported. Color, metalness, roughness, normal, emissive, opacity and every texture slot below.
MeshPhysicalMaterialSupported. Plus clearcoat, transmission, thickness, IOR, sheen, specular and anisotropy. Iridescence and dispersion do not render yet.
MeshStandardNodeMaterialSupported. Your TSL graph renders. See Custom shaders.
MeshPhysicalNodeMaterialSupported. As above, with the physical inputs.
MeshBasicMaterialApproximated. Its color and map, unlit, as in your viewport. It does not light the scene, cast a shadow or show in reflections.
MeshLambertMaterialApproximated. A fully rough, non-metal surface in its color and map.
MeshPhongMaterialApproximated. A fully rough, non-metal surface, like Lambert. shininess and specular are not used, so there are no sharp highlights.
MeshToonMaterialApproximated. A fully rough, non-metal surface, without the cel shading.
MeshMatcapMaterialApproximated. A fully rough, non-metal surface in its color and map. The matcap is not used.
MeshNormalMaterialApproximated. Flat gray.
MeshDepthMaterialApproximated. Flat gray.
MeshDistanceMaterialApproximated. Flat gray.
ShaderMaterialNot supported. Flat gray. Declare a fallback or port it to TSL.
RawShaderMaterialNot supported. As above.

On Lambert, Phong and Toon materials, emissiveIntensity is not used: an emissive color glows at intensity 1.

Any other material type is an error with the code material_unknown. It renders as a fully rough surface in its color, or flat gray if it has no color. A node material without a TSL graph renders like the material it is built on, so a MeshBasicNodeMaterial renders like a MeshBasicMaterial.

Glass refracts in the render, but by default it casts a solid shadow, like it does in your viewport. To get the bright pool of light a real glass throws on a table, turn on caustics.

Sheen shows best in motion. This fabric chair turns in the viewport and in the render:

Fabric is where a rasteriser runs out of road. The sheen along a fold is light that entered the weave and left it somewhere else. The traced frame also grounds the legs, and that contact shadow was not authored.

240 frames at 60fps·preview preset

Texture slots that render

map, normalMap, roughnessMap, metalnessMap, emissiveMap, clearcoatMap, clearcoatNormalMap, clearcoatRoughnessMap, transmissionMap, sheenColorMap, sheenRoughnessMap, anisotropyMap, specularColorMap and specularIntensityMap.

The renderer traces shadowed corners and the depth of glass from your geometry, so aoMap and thicknessMap are not used. A material's own envMap and lightMap are not used either: the render lights every surface from the scene.

Slots the render ignores

check() warns with material_map_ignored when a material uses one of these, and names each one.

SlotWhat to do instead
alphaMapPut the cutout in the alpha channel of map, and keep transparent or alphaTest
bumpMapBake the bump detail into a normalMap
displacementMapModel the shape, or bake the detail into a normalMap
specularMapUse MeshStandardMaterial with a roughnessMap
iridescence, iridescenceMap, iridescenceThicknessMapDoes not render yet
dispersionDoes not render yet

A slot your viewport does not draw either, such as an alphaMap on an opaque material, gets no warning.

What the score means

score is the share of your scene's triangles that belong to objects without an error. It counts triangles and not objects, so one unsupported bolt barely moves it and an unsupported car body does. An empty scene scores 1.

Stop a render when there are errors

Neither a warning nor an error stops a render. What check() reports is approximated or left out, and the report is saved with the render.

To stop on errors and show them in your own UI instead:

const report = bakery3.check();

if (report.counts.error > 0) {
  return showIssues(
    report.issues.filter((issue) => issue.severity === 'error'),
  );
}

Leave an object out of the render

Helpers, gizmos and grids are left out automatically. Leave anything else out with userData.

selectionOutline.userData.bakery3 = { exclude: true };

check(), renders and bakes all skip an excluded object and its children. To run the same test yourself, for example in an object picker:

import { shouldExclude } from '@oeave/bakery3';

const pickable = meshes.filter((mesh) => !shouldExclude(mesh));

Render an object your viewport hides

Say your shop shows the sofa on white, and the render should put it in a room. Keep the room visible = false and mark it renderOnly.

room.visible = false;
room.userData.bakery3 = { renderOnly: true };

The room renders like any visible object. Objects hidden inside it, such as a finish the user has not picked, stay hidden.

Instanced meshes

InstancedMesh renders. Its triangles are multiplied by count in the estimate and the size warnings. An instanced mesh cannot be baked. See Bake a scene.

When a material is not supported

You have three options, best first.

  1. Change it to MeshStandardMaterial or MeshPhysicalMaterial.
  2. Port it to TSL as a node material. See Custom shaders.
  3. Declare a fallback that says what it should look like. See Material fallbacks.