第 8 章 雾化:为什么远处的山看不清
这是你专门点名想搞懂的。好,咱们把它从”一个模糊的滑块”拆成”一套解决问题的工具”。
先问你一个生活里的观察:
你站在山脚下往远处看,近处的树清清楚楚,稍远的山轮廓还在,但颜色发灰发蓝;再远一点的山,几乎和天空融成一片,只剩个淡淡的影子。为什么越远越”糊”?
这不是你视力不好,是空气在捣乱。
8.1 自然现象:空气透视(Aerial Perspective)
现实里,你和远山之间隔着几公里的空气。空气里飘着水汽、尘埃、微粒。光从远山出发,要穿过这层”脏玻璃”才能到你眼睛。
每一次穿过微粒,都有一部分光被散射掉、改变方向;同时,周围环境的光(尤其是天空的蓝光)被这些微粒散射进你的视线。结果是:
- 距离越远 → 穿过的大气越厚 → 原本的物体颜色越被”冲淡”。
- 被冲淡的方向,是天空 / 环境光的颜色(白天偏蓝,所以远山发蓝)。
- 对比度下降,细节消失,最后只剩个色块。
画家早就把这叫空气透视——你画风景时,故意把远处的山画得淡、画得蓝,画就”有纵深感”了。这是人类几百年前就从现象里总结出的规律。
所以”远处看不清”不是 bug,是真实世界的物理。游戏要想”像真的”,就得复刻它。
8.1.5 散射的两种机制:天空为什么蓝、雾为什么灰白
8.1 说”光被空气微粒散射、环境光被散射进视线”,这句太粗,值得拆成两种真实物理,因为它直接决定了雾该用什么颜色:
-
瑞利散射(Rayleigh):空气分子(氮、氧)比可见光波长还小,它们对短波(蓝、紫)的散射远强于长波(红)。所以白天天空被”散射来的蓝光”填满 → 天是蓝的;而傍晚太阳斜射、光穿过更厚的大气,蓝紫早被散射光了,只剩红橙能直达你眼 → 夕阳红。回到游戏:远山发蓝,正是瑞利散射把天空的蓝光混进了你的视线——这给了你”雾色该取天蓝”的物理依据。
-
米氏散射(Mie):雾、云、霾里的水滴/尘埃比可见光波长大,它们对各个波长的散射差不多均匀,于是呈现白、灰白。这就是为什么浓雾是白茫茫一片,而不是蓝的。
所以”雾色取天蓝还是灰白”不是美术拍脑袋:晴天远山偏蓝(瑞利主导),阴雨/沙尘的雾偏灰白(米氏主导)。你理解了这两种散射,调 Fog Color 时就是在”选一种天气的物理”,而不是在”选一个好看的颜色”。
8.2 问题:游戏为什么要”故意”把远处弄糊
你可能会说:复刻真实感我懂,但游戏里”看不清”难道不是缺点?玩家明明想看清楚远处有没有敌人啊。
这就引出关键了——游戏做雾,不单为了好看,更是为了省钱和遮丑。我拆成三个真实问题:
问题一:性能——看不清的东西,就别画那么细
回到第 1 章的”餐厅”比喻。远处一座山,玩家根本看不清它的纹理细节。如果你还老老实实给这座远山贴 4K 高清贴图、算精确光照,那就是在 16 毫秒里白烧算力。
更狠的招是距离剔除(Distance Culling):远处的草、石头、敌人,直接不画了。但问题来了——你不画,玩家就会看见”世界突然缺了一块”,像照片被剪掉一角,非常出戏。
雾正好用来遮这个丑:你把远处设成”全是雾色”,那么”不画远处物体”和”远处被雾遮住”在视觉上几乎无法区分。于是你可以名正言顺地偷工减料——远处不画、不精细、不计算,反正它被雾淹没了,玩家发现不了。
一句话:雾是”偷性能”的合法掩护。 没有雾,你就得老老实实画到天边。
问题二:边界隐藏——别让玩家看见”世界尽头”
游戏世界再大,也有个边界。如果你的可视距离无限,玩家会看到”地图边缘的悬崖”或”一片空荡荡的虚空”,瞬间出戏。
经典处理:把”可视距离”卡在一个值(比如 500 米),500 米外不渲染。但为了不让玩家一眼看穿”500 米外是墙”,就在 300–500 米这段加上浓雾,让边界柔和地溶进雾里。雾成了一道温柔的窗帘,遮住了世界的边缘。
问题三:真实感——纵深感来自”不清”
人眼判断”哪个近哪个远”,一个强烈线索就是”清 vs 糊”。全是清晰的画面,反而像贴纸、像沙盘模型,没有空间感。适度的雾,让近处锐利、远处朦胧,纵深感立刻就出来了。
8.3 方案:怎么用数学描述”越来越糊”
现在工程师要拿出一个可计算的办法:给定”这个物体离摄像机有多远”,算出”它该被雾盖住多少”。
核心思想就一句:最终颜色 = 物体原本颜色 和 雾颜色 的混合(mix),混合比例由距离决定。
- 离得近 → 多用物体本色,少用雾色。
- 离得远 → 多用雾色,少用物体本色。
- 远到极致 → 全是雾色,物体彻底消失在雾里。
这个”混合比例”叫 fogFactor(雾因子,取值 0~1,1 表示完全清晰、0 表示完全被雾吞没)。不同”距离→fogFactor”的公式,就是不同的雾模式。
线性雾(Linear Fog)
最简单:设一个起点 start 和终点 end。
当 distance <= start: fogFactor = 1 (完全清晰,雾还没开始)
当 start < distance < end:fogFactor 从 1 线性降到 0
当 distance >= end: fogFactor = 0 (完全被雾吞没)
公式:fogFactor = (end - distance) / (end - start)。
直觉:从 start 米开始起雾,到 end 米彻底糊死,中间匀速变糊。
指数雾(Exponential Fog)
真实大气的散射不是匀速的,而是越远越剧烈——前面几米变化小,后面几十米迅速糊掉。这用指数描述更贴切:
fogFactor = exp( -density * distance ) (Exp 模式)
或
fogFactor = exp( -(density * distance)^2 ) (Exp2 模式,更陡)
这里的 density(密度)就是”空气多浑”。density 越大,雾越浓,几米外就糊了;density 越小,雾越淡,要很远才起效果。
注意看:线性雾用
start/end两个距离参数;指数雾只用density一个参数。这就是为什么你在 Unity 里切Fog Mode时,某些滑块会灰掉——模式变了,控制的参数也变了。这点下面马上拆。
8.3.5 那行”混合”在 shader 里到底长什么样(先预告)
8.3 那句”最终颜色 = 物体色 与 雾色 的混合”,听着像散文,落到代码其实极其朴素——就是一个线性插值(lerp):
最终颜色 = lerp(物体原本颜色, 雾颜色, 1 - fogFactor)
lerp(a, b, t) 就是”从 a 到 b 按 t 比例取中间值”:t=0 全是 a(物体本色),t=1 全是 b(雾色)。这里 t = 1 - fogFactor,所以当 fogFactor=1(近、清晰)时 t=0,取物体色;fogFactor=0(远、糊死)时 t=1,取雾色。完美对应 8.3 的描述。
而且 fogFactor 被 exp() 这类公式天然夹在 0~1 之间,所以混出来的颜色绝不会”过冲”——你不用担心远处物体变成比雾色更夸张的东西。
这一行你先记着。等第 33 章”动手二:在 Shader 里亲手写出雾”,你会自己把 fogFactor 从”视空间深度”算出来,再写下这行 lerp。到时候你会回头感谢 8.3 埋的这个钩子:雾不是贴上去的滤镜,是逐像素按深度算出来的插值。
8.4 参数解读:那几个旋钮各管什么
Unity 里雾在 Window → Rendering → Lighting → Scene(或 RenderSettings) 的 Fog 区。核心参数:
- Fog(开关):开不开雾。关掉,下面全无效。
- Fog Mode(模式):
Linear/Exp/Exp2。决定用哪套”距离→浓度”公式(见上)。 - Fog Color(雾颜色):远处物体”溶进”什么颜色。实战里几乎总设成和天空盒(Skybox)一样的颜色——这样雾的边界就隐形了,远山不是”变白”,而是”变成天空的颜色”,天衣无缝。
- 思考题先埋着:如果雾色设成鲜红色,远处会怎样?(答案在参考答案)
- Fog Start Distance(Linear 专用):起雾距离。近于此距离完全清晰。
- Fog End Distance(Linear 专用):彻底糊死的距离。
- Fog Density(Exp / Exp2 专用):雾的浓度。0.01 很淡,0.05 很浓。
调参直觉(记住”它对付什么问题”就很好拧):
| 你想达到的效果 | 改哪个参数 | 怎么改 |
|---|---|---|
| 远处轻轻有点朦胧感,不挡视线 | Linear + 大 Start/End | Start 拉远(如 50),End 很远(如 800) |
| 想藏住 500 米外的边界 | Linear | End 设在 500,雾色=天空色 |
| 恐怖游戏那种”几步外就啥也看不见” | Exp2 + 大 Density | density 0.05~0.1 |
| 海底 / 沙尘暴那种”到处都浑” | Exp + 中等 Density + 雾色偏蓝绿 | density 0.02~0.04 |
| 远山发蓝的真实空气透视 | Linear + 雾色取天蓝 | Start/End 调远,让过渡自然 |
看到了吗?每个参数都不是孤立的旋钮,而是”对付某个具体问题”的扳手。 你先想”我要解决视觉里的什么问题”,再去拧对应的那个,就不会瞎调了。
8.5 举一反三:雾还能干什么
理解了”雾 = 按距离把物体色混进某个颜色”,你会发现它根本不只能做”山间的雾”。
- 战争迷雾(Fog of War):策略游戏里”没探索的区域是黑的”。这其实不是大气雾,而是另一套”可见性遮罩”,但名字借了 fog。本质是”按条件把某区域混成黑色”。
- 水下 / 沙尘 / 毒气:把雾色调成蓝绿、土黄,density 调高,整个场景就”泡”在另一种介质里。换的只是颜色和数字。
- 梦境 / 回忆滤镜:雾色偏白、偏柔,配合后处理(第 14 章),能做出”记忆里模模糊糊”的质感。
- 体积雾(Volumetric Fog):上面讲的都是”离摄像机越远越糊”的均匀雾。高级做法是”雾本身有形状”——一束光打进雾里能看见光柱(丁达尔效应)。那是另一层复杂度,但底色还是同一个想法:光在介质里被散射。
你看,一旦你抓住”雾的本质是按距离混合颜色”,它从”天气效果”升级成了”一种通用的空间混合工具”。这就是理解原理带来的自由度。
8.5.5 雾、景深、后处理:都能”远处柔和”,但机制不同
理解了雾的本质,你会发现还有两个效果也能让”远处变柔和”,新手容易把它们和雾混为一谈。这里一次厘清(深层的会由第 30 章后处理、第 33 章 shader 展开):
-
雾(Fog):在物体着色阶段,按”该像素离摄像机的深度”把物体色混进雾色。它是逐物体、逐像素的,跟着每个物体的材质走。最便宜,且天然”谁远谁糊”。
-
景深(Depth of Field, DOF,第 30 章):模拟镜头对焦——对焦平面清晰,离焦处被”模糊”。它不是颜色混合,而是对画面做模糊卷积,模拟光学。机制和雾完全不同:雾是”远处变成雾色”,DOF 是”远处变模糊但仍见轮廓”。两者可叠加(远处既发蓝又模糊,电影感拉满)。
-
后处理雾(Post-process Fog):把整屏深度图拿出来,在后处理阶段统一按深度混雾色。它和”物体着色雾”结果相似,但走的是”全屏一遍 pass”的路子,好处是能统一控制、能配合体积效果,代价是多一次全屏计算。
一句话记牢:雾是着色时的深度插值,DOF 是镜头的模糊,后处理雾是把雾挪到全屏阶段做。三者都能制造”空间感”,但成本与可控性各异——你调参前先想清楚”我要的是哪一种柔和”,才不会把景深的模糊当雾去拧 Density。
8.6 收个尾,连回主线
回到第 1 章那句话:游戏里很多效果是为了在”实时”约束下省钱、遮丑、又显得真。 雾是教科书级的例子:
- 真实现象:空气透视。
- 顺带解决的问题:性能(远处可偷工)、边界(藏世界尽头)、纵深感。
- 落进引擎:Fog Mode / Fog Color / Start-End / Density。
- 你能做的:不只做雾,还能做海底、战场迷雾、梦境。
下一章开始进入”声音”——你会发现,声音”存进计算机”这件事,同样是从一个自然现象(波)出发,为了解决”连续的东西没法直接存”的问题,才发明出采样、量化、压缩这一整套方案。思路和雾完全一致:先有现象和问题,才有参数。
8.7 动手试:在 Unity 里 5 步看到雾
光看不练记不牢。开一个空场景:
Window → Rendering → Lighting → Scene标签,勾选 Fog。Fog Mode选 Linear,Fog Color用吸管取天空盒颜色。Start设 20,End设 200。- 摆几个方块,离摄像机从近到远排开。
- 你会看到:近处方块棱角分明,远处方块溶进天空色。
再做两个对照实验加深理解:
- 把
Fog Color改成鲜红 → 远处变红,像置身异星。验证”雾色 = 远处溶进的颜色”。 - 把
Fog Mode改Exp2、Density拉到 0.05 → 近处几米就糊死。验证”指数雾用单个密度参数控制衰减”。
8.8 常见翻车
- 雾色和天空盒不一致:远处物体溶进雾色,背景却是天空色,物体边缘出现一圈明显分界。修法:雾色 = 天空盒主色。
- 雾太浓导致远处全白/全灰:多半
End太小或Density太大,玩家看不见任何远处目标。修法:先想”我要藏的是哪段距离”,再把End设在那之外。
8.9 性能账本:雾本身几乎不花钱,它”掩护”省下的才是大头
最后算一笔账,免得你对雾有错误的心智——以为”开了雾会变卡”。
雾本身极廉价。 它每个像素只做一次插值(lerp),比起你场景里成千上万个三角形的顶点变换、光照计算,这点开销可以忽略。所以开雾几乎不会拖性能。
那雾的”性能价值”在哪?在 8.2 说的”掩护”:因为远处被雾淹没、视觉上合理,引擎可以名正言顺地不对远处做昂贵的事——
- 距离剔除(Distance Culling):远处 1000 丛草,本来每丛都要一次 Draw Call、一堆顶点。开了雾并把可见距离卡在雾浓处,其中 900 丛直接不渲染,省下的是这 900 丛的 Draw Call 和顶点,不是雾那点插值。
- LOD(细节层次,第 14 章):远处模型换成低面数版本,反正看不清,连回 8.2 的”偷工”。
所以真正吃性能的从来不是雾,而是”你有没有借雾的掩护把远处省掉”。排查口诀:游戏卡顿,先别怪雾(它不是瓶颈),去查远处物体有没有剔除、LOD 有没有生效、Camera.farClipPlane 是不是被拉得太大导致一堆东西被迫画。
另外点破一个名字误会:战争迷雾(Fog of War)不是大气雾。它是”可见性遮罩”——未探索区域被一层黑/灰盖住,本质是逻辑判定”这块地你看到没”,常在后处理或单独图层做,和”空气透视”毫无物理关系,只是借了 fog 这个词。以后你做策略游戏要做”战争迷雾”,走的是遮罩/后处理路线,不是调 Fog Density。
8.10 配方卡:不同游戏类型怎么设雾 + 体积雾一句话
理论落到”开新项目先拧哪个”,给你一张速查配方(连回第 25 章”第一眼氛围”——雾是成本最低的定调手段):
| 游戏类型 | Fog Mode | 关键参数 | 雾色 | 想要的氛围 |
|---|---|---|---|---|
| 开放世界 / 大场景 | Linear | Start 远(如 200)、End 极远(如 2000) | = 地平线色 | 远处自然淡出,藏住地平线接缝 |
| 恐怖地牢 / 密林 | Exp2 | Density 0.05~0.1 | 近黑 / 冷灰 | 几步外啥也看不见的压迫感 |
| 水下 / 深海 | Exp | Density 0.03~0.05 | 蓝绿 | ”泡在水里”的浑浊介质感 |
| 沙漠 / 沙尘暴 | Exp | Density 0.02~0.04 | 土黄 | 到处都浑、方向感模糊 |
| 赛博朋克雨夜 | Exp2 + 后处理 | Density 中等 | 偏品红/青 | 霓虹在雾里晕开(连第 30 章 Bloom) |
做你的塔防 / 大富翁时,第一步就定:雾色 = 天空盒主色,再按”你想要玩家多远开始看不清”选模式——这一步几乎零成本,却奠定了整个场景的呼吸感。
体积雾(Volumetric Fog)一句话:本章前面讲的都是”均匀雾”,只认”离摄像机多远”。高级做法是让雾本身有体积和形状——一束光打进雾里能看见光柱(丁达尔效应),雾会随高度、随光源变化。它的底色仍是 8.1 的”光在介质中被散射”,只是散射被放进了 3D 体积里逐点计算,通常在 HDRP 或后处理管线做,代价更高。你先把均匀雾玩透,体积雾是锦上添花。
8.11 一句收口:雾的排查速查
把 8.4、8.8 的零散经验收成一个速查,省得你下次对着屏幕发愣:
| 你看到的异常 | 第一反应 | 怎么拧 |
|---|---|---|
| 远处物体边缘有一圈明显分界 / 色差 | 雾色 ≠ 天空盒颜色 | 雾色吸管取天空盒主色 |
| 远处啥都看不见,玩家抱怨”盲” | End 太小 / Density 太大 | 想清楚”要藏的是哪段距离”,把 End 推远或 Density 调小 |
| 远处物体忽隐忽现、像在闪 | 雾没盖住”距离剔除”的边界 | 让雾浓度范围 ≥ 剔除距离,或调远 Camera.farClipPlane |
| 雾色太鲜艳(红/紫)导致氛围怪 | 美术误把雾当”滤镜”用过头 | 回到 8.1:雾色 = 介质散射色,自然天气里不会是纯饱和色 |
最后一句心法:雾不是用来”制造炸裂效果”的银弹,是用来”让世界合理地收尾”的工具。 你先用它把远处安稳藏好、把边界温柔溶掉,再去谈 Bloom、体积光那些花活——顺序错了,画面再花也立不住。
【思考题】
- 现实里”远处山发蓝”的物理原因是什么?和”山本身涂了蓝漆”是一回事吗?
- 游戏里雾除了”好看”,还解决了哪两个很实际的工程问题?分别解释。
- 线性雾和指数雾的控制参数有什么不同?为什么切换模式时有的滑块会变灰?
- 如果把 Fog Color 设成鲜红色、Fog Density 设很大,场景会呈现什么效果?这能用来做什么风格的游戏?
- 为什么说”雾是偷性能的合法掩护”?它和”距离剔除”是怎么配合的?
【参考答案】
- 物理原因是光在穿过远处空气时被散射、且环境光(天空蓝光)被大气微粒散射进视线,远山本体色被冲淡并向天空色偏移,所以发蓝。这和”山涂了蓝漆”完全不是一回事:蓝漆是物体自身反射蓝光;空气透视是介质对光的改造。画家画远山用蓝,是模拟后者。
- 另两个工程问题:(a) 性能——远处看不清,就不给它画高清细节甚至直接不画(距离剔除),雾把”没画清”的事实遮住;(b) 边界隐藏——把可视距离卡在雾浓处,玩家看不见世界尽头/地图边缘。两者都靠”远处本来就该糊”这个视觉合理性的掩护。
- 线性雾用
Start/End两个距离参数控制”从哪开始、到哪糊死”;指数雾只用Density一个参数控制浓度(指数衰减)。切换模式时,不属该模式的参数无意义,引擎就把它灰掉(例如选 Exp 后,Start/End 失效变灰,只留 Density)。 - 场景会”越远处越红、最终溶进红色”,像身处血色空间或火星尘暴。这种风格适合恐怖、末日、异世界、赛博空间等需要压抑/异样氛围的游戏。也说明:雾色是”远处溶进什么颜色”的掌控点,不限于自然天色。
- 因为”远处看不清”在真实世界里本就合理,玩家不会怀疑。于是引擎可以在雾的浓度范围内,对远处物体降低细节、延迟加载甚至完全不渲染(距离剔除),玩家既看不出破绽、又省下了算力。雾提供了”可以偷工而不穿帮”的视觉借口,所以是”合法掩护”。