深入理解:“4×4 噪声平铺后,重复周期正好是 4×4 像素“

📅 2026/8/24 8:10:16
深入理解:“4×4 噪声平铺后,重复周期正好是 4×4 像素“
这句话有两个概念需要拆开平铺tiling和重复周期。理解了它们你就明白为什么模糊能干净抹除噪声了。一、先搞懂一张 4×4 的纹理怎么盖满全屏屏幕有一两百万个像素但噪声纹理只有 16 个像素4×4。它是怎么覆盖每个屏幕像素的答案是——平铺tiling也就是反复重复贴像贴瓷砖一样。关键代码在这里const vec2 noiseScale vec2(1280.0/4.0, 720.0/4.0); // (320, 180) vec3 randomVec texture(texNoise, TexCoords * noiseScale).xyz; // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ // 这个乘法是平铺的关键TexCoords是屏幕 UV范围[0, 1]。正常查纹理时 UV 也是[0, 1]纹理刚好贴一次。但这里把 UV乘以了 320横向于是采样坐标范围变成了[0, 320]TexCoords 范围 [0 ————————— 1] 屏幕UV × 320 后 [0 ————————— 320] 超出 1 很多倍纹理采样器遇到超过 1 的坐标会怎么做默认是重复模式GL_REPEAT——超过 1 就绕回 0采样坐标0.0 0.5 1.0 1.5 2.0 2.5 ... 320 实际取值0.0 0.5 0.0 0.5 0.0 0.5 ... 小数部分循环 ↑ ↑ 绕回 又绕回于是这张 4×4 纹理就在屏幕上横向重复了 320 次纵向重复了 180 次像瓷砖一样铺满全屏。二、重复周期是 4×4到底什么意思平铺之后屏幕上的噪声值呈现出规律的循环。我们把 4×4 纹理的 16 个值标记为 A~P一张 4×4 噪声纹理16个随机值 ┌───┬───┬───┬───┐ │ A │ B │ C │ D │ ├───┼───┼───┼───┤ │ E │ F │ G │ H │ ├───┼───┼───┼───┤ │ I │ J │ K │ L │ ├───┼───┼───┼───┤ │ M │ N │ O │ P │ └───┴───┴───┴───┘平铺到屏幕上后就变成这样一块块拼接屏幕像素的噪声值分布 ┌───┬───┬───┬───┬───┬───┬───┬───┐ │ A │ B │ C │ D │ A │ B │ C │ D │ ... ├───┼───┼───┼───┼───┼───┼───┼───┤ │ E │ F │ G │ H │ E │ F │ G │ H │ ... ├───┼───┼───┼───┼───┼───┼───┼───┤ │ I │ J │ K │ L │ I │ J │ K │ L │ ... ├───┼───┼───┼───┼───┼───┼───┼───┤ │ M │ N │ O │ P │ M │ N │ O │ P │ ... ├───┼───┼───┼───┼───┼───┼───┼───┤ │ A │ B │ C │ D │ A │ B │ C │ D │ ... ← 纵向也开始重复 │...│ │ │ │ │ │ │ │重复周期是 4×4的意思就是屏幕上每隔 4 个像素横向、每隔 4 个像素纵向噪声值就完全重复一次。任意一个 4×4 的方块里面都装着 A~P 这完整的 16 个值。你可以随便框一个 4×4 区域无论框在哪框在这里 ↓ 或框在这里 ↓错开位置 ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ │ A │ B │ C │ D │ │ C │ D │ A │ B │ │ E │ F │ G │ H │ │ G │ H │ E │ F │ │ I │ J │ K │ L │ │ K │ L │ I │ J │ │ M │ N │ O │ P │ │ O │ P │ M │ N │ └───┴───┴───┴───┘ └───┴───┴───┴───┘ 包含 A~P 全部 16 个 顺序变了但还是 A~P 全部 16 个无论你框在哪个位置一个 4×4 的窗口里永远恰好包含全部 16 种随机值只是排列顺序不同。记住这个结论它就是模糊能抹干净的关键。三、精妙之处模糊核 一个完整周期现在把模糊 Pass请出来。它用的是 4×4 的核对每个像素取它周围 4×4 邻域求平均for (int x -2; x 2; x) for (int y -2; y 2; y) // 4×4 16 个邻居 result texture(ssaoInput, TexCoords offset).r; FragColor result / 16.0; // 求平均关键来了——模糊核大小4×4正好等于噪声重复周期4×4。这意味着每个像素做模糊时它盖住的 4×4 邻域恰好包含 A~P 全部 16 种随机旋转对应的 AO 结果。对任意一个像素做 4×4 模糊 ↓ 盖住的 16 个邻居用的随机旋转恰好是 A~P 全套 ↓ 相当于这个像素综合了 16 个不同方向的采样结果 ↓ 16 种随机旋转的偏差被平均后互相抵消 ↓ 噪声图案 → 被完美抹平零残留 ✅为什么这样就零残留因为噪声是高频的每个像素都在跳变但它的图案每 4×4 就循环一次。当你用一个正好 4×4 的窗口去平均时——无论窗口滑到哪个位置平均的都是同一套 16 个值得到的平均结果处处相同。像素1 的 4×4 平均 (AB...P) / 16 像素2 的 4×4 平均 (CD...N) / 16 ← 顺序不同但还是那 16 个值 像素3 的 4×4 平均 (FG...E) / 16 ← 同样是那 16 个值 ↓ 所有像素的平均结果趋于一致 ↓ 噪声造成的忽明忽暗被彻底抹平这就是精妙所在噪声的重复周期和模糊核尺寸严丝合缝对齐导致模糊后每个像素吃进的随机样本集合完全相同噪声图案被数学上干净地消除。四、反面对比如果不对齐会怎样情况 A噪声是全屏随机的周期无限大不重复全屏随机噪声每个像素的值都独一无二没有循环 ↓ 4×4 模糊核只能盖住随机的一小片 ↓ 像素1盖住的 16 个值 ≠ 像素2盖住的 16 个值毫无规律 ↓ 每个像素的平均结果都不同 → 噪声抹不干净画面残留颗粒感 ❌情况 B噪声周期是 4×4但模糊核用 3×3不对齐3×3 模糊核9个样本盖不满 4×4 的一个完整周期16个值 ↓ 每个像素只平均了 A~P 中的一部分且各不相同 ↓ 噪声残留抹不干净 ❌只有当噪声周期和模糊核尺寸完全相等时才能做到零残留。这就是为什么二者必须配对设计。五、一个直观的类比想象一排灯泡在闪烁规律是每 4 个一组循环闪灯泡状态亮 暗 亮 暗 | 亮 暗 亮 暗 | 亮 暗 亮 暗 | ... └── 4个一组 ──┘现在你戴一副能看到相邻 4 个灯泡平均亮度的眼镜 4×4 模糊核无论你看哪 4 个连续灯泡里面永远是2 亮 2 暗平均下来处处都是同样的中等亮度→ 你看到的是一片均匀的柔光完全感觉不到闪烁但如果灯泡是完全随机乱闪的无周期你的4 灯平均眼镜就没法把它抹匀——这里平均是偏亮那里平均是偏暗还是能看出忽明忽暗。噪声 模糊的关系就是这副眼镜和灯泡闪烁周期的关系周期对齐才能看到完美的均匀。六、总结4×4 噪声平铺后重复周期是 4×4 的精妙之处 1. 平铺 → 4×4 纹理靠 UV × 320 在屏幕上反复重复贴满 2. 重复周期 4×4 → 屏幕上任意 4×4 方块都恰好含全部 16 个随机值 3. 模糊核也是 4×4 → 每个像素模糊时恰好平均完整一套 16 种旋转 4. 结果 → 所有像素平均的是同一套值噪声被数学级地彻底抹平 本质规律 噪声重复周期 模糊核尺寸 → 零残留 二者不匹配 → 抹不干净这不是巧合而是故意让两个模块的尺寸精确对齐的设计——单看噪声觉得太小气看懂它和模糊的配合才明白 4×4 是为整条管线量身定做的黄金数字。