关于 threejs-impl-lighting
面向 Three.js 开发者的场景照明参考,涵盖灯光类型、物理强度单位、环境贴图、性能考量及常见设置问题。
主要功能
- 01对比七种灯光类型
- 02说明物理强度单位
- 03介绍 HDR 环境贴图流程
- 04提供灯光辅助器设置指引
- 05说明性能与阴影开销
适用场景
- 01为室内或室外场景选择灯光
- 02设置 PBR 环境照明
- 03排查灯光或阴影异常
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ impertio-studio/ three.js-claude-skill-package --skill threejs-impl-lighting安装后在 Claude Code 中输入/threejs-impl-lighting确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitkeepreferences/anti-patterns.mdexamples.mdmethods.md详细介绍
threejs-impl-lighting
快速参考
灯光类型一览
| 灯光 | 阴影 | 方向 | 开销 | 强度单位(r160+) |
|---|---|---|---|---|
AmbientLight | 否 | 无(均匀) | 可忽略不计 | 无单位乘数 |
HemisphereLight | 否 | 垂直渐变 | 可忽略不计 | 无单位乘数 |
DirectionalLight | 是 | 平行光线 | 中等 | 勒克斯 |
PointLight | 是(6 次渲染!) | 全向 | 高 | 坎德拉 |
SpotLight | 是 | 锥形 | 高 | 坎德拉 |
RectAreaLight | 否 | 平面发光 | 很高 | 尼特(cd/m2) |
LightProbe | 否 | 球谐函数 | 低 | 无单位乘数 |
重要警告
绝对不要将 AmbientLight 用作唯一光源——它会产生扁平、缺乏空间感的渲染效果。务必至少搭配一个方向光或点光源使用。
绝对不要在重新定位 DirectionalLight 或 SpotLight 的目标时,忘记将 light.target 添加到场景中——否则方向向量不会更新。
绝对不要在未先调用 RectAreaLightUniformsLib.init()(WebGLRenderer)或 RectAreaLightTexturesLib(WebGPURenderer)的情况下使用 RectAreaLight——否则灯光渲染会不正确,甚至完全不显示。
绝对不要使用超过 1-2 个投射阴影的 PointLight 实例——每个实例都需要 6 次阴影贴图渲染。可以改用带阴影的 SpotLight,开销更低。
务必在生成环境贴图后调用 pmremGenerator.dispose()——PMREMGenerator 会占用大量 GPU 内存。
务必在使用物理正确的强度值时设置 renderer.toneMapping——若不进行色调映射,较高的勒克斯/坎德拉值会使场景过曝成一片白色。
灯光类层级结构
所有灯光都继承自扩展了 Object3D 的 Light:
Object3D
└── Light (abstract: .color, .intensity, .dispose())
├── AmbientLight — uniform fill
├── HemisphereLight — sky/ground gradient
├── DirectionalLight — parallel rays (sun)
├── PointLight — omnidirectional (bulb)
├── SpotLight — cone (flashlight)
├── RectAreaLight — planar (window/panel)
└── LightProbe — spherical harmonics (IBL)
Light 基类提供:
.color(Color)——灯光颜色,默认值为0xffffff.intensity(number)——强度乘数,默认值为1.isLight(boolean,只读)——始终为true.dispose()——释放 GPU 资源
物理正确的灯光(r160+)
从 r160+ 开始,所有灯光默认都使用基于物理的单位。旧版 renderer.useLegacyLights 属性已移除。
| 灯光类型 | 强度单位 | 说明 |
|---|---|---|
| DirectionalLight | 勒克斯(lm/m2) | 阳光:50,000-100,000 勒克斯 |
| PointLight | 坎德拉(lm/sr) | 100W 灯泡:约 1700 cd |
| SpotLight | 坎德拉(lm/sr) | 舞台聚光灯:约 10,000 cd |
| RectAreaLight | 尼特(cd/m2) | LED 面板:约 500-5000 尼特 |
| AmbientLight | 无单位 | 乘数,无物理单位 |
| HemisphereLight | 无单位 | 乘数,无物理单位 |
PointLight、SpotLight 和 RectAreaLight 的 .power 属性表示以流明为单位的光通量:
- PointLight:
power = intensity * 4 * Math.PI - SpotLight:
power = intensity * Math.PI
务必将物理正确的强度与色调映射搭配使用:
import * as THREE from 'three';
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
7 种灯光类型
AmbientLight
均匀补光。无方向、无阴影。仅用于基础照明。
const ambient = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambient);
HemisphereLight
从天空到地面的渐变光。无阴影。通过天空光和地面反射模拟户外环境光。
const hemi = new THREE.HemisphereLight(0xffffbb, 0x080820, 1.0);
scene.add(hemi);
属性:.groundColor(Color)——下半球颜色。
DirectionalLight
模拟远处光源(太阳)的平行光线。方向由 light.position 指向 light.target.position。
const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(5, 10, 7.5);
scene.add(sun);
scene.add(sun.target); // REQUIRED for target repositioning
属性:.target(Object3D)、.shadow(DirectionalLightShadow)。
PointLight
从单一点向各个方向发出的光。阴影需要 6 次渲染。
const bulb = new THREE.PointLight(0xffaa44, 800, 20, 2);
bulb.position.set(0, 3, 0);
scene.add(bulb);
属性:.distance(number,0=无限距离)、.decay(number,2=物理正确)、.power(流明)。
SpotLight
锥形光。务必将 penumbra 设为不小于 0.1,以获得逼真的柔和边缘。
const spot = new THREE.SpotLight(0xffffff, 1000);
spot.position.set(0, 10, 0);
spot.angle = Math.PI / 6;
spot.penumbra = 0.3;
spot.decay = 2;
scene.add(spot);
scene.add(spot.target); // REQUIRED for target repositioning
属性:.angle(最大值为 Math.PI/2)、.penumbra(0-1)、.distance、.decay、.power、.map(Cookie 纹理,要求 castShadow = true)、.target、.shadow。
RectAreaLight
用于窗户、面板、灯带的平面发光体。仅适用于 MeshStandardMaterial 和 MeshPhysicalMaterial。无法投射阴影。
import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';
RectAreaLightUniformsLib.init(); // MUST call before creating any RectAreaLight
const panel = new THREE.RectAreaLight(0xffffff, 5, 4, 10);
panel.position.set(5, 5, 0);
panel.lookAt(0, 0, 0); // Orient using lookAt, NOT rotation
scene.add(panel);
属性:.width、.height、.power(流明)。
LightProbe
基于球谐函数的环境光照。适用于 AR 和烘焙环境光照。
import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js';
const probe = LightProbeGenerator.fromCubeTexture(cubeTexture);
scene.add(probe);
环境贴图(IBL)
基于图像的光照(IBL)可为 PBR 材质提供最逼真的环境光照。标准工作流使用 RGBELoader + PMREMGenerator。
标准 HDR 环境工作流
import * as THREE from 'three';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
const pmremGenerator = new THREE.PMREMGenerator(renderer);
const rgbeLoader = new RGBELoader();
rgbeLoader.load('environment.hdr', (hdrTexture) => {
const envMap = pmremGenerator.fromEquirectangular(hdrTexture);
scene.environment = envMap.texture; // ALL PBR materials auto-use this
scene.background = envMap.texture; // Optional: visible HDR background
hdrTexture.dispose(); // Free source texture
pmremGenerator.dispose(); // ALWAYS dispose after use
});
scene.environment 与 scene.background
| 属性 | 效果 | 使用场景 |
|---|---|---|
scene.environment | 为所有 Standard/Physical 材质提供 PBR 反射和环境光照 | 始终用于逼真的 PBR |
scene.background | 可见的天空盒/背景 | 需要显示 HDR 时 |
| 两者设为相同的纹理 | 完整的 IBL,并显示环境 | 最常用于产品展示图 |
scene.backgroundBlurriness | 模糊背景(0-1) | 背景景深效果 |
scene.environmentIntensity | 缩放 IBL 的贡献度 | 微调环境光照强度 |
scene.environmentRotation | 旋转环境贴图 | 无需移动灯光即可调整光照方向 |
设置 scene.environment 后,所有 MeshStandardMaterial 和 MeshPhysicalMaterial 实例都会自动使用它进行反射和环境光照,无需逐个配置材质。
PMREMGenerator 方法
| 方法 | 输入 | 用途 |
|---|---|---|
fromEquirectangular(texture) | 等距柱状纹理 | 将 HDR 全景图转换为 PMREM |
fromScene(scene, sigma?) | Three.js 场景 | 从 3D 场景生成 PMREM |
fromCubemap(texture) | CubeTexture | 将立方体贴图转换为 PMREM |
dispose() | -- | 释放 GPU 内存(务必调用) |
EXR 替代方案
import { EXRLoader } from 'three/addons/loaders/EXRLoader.js';
new EXRLoader().load('environment.exr', (exrTexture) => {
const envMap = pmremGenerator.fromEquirectangular(exrTexture);
scene.environment = envMap.texture;
exrTexture.dispose();
pmremGenerator.dispose();
});
灯光辅助器
| 辅助器 | 导入 | 构造函数 |
|---|---|---|
DirectionalLightHelper | three | new DirectionalLightHelper(light, size?, color?) |
SpotLightHelper | three | new SpotLightHelper(light, color?) |
PointLightHelper | three | new PointLightHelper(light, sphereSize?, color?) |
HemisphereLightHelper | three | new HemisphereLightHelper(light, size, color?) |
RectAreaLightHelper | three/addons/helpers/RectAreaLightHelper.js | new RectAreaLightHelper(light) |
LightProbeHelper | three/addons/helpers/LightProbeHelper.js | new LightProbeHelper(probe, size) |
如果辅助器不会自动更新,更改灯光属性后务必调用 helper.update()。
const helper = new THREE.DirectionalLightHelper(dirLight, 5);
scene.add(helper);
// After changing dirLight properties:
helper.update();
性能预算
| 类别 | 预算 |
|---|---|
| 移动端 WebGL | 实时灯光总数最多 4-5 个 |
| 桌面端 WebGL | 根据场景,最多 8-16 个灯光 |
| 投射阴影的 PointLight | 最多 1-2 个(每个需要 6 次渲染遍历) |
| RectAreaLights | 最多 2-3 个(LTC 计算开销较大) |
对于静态环境,务必优先使用烘焙光照,而非实时灯光。
务必使用环境贴图(IBL)作为主要环境光源,而非多个补光灯。
参考链接
- references/methods.md -- 所有灯光类型和 PMREMGenerator 的完整 API 签名
- references/examples.md -- 灯光方案:户外、室内、影棚、产品
- references/anti-patterns.md -- 常见灯光错误及修复方法
官方来源
- https://threejs.org/docs/#api/en/lights/AmbientLight
- https://threejs.org/docs/#api/en/lights/DirectionalLight
- https://threejs.org/docs/#api/en/lights/PointLight
- https://threejs.org/docs/#api/en/lights/SpotLight
- https://threejs.org/docs/#api/en/lights/RectAreaLight
- https://threejs.org/docs/#api/en/lights/HemisphereLight
- https://threejs.org/docs/#api/en/lights/LightProbe
- https://threejs.org/docs/#api/en/extras/PMREMGenerator