threejs-materials-lighting

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

three.js Materials & Lighting

three.js 材质与光照

Make three.js surfaces look right: pick the correct material, light the scene, enable shadows, and add image-based lighting. Patterns target r165+, verified against r184 (lighting is physically based by default since r155).
让three.js表面呈现正确效果:选择合适的材质、为场景打光、启用阴影并添加基于图像的光照。本文模式适用于r165+版本,已在r184版本验证(自r155版本起,光照默认采用物理渲染)。

When to use

适用场景

  • Use when a mesh renders black or flat, when choosing a material, adding lights, enabling shadows, or setting up environment-map reflections (IBL).
  • Use when code constructs
    MeshStandardMaterial
    ,
    DirectionalLight
    , etc., or sets
    renderer.shadowMap.enabled
    or
    scene.environment
    .
When not to use: the renderer/camera/loop →
threejs-scene-setup
. Loading models (whose PBR materials this complements) →
threejs-gltf-loading
. Custom GLSL/
ShaderMaterial
is its own topic; for the portable concept see
shader-programming
.
  • 当网格渲染为黑色或平面化、需要选择材质、添加灯光、启用阴影或设置环境贴图反射(IBL)时使用。
  • 当代码中创建
    MeshStandardMaterial
    DirectionalLight
    等对象,或设置
    renderer.shadowMap.enabled
    scene.environment
    时使用。
不适用场景:渲染器/相机/循环设置 → 请使用
threejs-scene-setup
。模型加载(其PBR材质可借助本文内容调整)→ 请使用
threejs-gltf-loading
。自定义GLSL/
ShaderMaterial
属于独立主题;如需了解可移植概念,请查看
shader-programming

Core workflow

核心工作流程

  1. Pick a material by need.
    MeshStandardMaterial
    (PBR:
    roughness
    ,
    metalness
    , reacts to lights/IBL) for realism;
    MeshPhysicalMaterial
    for clearcoat/transmission;
    MeshBasicMaterial
    (unlit, ignores lights) for UI/flat;
    MeshNormalMaterial
    /
    MeshDepthMaterial
    for debugging.
  2. Add light, or nothing shows. Lit materials need a light source and/or
    scene.environment
    . Combine a soft fill (
    AmbientLight
    /
    HemisphereLight
    ) with a key
    DirectionalLight
    .
  3. Mind light intensity. Since r155, lighting is physically based; modern intensities are higher than old tutorials (a key
    DirectionalLight
    ≈ 1–3).
  4. Enable shadows in three places.
    renderer.shadowMap.enabled = true
    , the light's
    castShadow = true
    , and each mesh's
    castShadow
    /
    receiveShadow
    . Then fit the light's shadow camera to the scene.
  5. Use an environment map for grounded reflections. Assign an equirectangular or PMREM-processed texture to
    scene.environment
    ; PBR materials pick it up automatically.
  6. Verify under real lighting — confirm the surface responds to the key light (highlights move), shadows land where expected, and reflections look plausible.
  1. 按需选择材质
    MeshStandardMaterial
    (PBR材质:支持
    roughness
    metalness
    属性,对灯光/IBL有响应)用于实现真实感效果;
    MeshPhysicalMaterial
    用于清漆/透射效果;
    MeshBasicMaterial
    (无光照,忽略灯光)用于UI/平面效果;
    MeshNormalMaterial
    /
    MeshDepthMaterial
    用于调试。
  2. 添加光源,否则无显示。受光照材质需要光源和/或
    scene.environment
    环境贴图。将柔和的填充光(
    AmbientLight
    /
    HemisphereLight
    )与主
    DirectionalLight
    平行光结合使用。
  3. 注意灯光强度。自r155版本起,光照采用物理渲染;现代版本的灯光强度高于旧教程(主平行光强度≈1–3)。
  4. 在三处启用阴影。设置
    renderer.shadowMap.enabled = true
    ,开启光源的
    castShadow = true
    ,并为每个网格设置
    castShadow
    /
    receiveShadow
    属性。然后调整光源的阴影相机使其适配场景。
  5. 使用环境贴图实现真实反射。将等矩形或经PMREM处理的纹理赋值给
    scene.environment
    ;PBR材质会自动应用该贴图。
  6. 在真实光照下验证 —— 确认表面对主光源有响应(高光移动)、阴影位置符合预期、反射效果逼真。

Patterns

示例代码

1. PBR material under a 3-light rig

1. 三光源系统下的PBR材质

js
import * as THREE from 'three';

const material = new THREE.MeshStandardMaterial({
  color: 0xcc4444,
  roughness: 0.5,     // 0 = mirror, 1 = fully matte
  metalness: 0.0,     // 0 = dielectric (plastic/wood), 1 = metal
});
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), material);
scene.add(mesh);

// Soft sky/ground fill + a directional key light.
scene.add(new THREE.HemisphereLight(0xbbddff, 0x443322, 1.0)); // sky, ground, intensity
const key = new THREE.DirectionalLight(0xffffff, 2.5);
key.position.set(5, 10, 7);
scene.add(key);
js
import * as THREE from 'three';

const material = new THREE.MeshStandardMaterial({
  color: 0xcc4444,
  roughness: 0.5,     // 0 = 镜面效果, 1 = 完全哑光
  metalness: 0.0,     // 0 = 绝缘材质(塑料/木材), 1 = 金属材质
});
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), material);
scene.add(mesh);

// 柔和的天空/地面填充光 + 主平行光
scene.add(new THREE.HemisphereLight(0xbbddff, 0x443322, 1.0)); // 天空色, 地面色, 强度
const key = new THREE.DirectionalLight(0xffffff, 2.5);
key.position.set(5, 10, 7);
scene.add(key);

2. Unlit material (no light needed)

2. 无光照材质(无需光源)

js
// MeshBasicMaterial ignores lights — for flat color, UI, or sprites/labels.
const flat = new THREE.MeshBasicMaterial({ color: 0x44aa88 });
// A textured color map should be tagged sRGB so colors aren't washed out:
const tex = new THREE.TextureLoader().load('assets/logo.png');
tex.colorSpace = THREE.SRGBColorSpace;
const logo = new THREE.MeshBasicMaterial({ map: tex, transparent: true });
js
// MeshBasicMaterial忽略灯光 —— 用于纯色、UI或精灵/标签
const flat = new THREE.MeshBasicMaterial({ color: 0x44aa88 });
// 带纹理的颜色贴图需标记为sRGB,避免颜色褪色:
const tex = new THREE.TextureLoader().load('assets/logo.png');
tex.colorSpace = THREE.SRGBColorSpace;
const logo = new THREE.MeshBasicMaterial({ map: tex, transparent: true });

3. Shadows (the three required switches + camera fit)

3. 阴影效果(三个必要设置 + 相机适配)

js
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;     // softer edges

const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(8, 12, 6);
sun.castShadow = true;
sun.shadow.mapSize.set(2048, 2048);                   // default 512; raise for crisp
// DirectionalLight uses an OrthographicCamera — fit it tightly to the scene:
const cam = sun.shadow.camera;
cam.near = 1; cam.far = 40;
cam.left = -15; cam.right = 15; cam.top = 15; cam.bottom = -15;
scene.add(sun);

mesh.castShadow = true;
ground.receiveShadow = true;                          // a plane to catch the shadow
js
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;     // 边缘更柔和

const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(8, 12, 6);
sun.castShadow = true;
sun.shadow.mapSize.set(2048, 2048);                   // 默认512;提高数值可获得更清晰的阴影
// 平行光使用正交相机——需使其紧密适配场景:
const cam = sun.shadow.camera;
cam.near = 1; cam.far = 40;
cam.left = -15; cam.right = 15; cam.top = 15; cam.bottom = -15;
scene.add(sun);

mesh.castShadow = true;
ground.receiveShadow = true;                          // 用于接收阴影的平面

4. PBR textures on a material

4. 材质上的PBR纹理

js
const loader = new THREE.TextureLoader();
const colorMap = loader.load('assets/brick_color.jpg');
colorMap.colorSpace = THREE.SRGBColorSpace;           // color maps are sRGB
const normalMap = loader.load('assets/brick_normal.jpg'); // data maps stay linear
const roughMap  = loader.load('assets/brick_rough.jpg');

const brick = new THREE.MeshStandardMaterial({
  map: colorMap,
  normalMap,
  roughnessMap: roughMap,
  metalness: 0,
});
js
const loader = new THREE.TextureLoader();
const colorMap = loader.load('assets/brick_color.jpg');
colorMap.colorSpace = THREE.SRGBColorSpace;           // 颜色贴图为sRGB格式
const normalMap = loader.load('assets/brick_normal.jpg'); // 数据贴图保持线性
const roughMap  = loader.load('assets/brick_rough.jpg');

const brick = new THREE.MeshStandardMaterial({
  map: colorMap,
  normalMap,
  roughnessMap: roughMap,
  metalness: 0,
});

5. Image-based lighting from an HDR environment

5. 基于HDR环境的图像光照

js
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

new RGBELoader().load('assets/studio.hdr', (hdr) => {
  hdr.mapping = THREE.EquirectangularReflectionMapping;
  scene.environment = hdr;     // lights + reflects all PBR materials
  scene.background = hdr;       // optional: show it as the backdrop
});
// Optional cinematic tone curve:
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
js
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

new RGBELoader().load('assets/studio.hdr', (hdr) => {
  hdr.mapping = THREE.EquirectangularReflectionMapping;
  scene.environment = hdr;     // 为所有PBR材质提供光照与反射
  scene.background = hdr;       // 可选:将其设为背景
});
// 可选电影色调曲线:
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;

Pitfalls

常见问题

  • Mesh is pure black → a lit material with no light and no
    scene.environment
    . Add a light or an environment map; to confirm geometry, temporarily swap to
    MeshBasicMaterial
    /
    MeshNormalMaterial
    .
  • Scene too dark even with lights → old tutorial intensities. r155+ is physically based; raise intensities (key light ≈ 2–3) or add an environment map.
  • Shadows don't appear → you missed one of the three switches (
    renderer.shadowMap.enabled
    ,
    light.castShadow
    , mesh
    castShadow
    /
    receiveShadow
    ).
  • Shadows are cut off or blocky → the
    DirectionalLight
    's orthographic
    shadow.camera
    frustum is too big/small or doesn't cover the scene; tighten
    left/right/top/bottom/near/far
    and raise
    shadow.mapSize
    . Visualise it with
    new THREE.CameraHelper(light.shadow.camera)
    .
  • Shadow acne / peter-panning → adjust
    light.shadow.bias
    (small negative) and
    light.shadow.normalBias
    .
  • Colors look washed out / too bright → color (albedo) textures need
    texture.colorSpace = THREE.SRGBColorSpace
    ; normal/roughness/metalness maps must stay linear (leave them as
    NoColorSpace
    ).
  • PointLight shadows tank performance → a point light renders the scene 6 times (cube map). Prefer one shadow-casting
    DirectionalLight
    ; use cheaper fakes elsewhere.
  • 网格全黑 → 使用了受光照材质但未添加光源或
    scene.environment
    环境贴图。添加光源或环境贴图;如需确认几何体,可临时切换为
    MeshBasicMaterial
    /
    MeshNormalMaterial
  • 添加灯光后场景仍过暗 → 旧教程中的强度值不适用于新版本。r155+版本采用物理渲染;提高灯光强度(主光源≈2–3)或添加环境贴图。
  • 阴影不显示 → 遗漏了三个必要设置之一(
    renderer.shadowMap.enabled
    light.castShadow
    、网格的
    castShadow
    /
    receiveShadow
    )。
  • 阴影被截断或块状化 → 平行光的正交
    shadow.camera
    视锥体过大/过小或未覆盖场景;调整
    left/right/top/bottom/near/far
    参数并提高
    shadow.mapSize
    。可使用
    new THREE.CameraHelper(light.shadow.camera)
    可视化相机范围。
  • 阴影瑕疵/偏移 → 调整
    light.shadow.bias
    (小负值)和
    light.shadow.normalBias
    参数。
  • 颜色褪色/过亮 → 颜色(反照率)纹理需设置
    texture.colorSpace = THREE.SRGBColorSpace
    ;法线/粗糙度/金属度贴图必须保持线性(保留
    NoColorSpace
    设置)。
  • 点光源阴影严重影响性能 → 点光源需渲染6次场景(立方体贴图)。优先使用单个投射阴影的平行光;其他场景使用更廉价的模拟阴影。

References

参考资料

  • For the material cheat-sheet (which
    Mesh*Material
    for which look), light types and their parameters/units, transparency vs
    alphaTest
    ordering, and the
    PMREMGenerator
    /
    RoomEnvironment
    route to IBL without an HDR file, read
    references/materials-lights-table.md
    .
  • 如需了解材质速查表(不同
    Mesh*Material
    适用效果)、灯光类型及其参数/单位、透明度与
    alphaTest
    层级,以及无需HDR文件即可实现IBL的
    PMREMGenerator
    /
    RoomEnvironment
    方法,请阅读
    references/materials-lights-table.md

Related skills

相关技能

  • threejs-scene-setup
    — renderer, camera, and loop (set
    shadowMap
    , tone mapping).
  • threejs-gltf-loading
    — models arrive with PBR materials this skill tunes.
  • shader-programming
    — custom shader effects (engine-agnostic concept).
  • threejs-scene-setup
    —— 渲染器、相机与循环设置(需配置
    shadowMap
    、色调映射)。
  • threejs-gltf-loading
    —— 模型加载后可借助本文内容调整其PBR材质。
  • shader-programming
    —— 自定义着色器效果(引擎无关概念)。