mcpField
T
threejs-impl-lighting

threejs-impl-lighting

github.com/impertio-studio开发23141 次安装30 周前更新
代码仓库

关于 threejs-impl-lighting

面向 Three.js 开发者的场景照明参考,涵盖灯光类型、物理强度单位、环境贴图、性能考量及常见设置问题。

主要功能

  1. 01对比七种灯光类型
  2. 02说明物理强度单位
  3. 03介绍 HDR 环境贴图流程
  4. 04提供灯光辅助器设置指引
  5. 05说明性能与阴影开销

适用场景

  1. 01为室内或室外场景选择灯光
  2. 02设置 PBR 环境照明
  3. 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 外,安装时一起下载的参考资料和脚本。

.gitkeep
references/
anti-patterns.md
examples.md
methods.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();
});

灯光辅助器

辅助器导入构造函数
DirectionalLightHelperthreenew DirectionalLightHelper(light, size?, color?)
SpotLightHelperthreenew SpotLightHelper(light, color?)
PointLightHelperthreenew PointLightHelper(light, sphereSize?, color?)
HemisphereLightHelperthreenew HemisphereLightHelper(light, size, color?)
RectAreaLightHelperthree/addons/helpers/RectAreaLightHelper.jsnew RectAreaLightHelper(light)
LightProbeHelperthree/addons/helpers/LightProbeHelper.jsnew 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)作为主要环境光源,而非多个补光灯。


参考链接

官方来源

评论

支持 Markdown