经纬志
首页 / three.js / 教程

后处理

先看结论

后处理把渲染结果当成一张图片,再叠加几道处理。它适合统一画面质感, 但也意味着每一道工序都是一次全屏渲染,链路越长越费。

最后验证 2026-11-03 · three.js 0.160.0 · 难度:进阶 · 核验 2026-10-29 · 引用本文

搭建一条最小的后处理链

EffectComposer 接管渲染流程,RenderPass 负责把场景画进缓冲,后续 Pass 依次处理。最后必须有一个输出 Pass, 否则颜色空间不会转换,画面偏暗。

import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';

const size = new THREE.Vector2(
  renderer.domElement.clientWidth,
  renderer.domElement.clientHeight
);

const composer = new EffectComposer(renderer);
composer.setSize(size.x, size.y);

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

const bloom = new UnrealBloomPass(size, 0.55, 0.4, 0.82);
composer.addPass(bloom);

composer.addPass(new OutputPass());

renderer.setAnimationLoop(function () {
  composer.render();          // 不再直接 renderer.render
});

UnrealBloomPass 的三个数值依次是强度、半径、阈值。 阈值过低会让整个画面发光,路网和文字都会糊成一片; 城市夜景场景一般设在 0.8 以上。

Pass作用顺序开销
RenderPass渲染场景到缓冲必须第一个正常渲染开销
UnrealBloomPass高光泛光渲染之后多级降采样,较高
SMAAPass抗锯齿泛光之前中
OutputPass颜色空间与色调映射必须最后一个一次全屏拷贝

分辨率与像素比

Composer 的尺寸要跟随渲染器,但不必等于物理像素。 在高像素比设备上,把后处理缓冲降一档能省下大量填充率。

function resize() {
  const w = renderer.domElement.clientWidth;
  const h = renderer.domElement.clientHeight;

  camera.aspect = w / h;
  camera.updateProjectionMatrix();

  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  renderer.setSize(w, h, false);

  composer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));
  composer.setSize(w, h);
}

window.addEventListener('resize', resize);
resize();

composer.setPixelRatio 与渲染器的像素比可以不同。 前者设为 1.5 表示后处理按 1.5 倍分辨率计算,最终画面会被缩放回画布大小。

按需开关

后处理是纯视觉增益,交互期间可以临时关闭,松手后再打开。 开关的代价是重建渲染目标,所以不要在每一帧反复切换。

let postEnabled = true;

function setPostProcessing(enabled) {
  if (postEnabled === enabled) return;
  postEnabled = enabled;

  bloom.enabled = enabled;
  composer.renderToScreen = enabled;
}

pass.enabled = false 会跳过该 Pass 的绘制,但不会跳过整条链。 要彻底回到直接渲染,应改为调用 renderer.render(scene, camera)。

先对比再启用。把后处理关掉截一张图,再开启截一张同视角的图。 如果差异只体现在亮度,直接调渲染器的 toneMappingExposure 更省性能。

注意事项

  • 最后一个 Pass 必须是 OutputPass,它负责色调映射与 sRGB 输出。
  • 后处理链渲染到离屏缓冲,preserveDrawingBuffer 的截图行为会随之改变。
  • UnrealBloomPass 对透明物体敏感,半透明面容易整片发光,可用图层分离规避。
  • MSAA 与后处理不能同时依赖,启用 Composer 后抗锯齿要改用 SMAAPass 或 FXAA。
  • 移动端上后处理开销接近渲染本身,分辨率与 Pass 数量都要保守。
引用本文

经纬志(2026)。《后处理》。https://www.jingweizhi.com/three/tutorial/post-processing.html(访问日期 2026-11-03)。