PHASE 2 · 效果工坊

2.4复古与故障

CRT、扫描线、Glitch 与半调印刷

效果工坊最后一站,做「氛围感」:老电视的暖光噪点、赛博朋克的信号故障、漫画海报的印刷网点。这类效果的共同套路是模拟一种「不完美的显示介质」——完美的数字图像反而显得廉价,恰到好处的瑕疵才是味道。技术上,全是前三章工具的组合应用,本章可以当成 Phase 2 的「综合演练」。

1色差:最便宜的高级感

真实镜头对不同波长的光折射率不同,红绿蓝三色会在边缘微微错位——这叫色差(Chromatic Aberration)。模拟它只需要三个通道各采一次样,采样位置略微错开:

GLSL · 径向色差(镜头风)
vec2 dir = uv - 0.5;                    // 从中心指向边缘
float amt = 0.008 * length(dir);        // 边缘错位大,中心为零

float r = texture(uTex, uv + dir * amt).r;   // 红色往外错
float g = texture(uTex, uv).g;               // 绿色不动
float b = texture(uTex, uv - dir * amt).b;   // 蓝色往里错
vec3 col = vec3(r, g, b);

成本三次采样,效果立竿见影:静态图秒变「电影感」,配合运动越剧烈错位越大(把 amt 乘上速度),就是游戏里的受击/冲刺反馈。它也是接下来 CRT 和 Glitch 的固定配料。

2CRT 老电视全家桶

CRT 显像管的味道来自一整套物理特征,每个特征对应一小段代码,像配菜一样自由增减:

特征物理来源Shader 手法
屏幕鼓起玻璃面板是曲面UV 桶形畸变(按到中心距离外推)
扫描线电子束逐行扫描y 方向正弦暗纹(1.1 章条纹)
RGB 荫罩荧光粉三色条排列x 方向按像素周期给 RGB 加权
暗角边缘亮度衰减smoothstep 渐晕(1.1 章)
闪烁 / 噪点信号不稳定uTime 驱动的亮度抖动 + hash 噪点
「叠特征」是复古效果的通用方法论

VHS 录像带、老胶片、Game Boy 屏……做法都一样:先列出那种介质有哪些物理缺陷,再逐个翻译成一两行代码叠上去。VHS = 横向拉丝(行同步误差)+ 色度错位 + 底噪;胶片 = 颗粒 + 划痕(细竖线)+ 呼吸式曝光波动。列清单的能力比写代码重要。

3Glitch:精心策划的事故

故障风的骗术核心:让随机「按块、按节拍」发生,而不是每帧每像素乱跳。三个关键决策全靠 1.5 章的 hash,但喂给它的输入很讲究:

  • 时间量子化:floor(uTime * 8.0) 让随机数每 1/8 秒才换一次——故障是「一顿一顿」的,不是连续抖动;
  • 空间按条带:floor(uv.y * 24.0) 让同一横条内的像素同进退——错位是「整条撕裂」,不是逐像素噪声;
  • 稀疏触发:step(0.75, hash(...)) 只让 25% 的节拍发生强故障——大部分时间正常,偶尔抽风,才像信号问题。

4半调印刷:波普风网点

报纸和漫画用大小不一的网点模拟灰度——离远看是照片,凑近看全是圆点,这叫半调(Halftone)。它和 2.2 章圆点马赛克的区别只有一个,但正是灵魂所在:网格要旋转一个角度(印刷术语叫网角),而且圆点大小由「本像素的亮度」决定,而非格心颜色:

Android 视角 落地场景

这一章的效果在 App 里的真实岗位:CRT/半调做主题化滤镜(相机 App、头像编辑);glitch 做转场和错误态(配合 uProgress,3.5 章的转场框架直接可用);色差做手势反馈(拖拽越猛错位越大,松手回弹)。全部都是「一张输入纹理 + 几个 uniform」,AGSL 一个 RuntimeShader 就装下。

本章小结

  • 色差 = RGB 三通道错位采样,径向错位是镜头感,横向错位是信号感;三次采样买到高级感。
  • CRT = 特征清单逐个翻译:桶形畸变、扫描线、RGB 荫罩、暗角、闪烁噪点;复古效果都按「列介质缺陷 → 逐条实现」的方法论做。
  • Glitch 三决策:时间量子化(按拍抽风)、空间条带(整条撕裂)、稀疏触发(偶尔发作);强度参数化后就是现成的转场。
  • 半调 = 旋转网格 + 本像素亮度定点径;与圆点马赛克的差别在「网角」和「亮度来源」。
  • Phase 2 完结:所有效果 = 坐标手术 + 采样策略 + 材质细节,三件事排列组合。

动手练习

  1. 做 VHS 录像带:按「特征清单」方法论——横向正弦拉丝(y 量子化 + sin 位移)、色度错位(色差的横向版)、画面顶部一条跳动的白噪声带。
  2. 给 Glitch 加「波形干扰」:横向位移不用 hash,改用 sin(uv.y * 40.0 + uTime * 30.0) * 0.02,做出「信号同步失败」的整屏波浪。
  3. 彩色半调:分别用青、品红、黄三种墨色各做一层半调,网角分别取 15°、45°、75°,三层相乘叠加(墨是减色的)——放大看,你会得到和真印刷品一模一样的玫瑰纹。