Day 114 · 后期处理进阶 — 辉光与工业调色:画面的"高级感"
Day 109 你已经把
EffectComposer跑起来了(渲染 → OutlinePass 描边)。今天的主题是让画面有"电影感":UnrealBloomPass辉光(工业大屏最出效果的后处理——设备边缘、指示灯、扫描线都带光晕)、以及色彩分级(把整个画面统一成工业深色风,与 Day 66 token 对齐)。同时建立预算意识:辉光是性能大头,叠加要克制。做完,你的车间从"好看"升级到"高级"。
目录
一、后期处理回顾与管线叠加
Day 109 的管线只有两段:RenderPass(正常渲染)→ OutlinePass(描边)。后处理的精髓是任意叠加:
渲染 → 描边 → 辉光 → 调色 → 上屏
↑ ↑ ↑ ↑
RenderPass Outline Bloom ColorAdjust
顺序决定结果:辉光放在描边之后,描边线条也会发光;调色放最后,统一整个画面的色调。每加一段,多一次离屏渲染(性能成本见第五节)。
二、UnrealBloomPass:工业最出效果的辉光
# 后处理 pass 都在 three/examples 里(随 three 安装)
# import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera)); // ① 正常渲染
const outlinePass = new OutlinePass(new THREE.Vector2(w, h), scene, camera);
composer.addPass(outlinePass); // ② 描边(Day 109)
// ③ 辉光:UnrealBloomPass(分辨率, 强度, 半径, 阈值)
const bloomPass = new UnrealBloomPass(
new THREE.Vector2(w, h),
0.6, // strength:辉光强度
0.5, // radius:光晕扩散半径
0.8 // threshold:亮度阈值(高于此值才发光)
);
composer.addPass(bloomPass);
工业大屏的"发光设备"感就来自这行——指示灯、描边、扫描线、高亮色都会被辉光照亮。这也是为什么 Day 113 的 AdditiveBlending 粒子会格外出彩(辉光叠加在它们身上)。
三、辉光的三个旋钮:threshold / strength / radius
记忆钩子:辉光调糊的元凶是 threshold 太低——把阈值抬上去,画面立刻干净。工业风追求"亮的地方亮、暗的地方净",不是全屏泛光。
四、色彩分级:把画面统一成工业风
4.1 为什么需要调色
场景里各种颜色(主色/强调色/告警色/粒子色)混在一起,可能"各自为战"。色彩分级 = 统一色调的最后一笔——就像 2D 大屏的 token 系统(Day 66),3D 画面也需要"整体观感一致"。
4.2 用 Three 的 ColorCorrectionShader 或简单调色
// 方式一:内置 ColorCorrectionShader(简单调色:亮度/对比度/饱和度)
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";
import { ColorCorrectionShader } from "three/examples/jsm/shaders/ColorCorrectionShader.js";
const colorPass = new ShaderPass(ColorCorrectionShader);
colorPass.uniforms["powRGB"].value.set(1.1, 1.1, 1.1); // RGB 幂次校正(提亮)
colorPass.uniforms["mulRGB"].value.set(1.0, 1.0, 1.0); // RGB 增益
colorPass.uniforms["addRGB"].value.set(0.0, 0.0, 0.0); // 偏移
composer.addPass(colorPass);
4.3 更"工业风"的做法:叠加暗角 + 色偏
// 方式二:用自定义 ShaderPass 做"工业冷色 + 轻微暗角"(Day 116 学会写后更自由)
// 思路:画面整体偏青蓝(主色系)+ 四角压暗(聚焦中心)
// 本周先用内置 ColorCorrectionShader 调亮度/对比度/饱和度,够用即可
红线第 3 条精神:调色先用内置工具,够用即可——自写调色 shader 等 Day 116-117 学会 GLSL 后再上。本周目标是"画面统一",不是"炫技"。
五、后期叠加的顺序与预算
5.1 每段 pass = 一次全屏渲染成本
RenderPass 1 次全屏渲染
OutlinePass 若干次(描边依赖深度/法线)
BloomPass ~5 次(辉光的分层模糊,最贵!)
ColorPass 1 次
合计 ≈ 8-10 次全屏渲染 / 帧
辉光为什么最贵:内部做多层降采样模糊(mipmap 式高斯),一次辉光 ≈ 5 次全屏渲染。它是后处理里的大头。
5.2 预算意识(Day 118 的预演)
一句话:后处理每叠加一层都要"值回票价"。辉光出效果但要克制——Day 118 会用 FPS 预算表量化"它花了几 ms"。
六、实战:工业画面(辉光 + 调色)
整合今天内容——把 Day 109 的 createAtmosphere 扩展成"工业氛围管线":
// src/core/three/create-atmosphere.ts(Day 114 扩展版)
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";
import { ColorCorrectionShader } from "three/examples/jsm/shaders/ColorCorrectionShader.js";
/**
* 工业氛围后处理管线:渲染 → 描边 → 辉光 → 调色
* 返回 composer(循环用)、setOutline、dispose
* 预算提醒:Bloom 最贵(~5×),强度/阈值按 3.2 节的推荐设
*/
export function createAtmosphere(
renderer: THREE.WebGLRenderer,
scene: THREE.Scene,
camera: THREE.PerspectiveCamera,
w: number, h: number
) {
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera)); // ① 渲染
// ② 描边(Day 109,选中设备发光圈)
const outlinePass = new OutlinePass(new THREE.Vector2(w, h), scene, camera);
outlinePass.edgeStrength = 4;
outlinePass.visibleEdgeColor.setHex(0x00c6ff);
composer.addPass(outlinePass);
// ③ 辉光(今天核心):让高亮设备/粒子/指示灯发光
const bloomPass = new UnrealBloomPass(new THREE.Vector2(w, h), 0.6, 0.5, 0.8);
composer.addPass(bloomPass);
// ④ 调色:统一工业风(亮度/对比度微调)
const colorPass = new ShaderPass(ColorCorrectionShader);
colorPass.uniforms["powRGB"].value.set(1.05, 1.05, 1.05); // 轻微提亮
composer.addPass(colorPass);
return {
composer,
setOutline(objects: THREE.Object3D[]) {
outlinePass.selectedObjects = objects;
},
/** 关辉光(性能紧急时的降档开关,Day 118 用) */
setBloom(on: boolean) { bloomPass.enabled = on; },
dispose() { outlinePass.dispose(); bloomPass.dispose(); composer.dispose(); },
};
}
注意
setBloom(on)——辉光留一个"可关"的开关。这是性能应急的设计:平时开辉光,FPS 不达标时一键降档。每个贵效果都该配一个降档开关(Day 118 的 FPS 预算哲学)。
七、常见坑点
坑 1:辉光过曝/全屏糊
原因:threshold 太低,大片都发光。修法:threshold 抬到 0.7~0.9(第三节)。
坑 2:辉光让描边"糊成一圈"
原因:描边在辉光前,描边色也被泛光。修法:调 strength/radius,或调整 pass 顺序(第一节)。
坑 3:叠加后性能崩
原因:Bloom 太贵 + 又多叠了效果。修法:用 setBloom(false) 降档,或用预算表逐层砍(第五、六节)。
坑 4:调色后画面发灰/发暗
原因:ColorCorrection 的 powRGB 设太小或色彩空间问题。修法:powRGB 从 1.0 微调到 1.05~1.1,别一次拉大。
坑 5:分辨率变化后辉光尺寸不对
原因:pass 的 Vector2 尺寸没跟着 resize 更新。修法:resize 时同步 bloomPass.setSize(w,h)、outlinePass.setSize(w,h)。
八、自测挑战
T1 · 辉光上手(50 分钟)
在 Day 113 的车间加 UnrealBloomPass,重点看:指示灯、扫描线、粒子是否"发光"。调 threshold 从 0.5→0.9 截三张对比——记住"糊与净"的临界。
T2 · 工业调色(40 分钟)
加 ColorCorrectionShader,把画面调到"深色 + 冷色 + 高光清晰"的工业风。与不加调色的截图对比,写出 3 条"工业风"的视觉特征。
T3 · 预算测量(40 分钟)
用 Performance 面板分别测:只有 Render / +Outline / +Bloom / +Color 四种配置的帧耗时(ms)。把这张表写进笔记——它就是 Day 118 预算表的雏形。
T4 · 降档开关(30 分钟)
实现 setBloom(on) 并绑定一个按键/开关(如按 B 开关辉光)。验证开关生效——这是"可降档"设计的实战。
九、总结
画面有"电影感"了:设备在发光、画面统一成工业色。明天解决"上量不卡"——LOD 与渲染优化。
明日预告:Day 115 LOD 与渲染优化——Level of Detail 多级模型、距离驱动的自动降模、以及可见性剔除(frustum culling),让"50 台设备 + 全效果"也能流畅。