导语:做过一个实验。把「回响峡谷」里一间 6m×8m 的灰盒房间交给美术,同一张桌子同一扇窗,要求用光讲四个故事:恐怖、孤独、希望、紧张。她没有移动任何家具,只改了灯光、雾和调色,四张截图放在一起,测试同事猜情绪的命中率是 100%。《最后生还者》的场景氛围,圈内通行的说法是七成靠光——这个数字未必经过严格统计,但关掉 Lumen 再打平你的场景,画面退回上个世代只需要一秒。卷二从这里开门,先学光,再学别的。
本章地图
mindmap
root((光影叙事))
美术补课
三点布光 主光/补光/轮廓光
色温叙事 暖与冷的刻板印象与反用
构图 三分法/引导线/负空间
引擎工具箱
五种光源的性格
曝光与色调分离
体积雾与丁达尔
叙事方法
明暗对比引导视线
四象限氛围配方
回响峡谷实操
医院走廊 恐怖
雨夜天台 孤独
安全屋 希望工程师常把灯当成"照亮就行"的工具,就像把字体当成"能看清就行"的排版。本章要拆掉这个惯性。贯穿全章的案例就是那间灰盒房间:一间 6m×8m、层高 3m 的毛坯房,东墙一扇 1.5m 宽的窗,正中一张桌子。后续每一节学到的工具,都会回到这个房间里做一遍实验,直到第 6 节把它扩成「回响峡谷」的三个标杆场景。
补课:三点布光是三种「光的职责」,不当公式套
补课:本节补美术基础。影视/美术出身可跳过,但第 6 节的光源清单默认你懂这套词汇。
三点布光(Three-Point Lighting)来自摄影棚:主光(Key Light)、补光(Fill Light)、轮廓光(Rim/Back Light)。教科书写得像通用公式,实际上它是一种职责划分——任何场景里的任何一盏灯,你都要能回答"它负责什么"。
- 主光:定义方向。观众潜意识里"光从哪来"的答案,通常也是场景里最强的逻辑光源(窗、太阳、手术灯)。
- 补光:定义宽容度。把主光造出来的阴影抬亮到什么程度,决定画面是"电影"还是"监控录像"。
- 轮廓光:定义分离。从侧后方勾一条亮边,把主体从背景里"撕"出来,尤其在暗场景里。
游戏和摄影棚有一个关键差别:玩家会走动。棚拍的灯位只对一个机位负责,游戏布光要对三百六十度都成立。所以三点布光在游戏里退化为"三层光"——逻辑主光定叙事方向,环境光(天光、Lumen 间接光,见第 7 章)当补光,局部的轮廓光留给关键交互物和敌人。第 6 节的三份光源清单都按这三层组织。
色温是情绪的母语
UE 光源的 Temperature 属性用开尔文(K)表示,勾选 Use Temperature 后生效。几组必须背下来的锚点:蜡烛约 1800K,钨丝灯 2700–3200K,正午日光 5500–6500K(UE 默认 6500K),阴天 7000–8000K,蓝天下的阴影处能到 10000K 以上。注意它和直觉相反:开尔文数值越低越暖,越高越冷。
影视语法沉淀出一套刻板印象:暖等于安全、家、回忆;冷等于危险、疏离、超自然。恐怖片把停尸房打成冷绿,温情片把厨房打成暖黄,观众不需要思考就能接收。这套刻板印象你要先用熟,再谈反用。
反用才是高级叙事。《遗传厄运》用正午暖阳拍不安,《银翼杀手 2049》里最具压迫感的场景泡在橙色尘雾里——当"该安全"的暖色出现在"不该安全"的场合,观众接收到的信号是扭曲而非舒适。「回响峡谷」的医院走廊用的就是这个手法:走廊尽头唯一的暖光源是一盏接触不良的病房灯,暖色在满屏冷绿里反而成了最瘆人的东西。规则是:刻板印象建立预期,打破预期制造情绪。打破的前提是,你先让观众习惯了规则。
五种光源的性格,以及各自最容易踩的坑
UE 5.8 给你五种光源 Actor,各自的"性格"来自物理:发光体尺寸决定阴影软硬,方向性决定叙事指向。
| 光源 | 阴影 | 开销 | 性格 | 典型用途 |
|---|---|---|---|---|
| Directional Light | 全局、硬 | 最低 | 上帝视角,定基调 | 太阳、月亮 |
| Sky Light | 无阴影、均匀 | 低 | 没有性格的性格 | 环境底光、补光 |
| Point Light | 全向、中等 | 中 | 诚实,告诉玩家"这有个灯泡" | 台灯、火堆、应急灯 |
| Spot Light | 锥形、可控 | 中高 | 强指向,天然引导视线 | 手电、射灯、舞台光 |
| Rect Light | 面光源、最软 | 高 | 影视剧标配,最像窗户 | 窗口、广告牌、摄影棚光 |
Directional Light 一场戏只该有一盏。见过不止一个新手关卡摆两三盏平行光"补亮暗处",结果是阴影方向互相打架,空间的逻辑彻底垮掉——观众说不出哪里不对,但会觉得"假"。暗处该由 Sky Light 和间接光负责,不该由第二个太阳负责。
Rect Light 是被低估的叙事武器。它模拟的是发光面,阴影边缘天然柔和,打在墙上的渐变和真实窗户几乎无法区分。代价是开销在五种光源里最高,且不支持 Lumen 的阴影缓存优化时容易成为热点(以官方文档 Light Types 词条的最新说明为准)。一间房里 Rect Light 别超过两三盏,用在镜头一定会停留的地方。
Spot Light 还有两个常被忽略的叙事旋钮:内锥角(Inner Cone Angle)与外锥角(Outer Cone Angle)。二者重合,光斑边缘像刀切,是舞台射灯和审讯灯的气质——人造、强势、有压迫感;内锥收到外锥的一半以内,边缘羽化开来,就成了手电和烛光——自然、脆弱、惹人怜惜。同样是"照亮玩家面前三米",锥角曲线决定了玩家对这份照亮的信任度。恐怖游戏里手电的外锥别超过 35°,给足中央亮度但让边缘迅速衰减,余光区的黑暗才是恐惧的培养基。
移动性(Mobility)三档的取舍在卷一讲 Lumen 时已经展开过(见第 7 章),这里只补一句和氛围相关的:Static 烘焙出来的柔和间接光在 Lumen 时代基本被取代,但 Stationary 和 Movable 的动态阴影成本不同——一盏 Movable Spot Light 每帧重画整张阴影贴图,一个场景里放二十盏,GPU 账单立刻爆炸。
动态光源的数量靠预算管,靠感觉只会超支。「回响峡谷」的预算制度是:单个镜头可见范围内,Movable 投影灯不超过 4 盏(手电占 1 盏),Stationary 不超过 12 盏,Static 不限。美术超预算该怎么办?骂回去?不——让他把 Static 改成 Stationary 前,先想清楚这盏灯的影子需不需要动。
下面这张图梳理光源组件与后处理体积的类关系。Actor 只是容器,真正干活的是 Component;而 PostProcessVolume 不属于任何光源,它是覆盖在镜头上的"最终解释权"。
classDiagram
ULightComponent <|-- UDirectionalLightComponent
ULightComponent <|-- UPointLightComponent
UPointLightComponent <|-- USpotLightComponent
UPointLightComponent <|-- URectLightComponent
ULightComponent <|-- USkyLightComponent
ULightComponent : +float Intensity
ULightComponent : +FLinearColor LightColor
ULightComponent : +float Temperature
ULightComponent : +ELightMobility Mobility
ALight "1" *-- "1" ULightComponent
APostProcessVolume ..> ULightComponent : 覆盖曝光/调色
AExponentialHeightFog "1" *-- "1" UExponentialHeightFogComponent
ULightComponent ..> AExponentialHeightFog : VolumetricScatteringIntensity
class APostProcessVolume {
+FPostProcessSettings Settings
+float BlendWeight
+bool bUnbound
}两个要点。其一,VolumetricScatteringIntensity 挂在灯上,它是这盏灯在体积雾里"显形"的倍率——丁达尔光束靠它调,不靠雾本身。其二,PostProcessVolume 的 bUnbound 为 true 时全图生效,否则按体积范围混合,区域氛围切换就是靠这个混合权重做过渡,第 6 节的伪代码会用到。
曝光决定"看谁",色调分离决定"什么心情"
回到灰盒房间。桌上放一个白色盒子,玩家进门第一眼会不会看它,不取决于盒子本身,取决于它和周围墙面的亮度差。亮度差从哪来?一半来自灯,另一半来自曝光。
UE 的自动曝光(Auto Exposure)模拟人眼虹膜:从暗处走进亮处,画面先过曝再收敛。这套拟真逻辑在电影里是被摄影指导严格锁死的——镜头对准谁,曝光就按谁的脸定。游戏没法锁定玩家的视线,所以默认的自动曝光经常帮倒忙:玩家在暗走廊里打开手电,自动曝光把整体拉亮,恐怖感瞬间稀释。
对策是把曝光从"自动"改成"有界的自动":在 PostProcessVolume 里把 Metering Mode 设为 Manual 或给 Auto Exposure 限定 Min/Max EV100 的窄区间(比如 -1 到 +2),让曝光只在小范围内补偿,绝不翻身做主。
EV100 的手感需要几组锚点:正午阳光大约 EV15,明亮的室内 EV8–10,夜晚路灯街道 EV5 上下,满月照亮的环境接近 EV0,再往下就是星光。UE 里 Directional Light 用 lux 计量、曝光用 EV100 补偿,两套单位隔着一道换算,但调参时不用算——记住"室内戏把 Min EV100 锁在 -1 附近,暗部就永远保留 2 档以上的黑",比记公式管用。锁完区间再去动灯的强度,顺序反了会得到一个怎么调都不暗的恐怖游戏。
色调分离(Split Toning)是电影调色的祖传手艺:阴影和高光分别上色。UE 5.8 的 Color Grading 面板把它拆成了 Shadows / Midtones / Highlights 三组 Lift-Gamma-Gain 控制,比老版本的单一 Split Tone 更细。好莱坞的默认配方是"阴影压青、高光提暖"(teal & orange),因为肤色在暖区,背景推向青蓝,主体自动分离。
「回响峡谷」的用法更克制:安全屋的高光提 5% 暖橙,阴影不动;医院走廊的阴影压 8% 青绿,高光不动。只染一端,染得轻,观众说不出来但感觉得到。两端都重染,画面就成了廉价滤镜。
下面这段 C++ 演示用代码给一个 PostProcessVolume 设置曝光与调色参数。运行时切换氛围预设走的就是这条路——改 Settings,不动 Actor。
void AAtmosphereVolume::ApplyPreset(const FAtmospherePreset& P)
{
FPostProcessSettings& S = Volume->Settings;
// 曝光:收窄自动曝光区间,让暗部保持暗
S.bOverride_AutoExposureMinBrightness = true;
S.bOverride_AutoExposureMaxBrightness = true;
S.AutoExposureMinBrightness = P.EVMin; // 医院走廊: -1.0
S.AutoExposureMaxBrightness = P.EVMax; // 医院走廊: 1.5
S.bOverride_ExposureCompensationCurve = true;
// 色调分离:只染阴影,压向青绿
S.bOverride_ShadowsGamma = true;
S.ShadowsGamma = FVector4(P.ShadowTint.R, P.ShadowTint.G,
P.ShadowTint.B, 1.0f);
// 全局对比度与饱和度的微调
S.bOverride_ColorContrast = true;
S.ColorContrast = FVector4(P.Contrast, P.Contrast, P.Contrast, 1.0f);
Volume->BlendWeight = 1.0f; // 权重由区域混合逻辑控制
}参数集中在一个 FAtmospherePreset 结构里,美术在 DataAsset 里调,程序只负责应用。氛围是数据,不是硬编码——这条原则第 6 节的区域切换会继续用。
体积雾:氛围的放大器,也是 GPU 的碎钞机
丁达尔效应——光柱、光束、光穿破窗棂的那几道"实体光"——是氛围叙事里最贵也最有效的一招。UE 5.8 里它的技术底座是体积雾(Volumetric Fog):把视锥切成体素网格(默认约 160×90×128 的 Froxel),逐格计算光的吸收与散射。每盏灯的 VolumetricScatteringIntensity 决定它在雾里留多深的痕迹。
这笔账必须算清。体积雾的成本与体素分辨率近似成正比,官方给了两个主旋钮:r.VolumetricFog.GridPixelSize(屏幕空间格子尺寸,默认 8)和 r.VolumetricFog.GridSizeZ(深度分层数,默认 128)。格子切得越细,光束边缘越干净,账单越长。
| 档位 | GridPixelSize | GridSizeZ | 1080p 下 GPU 增量(RTX 3080 量级) | 观感 |
|---|---|---|---|---|
| 低 | 16 | 64 | 约 0.5–1 ms | 光柱有锯齿,雾分层可见 |
| 中(默认) | 8 | 128 | 约 1–2.5 ms | 电影可用的下限 |
| 高 | 4 | 192 | 约 3–6 ms | 锐利光柱,暗角处仍有噪点 |
| 超高 | 2 | 256 | 约 6–12 ms | 截图级,帧率杀手 |
数量级比精确值重要:雾从默认档拉到超高,一帧可能多出 10ms——60fps 的预算总共才 16.6ms。「回响峡谷」的策略是按场景配档:医院走廊(雾是主角)给中档偏上,雨夜天台(雨幕本身遮挡视线)给低档,安全屋只需要窗口一道光柱,中档即可。全图统一超高,是把预算烧在没人看的地方。
对应的控制台调参就这几行,建议在灰盒阶段就逐个试过,对手感建立直觉:
; 体积雾开关与三档快调(开发机 RTX 3080 / 1080p 验证)
r.VolumetricFog 1 ; 0 即关闭,立刻省 1-2.5ms
r.VolumetricFog.GridPixelSize 8 ; 16=低 8=中 4=高
r.VolumetricFog.GridSizeZ 128 ; 深度层数,配合上面成对调
r.VolumetricFog.HistoryWeight 0.9 ; 时间抗噪权重,降它雾更"活"但更闪灯这一侧也有账。雾中每盏投下散射的灯都要逐格积分,一盏 VolumetricScatteringIntensity 调大的 Movable Spot Light,成本翻倍于它在屏幕上的光斑面积。所以光束要用少而准的灯制造:一扇破窗配一盏定向光把 Scattering 拉到 2–3,比摆十盏小灯出效果,还便宜一个数量级。
光出问题时,按这棵排查树走,别瞎调:
flowchart TD
A[画面不对] --> B{问题是脏还是平?}
B -- 脏: 漏光/噪点/闪 --> C{Lumen 场景?}
C -- 是 --> D[检查 Surface Cache 覆盖
见第 7 章排查清单]
C -- 否 --> E["雾的时间抗噪:
HistoryWeight 提到 0.9+"]
B -- "平: 没有层次" --> F{阴影在哪?}
F -- 没有阴影 --> G[灯 Mobility 是 Static 且未烘焙?
或 Contact Shadow 未开]
F -- 全是阴影 --> H["补光层缺失:
SkyLight 强度与间接光倍率"]
B -- "卡: 帧时间超标" --> I{stat gpu 谁最长?}
I -- VolumetricFog --> J[GridPixelSize 8→16
GridSizeZ 减半]
I -- ShadowDepths --> K["动态灯数量超限:
Movable 改 Stationary"]
I -- Lumen --> L["回第 7 章:
Software RT 降档"]三个高频坑提前点名。一,浓雾配高 Scattering 的定向光,室内会"漏光柱"——光柱穿过实体墙照进来,这是 Froxel 分辨率不够的物理限制,解法是缩小灯的照射范围而不是加大雾密度。二,雾的 HistoryWeight 低于 0.85 时,镜头快速转动会看到雾的拖影,恐怖游戏里玩家频繁甩手电,这个值别乱降。三,Height Fog 的密度是指数曲线,Fog Density 从 0.1 调到 0.2,实际上是把能见度砍到大约原来的平方根量级——翻倍的只是参数数值——调的时候 0.02 一档地走。
补课:玩家的眼睛落在哪,由对比度说了算
补课:构图基础。美术出身可跳过,但请美术同事也看看第五节后半的参数化讨论。
三条构图常识,一条一段讲完。
三分法:把画面横竖各三等分,四个交点是视觉的"天然座位"。主体放正中,观众感到的是"证件照"的安定;放交点上,画面才有冲击力。恐怖游戏的怪物亮相从不站正中——站三分线,观众的余光会替想象力补完另一半。
引导线:走廊、栏杆、光束、影子,一切长线都是视线的轨道。玩家说"这个关卡不用地图也能走对",多半是引导线在干活。光是最便宜的引导线:一束顶光打在正确的岔口,比放一个路标箭头优雅,还省 UI 成本。
负空间:画面里"什么都没有"的区域。新人布光的通病是把每个角落都打亮,画面信息均匀得像超市。负空间是给观众留的呼吸位,也是给"可能出现的东西"留的舞台——孤独感靠大面积空旷,恐怖感靠大面积黑暗,本质都是负空间的配比。
灰盒房间做过一个对照:恐怖版里把暗部面积从 40% 提到 65%,其余参数不动,找同一个测试者隔一周重玩,心率带记录的平均唤醒水平高了一截——人对自己看不见的区域比对看得见的东西紧张得多。孤独版则反过来,暗部不变,把桌子从房间中央挪到三分线交点,中央留出大片空地,测试者的主观描述从"阴森"变成了"冷清"。同一间屋子,黑暗的比例决定怕不怕,空旷的比例决定孤不孤。
这三条背后是同一个人眼生理事实:视网膜对相对亮度差敏感,对绝对亮度迟钝。这就是 Weber 定律在画面上的推论。描述一块区域在整屏里"有多抢眼",可以用 Michelson 对比度定义局部的冲突强度:
和 是该区域与紧邻背景的亮度。 接近 1 意味着该区域与背景几乎黑白分明——视线会被强行拽过去;低于 0.2 则融进背景。把全屏划成 个区域,第 块分到的初始注意力近似正比于它的"亮度 × 面积":
这个式子解释了为什么"一个小亮点"和"一面大亮墙"能平分秋色:台灯 0.1㎡ 但亮度 500nit,天花板 8㎡ 但亮度 40nit,二者的注意力权重在同一量级。想引导玩家看门,要么把门打亮(抬 ),要么把门框大(抬 ),要么把周围压暗(降分母)。三条路等价,按场景成本选——压暗周围通常最便宜,因为不需要加灯。
回到灰盒房间,四条布光配方的对照实验结果,收进这张象限图。横轴是主光色温,纵轴是全屏对比度,雾浓度写在每个点的参数里:
quadrantChart
title "灰盒房间四氛围光配方(雾浓度为 Fog Density)"
x-axis "冷色温 7000K+" --> "暖色温 3000K-"
y-axis "低对比 CM<0.4" --> "高对比 CM>0.7"
quadrant-1 "紧张: 双光对冲 3200K/8000K, CM 0.85+, 雾 0.10-0.20"
quadrant-2 "恐怖: 6500K带绿, CM 0.8+, 雾 0.15-0.30"
quadrant-3 "孤独: 8000-10000K, CM 0.3-0.5, 雾 0.20-0.40"
quadrant-4 "希望: 2800-4500K, CM 0.4-0.6, 雾 0.05-0.10"
"恐怖": [0.22, 0.82]
"孤独": [0.15, 0.28]
"希望": [0.80, 0.32]
"紧张": [0.62, 0.90]四象限的分工逻辑值得记住。恐怖是"冷且冲突":冷色剥离安全感,高对比藏东西。孤独是"冷且均匀":雾把对比度吃掉,世界没有焦点,人像被遗弃在灰里。希望是"暖且柔":低对比给宽容感,暖色给归属感。紧张最特殊——它的色温居中是因为用了冷暖对冲:警报红光打左墙,冷月光切右墙,两种色温在画面里交战,观众的生理唤醒水平直接拉满。第 8 章色彩补课里讲的"互补色冲突",在这里第一次变成可执行的布光参数。
参数区间是起跑线,没有谁拿圣旨来调数值。雾密度那几列尤其要按镜头驻留时间修正:过场动画镜头固定,雾可以浓;实机追逐战玩家高速转向,浓雾加 HistoryWeight 偏低会糊成一片。
「回响峡谷」三个标杆场景:把配方做成清单
理论到此为止,剩下的是工程。布光工作流在任何场景都一样,先立个流程再进实操:
flowchart LR
A[叙事意图
这个房间讲什么] --> B[主光层
逻辑光源定方向]
B --> C[补光层
天光+间接光定宽容度]
C --> D[氛围层
轮廓光/雾/光束定质感]
D --> E[校色层
曝光+色调分离定心情]
E --> F{实机走查}
F -- 情绪不对 --> A
F -- 性能超标 --> G[按排查树降档
雾→动态阴影→Lumen]
G --> F顺序不能乱。校色层永远最后做——先调色再打灯,等于在未锁定的白平衡上刷墙,所有灯的参数都要返工。
场景一:废弃医院走廊(恐怖)
叙事意图:玩家知道"该往前走",但每一步都想回头。手法是冷绿基调 + 高对比 + 负空间藏怪,色温刻板印象的反用点放在尽头那盏暖灯上。
| # | 光源 | 类型/移动性 | 关键参数 | 职责 |
|---|---|---|---|---|
| 1 | 破窗月光 | Directional / Movable | 0.4 lux,9500K,Scattering 2.5 | 主光,从右侧破窗斜切,制造光柱 |
| 2 | 环境底 | Sky Light / Movable | 0.25,冷灰 | 补光,保证暗部勉强可读 |
| 3 | 坏日光灯 | Rect / Stationary | 6200K 加 15% 绿,Light Function 闪烁 | 中段主视觉,闪烁节奏 0.8s/3s 不规则 |
| 4 | 出口牌 | Point / Stationary | 纯绿,半径 150cm,无阴影 | 地标,绿色在地面反弹 |
| 5 | 尽头病房灯 | Point / Stationary | 2700K 暖,接触不良式明灭 | 反用点:满屏冷里的唯一暖,最瘆人 |
| 6 | 地面应急灯 | Spot / Stationary | 红色,朝上,强度 30% | 低位逆光,拉长影子 |
| 7 | 玩家手电 | Spot / Movable | 外锥 32° 内锥 14°,5600K | 玩家可控的唯一安全感 |
后处理:EV100 区间 [-1, 1.5],Compensation -0.7;阴影 Gamma 压 8% 青绿;Height Fog Density 0.18,体积雾中档。验收标准一句话:关掉手电站在走廊入口,出口牌和尽头暖灯两个点光源的 都要在 0.8 以上,而两者之间保持大片 的暗区——视线被强制做选择题,恐怖感就成立。
场景二:雨夜天台(孤独)
叙事意图:世界很大,玩家只有自己。手法是大面积冷负空间 + 远处暖光"够不着"——暖色存在,但都在几百米外的城市灯火里,近身处一盏不给。
| # | 光源 | 类型/移动性 | 关键参数 | 职责 |
|---|---|---|---|---|
| 1 | 城市月光 | Directional / Movable | 0.6 lux,8000K | 主光,弱而均匀 |
| 2 | 雨夜天光 | Sky Light / Movable | 0.5,蓝灰,捕获得到的低饱和 HDRI | 补光,雾天漫反射 |
| 3 | 城市天际线 | Rect / Static | 钠灯橙 2200K,超大面积极低强度 | 远方暖色:够不着的人间 |
| 4 | 远处霓虹×2 | Rect / Static | 一品红一青,只照亮雨幕不照地 | 背景层次 |
| 5 | 空调外机警示灯 | Point / Movable | 红色,2s 呼吸明灭 | 全场唯一的"活物"信号 |
| 6 | 积水反射 | 无(材质侧) | 地面 Roughness 0.05–0.15 | 把上面所有光复制一份,画面翻倍 |
后处理:EV100 [-1.5, 0.5],Compensation -1.0;两端都不染色,保持灰;Fog Density 0.3 低档体积雾(雨幕交给第 13 章的 Niagara)。关键比例:亮部面积不超过画面 25%,主角周围 5 米内 。孤独感的真正来源是"均匀到没有焦点"。画面黑只是伴随现象。
场景三:安全屋(希望)
叙事意图:紧绷了一路的玩家,进门那一刻肩膀要松下来。手法是高调暖光 + 丁达尔尘光 + 柔阴影——这是三个场景里唯一允许"好看"优先于"省钱"的房间。
| # | 光源 | 类型/移动性 | 关键参数 | 职责 |
|---|---|---|---|---|
| 1 | 晨光 | Directional / Movable | 12 lux,3800K,入射角 15°,Scattering 2.0 | 主光,低角度长影子 |
| 2 | 天光 | Sky Light / Movable | 0.8,暖灰 | 补光,亮部占画面 70% |
| 3 | 窗口补偿 | Rect / Stationary | 4200K,对着窗内墙 | 模拟窗的二次反弹,柔化墙角 |
| 4 | 炉火 | Point / Movable | 2300K,Light Function 摇曳 | 情绪锚点:家=会动的暖光 |
| 5 | 角落防死黑 | Spot / Stationary | 5500K,强度 15% | 救暗部,不让 Lumen 漏光显眼 |
| 6 | 尘埃光柱 | 雾+主光 Scattering | Fog Density 0.06 | 体积感,"能闻到灰尘味" |
后处理:EV100 [0, 3],Compensation +0.3;高光 Gain 提 5% 暖橙,阴影不动;饱和度 +5%。和前两个场景对照,这个房间的平均亮度高了约两档 EV——希望感是可以用曝光值量化出来的。
安全屋是和 Lumen 配合最深的一个场景(Lumen 的软硬路径选择见第 7 章)。炉火这盏 Point Light 故意不投影:它的任务是发光而不是造影子,摇曳的暖色经 Lumen 间接光在墙面和家具上反弹,整个房间像被炉火"烘"着。窗口 Rect Light 模拟的二次反弹补的是 Lumen Surface Cache 在低角度入射时容易偏暗的墙角——动态 GI 再强,角落的宽容度仍要靠一盏懂事的补光兜底。
这也是三个场景里唯一敢让亮部占画面七成的房间:Lumen 在高调画面里的漏光缺陷最不明显,前两个暗场景反而要盯紧墙角。
三个场景之间,氛围的切换不能是硬切。玩家推开安全屋的门,冷绿不能在 0.1 秒内变成暖橙——那是换台,不是叙事。UE 的做法是区域 PostProcessVolume 按 BlendWeight 混合,运行时状态机驱动过渡时长:
stateDiagram-v2
[*] --> 走廊恐怖
走廊恐怖 --> 天台孤独: 推开消防门(过渡2.5s)
天台孤独 --> 走廊恐怖: 退回室内(过渡1.0s)
走廊恐怖 --> 安全屋希望: 剧情解锁(过渡4.0s)
天台孤独 --> 警觉紧张: 敌人索敌成功(过渡0.4s)
警觉紧张 --> 天台孤独: 脱离战斗(过渡3.0s)
安全屋希望 --> 走廊恐怖: 出门(过渡2.0s)
警觉紧张: 双光对冲+曝光收窄
安全屋希望: 暖高调+雾降档过渡时长本身就是叙事:进入危险的过渡要快(0.4s,生理惊吓),进入安全的过渡要慢(4s,让松弛感渗进来)。切换逻辑用伪代码描述如下,核心是对权重做插值而不是换资产:
# 伪代码:区域氛围切换(类Python)
class AtmosphereDirector:
def __init__(self):
self.current = PRESET_CORRIDOR # 当前生效的预设
self.weight = 1.0 # 当前预设的权重
self.blend_queue = [] # (目标预设, 过渡时长, 已耗时)
def on_enter_volume(self, preset, duration):
# 进入区域体积:压入混合队列,不打断正在进行的过渡
self.blend_queue.append((preset, duration, 0.0))
def tick(self, dt):
if not self.blend_queue:
return
target, duration, elapsed = self.blend_queue[0]
elapsed += dt
t = smoothstep(min(elapsed / duration, 1.0)) # 缓入缓出
# 两套预设按 (1-t) 和 t 混合,应用到同一个后处理体积
mixed = lerp_preset(self.current, target, t)
apply_to_postprocess_volume(mixed)
# 体积雾档位跟着氛围走:希望场景降档省钱
set_cvar("r.VolumetricFog.GridPixelSize",
lerp(self.current.fog_pixel, target.fog_pixel, t))
if t >= 1.0:
self.current = target
self.blend_queue.pop(0)lerp_preset 对色温、曝光、对比度逐字段插值即可,但要避开一个坑:雾密度别线性插。前面说过它是指数参数,从 0.3 到 0.06 线性插值的中点会明显偏浓,用几何插值(对数空间 lerp)过渡才均匀。
小结
光是叙事语言,不是照明工程。同一间灰盒房间改四组参数能讲四个故事,参数差异集中在色温、对比度、雾密度三个旋钮上。三点布光在游戏里要翻译成三层职责:逻辑主光、环境补光、局部轮廓光——任何一盏灯答不上"负责什么",就删掉。暖安全冷危险是起跑线不是天花板:刻板印象用来建立预期,反用用来制造扭曲,医院走廊尽头那盏暖灯比任何怪物都瘆人。体积雾按场景配档:超高档一帧能吃掉 10ms,把雾当主角的场景才配用中高档。氛围切换的过渡时长是叙事的一部分:进危险 0.4 秒,进安全屋 4 秒,数字反了情绪就反了。
上手任务
- 灰盒房间四连拍:搭出 6m×8m 灰盒房间,按第 5 节象限图复刻恐怖/孤独/希望/紧张四套布光,每套只允许改灯光、雾和后处理,不许动家具。验收:把四张截图给三个不了解项目的人看,情绪猜测命中率至少 3/4;且每张图都能在 5 秒内指出主光的逻辑来源。
- 雾的成本实测:在走廊场景里用
stat gpu记录r.VolumetricFog.GridPixelSize取 16/8/4 三档的 VolumetricFog 耗时。验收:三档耗时比例落在 1 : 2~3 : 6~10 的数量级区间内;写一句结论,说明你的目标平台该锁哪档。 - 区域切换落地:实现
AtmosphereDirector的伪代码逻辑(蓝图或 C++ 均可),做走廊→安全屋的过渡。验收:过渡全程 4 秒内无肉眼可见的跳变;雾密度用几何插值,中点时刻主观浓度接近两者的"中间感"而非偏浓。
下一章
光让场景会说话了,但场景里的人还在 T-Pose。第 11 章把「回响峡谷」的主角从滑步假人变成会走会跑会刹车的活物:动画状态机、混合空间,以及那个折磨过每一个团队的脚步滑移问题。
延伸阅读
- 官方文档:Unreal Engine → Rendering → Lighting → Light Types and Their Mobility(五种光源的权威参数表)
- 官方文档:Unreal Engine → Rendering → Fog Effects → Volumetric Fog(Froxel 网格与全部 CVar)
- 官方文档:Unreal Engine → Rendering → Post Process Effects → Color Grading and Filmic Tonemapper(Lift/Gamma/Gain 语义)
- 源码:Engine/Source/Runtime/Renderer/Private/VolumetricFog.cpp(体素注入与历史帧混合的实现)
- James Gurney《Color and Light: A Guide for the Realist Painter》:色温与大气透视的美术基础,程序也能读
- GDC Vault 检索方向:Naughty Dog 关于环境光照与氛围叙事的分享(The Last of Us 系列的 lighting 专题),看美术如何在静态场景里做光的层次