经纬志
首页 / three.js / 使用示例

后期处理

把场景先渲染到纹理,再叠加泛光与色调映射,观察高亮区域如何向外扩散。

three.js 0.160.0 · 更新 2026-10-28
源码与运行效果
运行效果

说明

EffectComposer 维护一条渲染链,每个 RenderPass 与后处理 Pass 依次读写屏幕纹理。示例只用了三个:先渲染场景, 再叠加泛光,最后由 OutputPass 统一做色调映射与色彩空间转换。

泛光强度、阈值都做成了滑杆。阈值决定多亮的像素会参与扩散, 强度决定叠加的倍数,半径影响扩散范围。 关闭泛光时只是把该 Pass 的 enabled 设为 false,渲染链本身不变。

场景中的柱子使用自发光材质,亮度远高于其他物体, 因此泛光只在柱体与环结高光处出现,不会把整幅画面糊成一片。

设置数值说明
泛光强度0 – 2.4UnrealBloomPass 的 strength
泛光阈值0 – 1低于阈值的像素不参与提取
扩散半径0.5越大越朦胧,本例固定
主体材质金属度 0.92、粗糙度 0.24高光集中,便于观察泛光边界
自发光柱强度 3.2远超 1.0 的亮度才会被阈值筛出
输出 PassOutputPass色调映射与 sRGB 转换只在这里做一次

管线顺序

顺序不能随意调换。RenderPass 必须在最前, 它负责把场景画进纹理;OutputPass 必须在最后, 它承担色彩管理。把 OutputPass 放到中间, 后面的 Pass 会在已经转换过的颜色上继续计算,画面会偏亮、偏灰。

const composer = new EffectComposer(renderer);
composer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
composer.setSize(width, height);

composer.addPass(new RenderPass(scene, camera));

const bloom = new UnrealBloomPass(
  new THREE.Vector2(width, height),
  0.9,   // strength
  0.5,   // radius
  0.35   // threshold
);
composer.addPass(bloom);

composer.addPass(new OutputPass());

渲染入口要从 renderer.render(scene, camera) 换成 composer.render(),否则后期链不会执行。 容器尺寸变化时,渲染器与 composer 都要 setSize,否则画面会被拉伸。

阈值与强度怎么配

阈值低、强度高时,整个画面都会发亮,暗部细节被泛光淹没; 阈值高时只有最亮的光源参与,效果克制但更接近夜景。 经验区间是阈值 0.6 到 0.9、强度 0.4 到 1.2。

泛光只认亮度,不认材质类型。太阳直射下的白墙、雪地同样会超过阈值, 整片泛白时应当先调高阈值,而不是一味压低强度。

代价

每个 Pass 都要读写一张与画布同尺寸的纹理,泛光本身还有多级降采样。 在高分屏上,pixelRatio 设为 2 会让带宽翻倍, 移动端通常降到 1 到 1.5。地形这类本身就很占填充率的场景, 叠加泛光后帧率下降会比预期更明显。

后期不改变几何。泛光只是屏幕空间的光晕, 不会照亮周围物体,也不会参与遮挡与拾取。 three.js 的后期链是渲染库层面的效果工具,与地理要素的符号化没有关系。