EffectComposer 不参与灯光计算,仅对渲染器输出的光照结果做后处理;真实感需通过灯光参数与后处理阈值的手动匹配实现,如调整 emissiveIntensity、light.intensity、Bloom threshold 等。

Three.js 的 EffectComposer 本身不参与灯光计算,它只在最终图像上叠加后处理效果;灯光仍由场景中的 Light 对象(如 DirectionalLight、PointLight)驱动,渲染器(WebGLRenderer)完成光照着色后,才把结果交给 EffectComposer 处理。想让“灯光”和“后处理”协同出真实感,关键不是让 Composer 控制光,而是让灯光输出能被后处理有效增强或修正。
为什么 Bloom 效果总显得假?光源强度与材质 emissive 不匹配
Bloom(泛光)本质是提取画面中“过曝区域”做模糊再叠加,但 Three.js 默认不会自动判断哪些像素该过曝——它只认 material.emissive 和 light.intensity 的绝对值。如果点光源设为 intensity = 2,而模型材质 emissive 是 0x000000,Bloom 就几乎没反应;反之若所有面都设 emissive = 0xffffff,整个画面会糊成一片白。
- 确保发光体真正“发光”:给灯罩、LED条带等模型单独赋材质,
emissive设为浅黄/暖白(如0xffeedd),emissiveIntensity≥ 1.5 - 点光源/聚光灯的
intensity建议设为 1–5(单位无物理意义,但高于 10 容易让 Bloom 失控) - 在
UnrealBloomPass中调threshold(默认 0.1):值越小,越暗的区域也参与泛光;室内场景常设为 0.05–0.08 - 禁用
renderer.gammaOutput = true时,Bloom 输入信号变弱,需同步提高emissiveIntensity或threshold
环境光(AmbientLight)+ HDRI 贴图怎么喂给 EffectComposer?
Three.js 原生 AmbientLight 是全局均质光,无法提供方向性反射或环境遮蔽;真·环境光必须靠 Scene.environment 设置 HDRI(.hdr 或 .exr)。但 EffectComposer 不会自动读取这个贴图——它只处理渲染器输出的帧。所以 HDRI 的作用发生在基础渲染阶段,而 EffectComposer 只能对它的结果做二次加工。
- 务必设置
scene.environment = hdrTexture(而非仅靠AmbientLight) - HDRI 加载后,启用
renderer.physicallyCorrectLights = true,否则金属/粗糙度材质响应异常 - 若想强化 HDRI 反射的锐利度,可在
EffectComposer链中加ShaderPass对法线贴图做边缘锐化,而不是调高 HDR 强度 - 避免同时启用
Scene.background = hdrTexture和Scene.environment:前者只影响背景色,后者才驱动 PBR 材质反射;两者混用会导致曝光冲突
灯光阴影在后处理链里突然变淡或消失?
阴影是光栅化阶段由 WebGLRenderer 生成的深度信息,EffectComposer 默认的 RenderPass 会把阴影一并渲染进去。但如果后续加了 FXAA 或 UnrealBloomPass,它们可能模糊或压制阴影边缘的对比度,造成“阴影发灰”。
- 把
RenderPass放在EffectComposer链最前端,且确保其clear = true,避免上一帧残留干扰阴影 - 禁用
FXAA的edgeThreshold(默认 0.0625):值过高会把阴影边缘误判为锯齿而过度平滑 - 若使用
OutlinePass等基于深度的通道,需确认renderPass输出包含深度缓冲(renderPass.renderToScreen = false时默认包含) - 阴影软硬程度由光源的
shadow.mapSize.width/height决定(建议 1024 或 2048),跟后处理无关;但BokehPass会覆盖景深,导致阴影虚化失真,二者慎叠用
最容易被忽略的是:灯光参数(尤其是 intensity 和 distance)与后处理阈值(如 Bloom.threshold、Outline.edgeStrength)之间没有自动映射关系,必须手动对齐数值量级。一个 PointLight 强度设成 100,在未开 gamma 校正时,Bloom 可能根本捕获不到它的高光——这不是 Bug,是管线设计使然。











