Тени и почему объект чёрный

Самая частая загадка новичка: «добавил красивый материал, а куб чёрный». Разбираемся почему и включаем тени.

Материалы, кроме Basic, видны только за счёт отражённого света. Нет источников света — нечего отражать, поэтому поверхность чёрная.

Почему чёрный куб

Сценарий знаком каждому новичку: вы создали MeshStandardMaterial с ярким цветом, добавили меш — а на экране чёрный силуэт. Дело не в цвете. Физический материал не «светится» сам: он лишь отражает падающий на него свет. Если на сцене нет ни одного источника, отражать нечего — и вы видите черноту.

Лечение — добавить свет (см. прошлый урок). Хотя бы слабый Ambient уже покажет цвет; Directional добавит объём.

// было: чёрный куб
const cube = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0xff5544 }));
scene.add(cube);

// стало: добавили свет — куб виден
scene.add(new THREE.AmbientLight(0xffffff, 0.4));
const dir = new THREE.DirectionalLight(0xffffff, 1);
dir.position.set(5, 8, 5);
scene.add(dir);

Быстрый способ проверить, что проблема именно в свете: временно поставьте MeshBasicMaterial. Он игнорирует освещение — если объект стал виден, значит, не хватало света, а не объект «сломан».

Тени: три выключателя

Тени в Three.js выключены по умолчанию — они стоят дорого. Чтобы они появились, нужно щёлкнуть тремя «выключателями»:

  1. Включить тени у рендерера: renderer.shadowMap.enabled = true.
  2. Разрешить источнику отбрасывать тень: light.castShadow = true (умеют Directional, Point, Spot; Ambient — нет).
  3. У объектов указать, кто отбрасывает (castShadow) и кто принимает (receiveShadow) тень.
renderer.shadowMap.enabled = true;

sun.castShadow = true;       // источник отбрасывает тень

cube.castShadow = true;      // куб отбрасывает
floor.receiveShadow = true;  // пол принимает тень от куба

Логика человеческая: тень нужна, когда что-то (куб) загораживает свет и падает на что-то (пол). Поэтому у куба — castShadow, у пола — receiveShadow. Забыли одно из трёх — теней не будет.

Тени стоят дорого

Каждый источник с тенями заставляет рендерить сцену дополнительно с его точки зрения. Поэтому теней должно быть мало: обычно один теневой Directional на всю сцену. Качество регулируют разрешением теневой карты (light.shadow.mapSize) — больше значит чётче, но тяжелее.

Итог

  • Чёрный объект = нет света; добавьте Ambient/Directional.
  • Проверка: Basic-материал виден без света — значит, дело в освещении.
  • Тени = три выключателя: renderer, light.castShadow, объекты cast/receive.
Проверьте себя
1. Почему MeshStandardMaterial без единого источника света выглядит чёрным?
AЭто баг Three.js
BОн показывает только отражённый свет; нет света — нечего отражать, поверхность чёрная
CУ него неправильный цвет по умолчанию
DКамера стоит не там
2. Что нужно включить, чтобы в сцене появились тени?
AТолько цвет фона
Brenderer.shadowMap.enabled = true, у света castShadow, у объектов castShadow/receiveShadow
CДостаточно добавить AmbientLight
DТени включены всегда по умолчанию
3. Какой свет НЕ создаёт теней?
ADirectionalLight
BSpotLight
CPointLight
DAmbientLight
Поддержать проект