后期处理
把场景先渲染到纹理,再叠加泛光与色调映射,观察高亮区域如何向外扩散。
说明
EffectComposer 维护一条渲染链,每个 RenderPass
与后处理 Pass 依次读写屏幕纹理。示例只用了三个:先渲染场景,
再叠加泛光,最后由 OutputPass 统一做色调映射与色彩空间转换。
泛光强度、阈值都做成了滑杆。阈值决定多亮的像素会参与扩散,
强度决定叠加的倍数,半径影响扩散范围。
关闭泛光时只是把该 Pass 的 enabled 设为 false,渲染链本身不变。
场景中的柱子使用自发光材质,亮度远高于其他物体, 因此泛光只在柱体与环结高光处出现,不会把整幅画面糊成一片。
| 设置 | 数值 | 说明 |
|---|---|---|
| 泛光强度 | 0 – 2.4 | UnrealBloomPass 的 strength |
| 泛光阈值 | 0 – 1 | 低于阈值的像素不参与提取 |
| 扩散半径 | 0.5 | 越大越朦胧,本例固定 |
| 主体材质 | 金属度 0.92、粗糙度 0.24 | 高光集中,便于观察泛光边界 |
| 自发光柱 | 强度 3.2 | 远超 1.0 的亮度才会被阈值筛出 |
| 输出 Pass | OutputPass | 色调映射与 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 的后期链是渲染库层面的效果工具,与地理要素的符号化没有关系。