UNIT 05灯光相机约 19 分钟 · 核心线
40 到 46 秒为什么一片亮?
把手机亮度拉到最大,屏幕上最白的那一格也就那么白;可正午的太阳亮得没法直视。渲染器算出来的亮度没有上限,屏幕有。红魔机甲片 v4 交给你以后,你一眼就看出来:「40-46秒之间是不是过曝了,一片亮」C23。你说的这六秒里,一片亮的是 43–46 秒那个从背后拍的镜头。这一课把那三秒拆开:亮度怎么塞进屏幕,塞不下的去了哪里,最后又为什么是改灯修好的。
05 · 1算出来的亮度没有上限
渲染器给每个像素算的,是有多少光到了镜头里,和真实世界一样,想多大就多大;这些数没有单位,只约定 1.0 是屏幕上的白。屏幕的每个像素是红、绿、蓝三个数(三个通道),每个只能从 0 到 1,写进一般的图片、视频是 0 到 255(每通道 8 位)。广州片正午的天空,用的是一张实拍的高动态范围(HDR)照片,每个像素存的是量出来的亮度。
这张天空照片里,太阳那一个像素,比旁边的天空亮多少倍?
- 三四倍:都是天上,差不多亮
- 几百倍
- 十几万倍
原图里太阳中心的亮度是 75,047,上半边天空的中位数是 0.34,差约 22 万倍(广州片自己的工具 hdri_sun.py 量的)。这么大的倍数,摄影里按档数(stop,也写作 EV):亮一倍是一档,亮 210 ≈ 1000 倍是十档;22 万倍约 17.7 档。
05 · 2调亮一点,会怎样?
要把这么宽的亮度放进 0 到 1,第一步是曝光(exposure):把所有亮度乘同一个数,Blender 里按档算,输出 = 亮度 × 2曝光。第二步最老实:超过 1 的一律当 1,Blender 叫它 Standard。先把曝光放在 −1 档:这张天空里被截断的像素约 3.5%,只有太阳和几片云边。嫌天空暗,最自然的想法是调亮一点。
曝光再加一档(所有亮度 × 2),被截断的像素会变成多少?
- 约 7%:亮了一倍,截断的也多一倍
- 约 30%
- 还是约 3.5%:本来到顶的只是更亮
−1 档 · 3.5%
0 档 · 30%
+1 档 · 100%截断的比例不是翻倍,是从 3.5% 跳到 30%,再加一档到 100%。这一幅取景里,九成像素最亮的那个通道(天空是蓝通道)落在 0.6 到 1.7 之间,就在 1 的两侧;曝光每加一档,一大片像素整批越过那条线。
「本来到顶的只是更亮」错在屏幕没有「更亮」:超过 1 的,不管是 1.2 还是 7 万,写进文件都是 255。
这就是过曝(overexposure)的准确意思:不是「太亮」,而是亮过屏幕的那一段被剪掉了,只剩一个值。在渲染器里那些数还在,换个曝光就回来;写进 8 位的帧、编码成片以后,就没了。
05 · 3不剪,把高光压弯
问题出在那一刀,那就别剪:让曲线在靠近 1 的地方慢慢弯过去,越亮挤得越紧,但永远分得出先后。这叫色调映射(tone mapping)。最简单的 Reinhard 把亮度 x 换成 x ÷ (1 + x):1 变成 0.5,3 变成 0.75,7 万也到不了 1。这几个数说的还是光的多少(线性值);写进屏幕之前,还要按人眼的感觉编码一次(上一节那条注),线性的 0.5 在屏幕上是 0.74。代价是不亮不暗的那一大片(中间调)也被一起往下压,亮暗拉不开,整幅画发灰。
Blender 5.2 推荐的是 AgX(旧的 Filmic 已标为弃用),广州片和红魔都用它,外加一个叫 Medium High Contrast 的对比度预设。实测它的曲线(下面都是写进屏幕的值,和上一段的 0.74 同一把尺):亮度 0.18(摄影里的「中灰」)显示成 0.46,亮度 1 显示成 0.81(截断是 1,Reinhard 是 0.74),要到约 7.6(比 1 高 2.9 档)才到顶。
−1 档 · 0.3%
0 档 · 0.7%
+1 档 · 1.5%颜色也跟着变。红魔的背景板是红色发光板,红、绿、蓝大约 1 : 0.05 : 0.02,越调越亮时:截断下红通道先到顶,那一点点绿还在涨,它往橙、往黄走;AgX 把太亮的颜色往白里收,它往粉、往白走。
05 · 4一片亮:辉光阈值
回到红魔。v4 用的就是 AgX,按说不该一片白。可它渲完以后还要过一道后期脚本 grade.py,加辉光(bloom):屏幕值里最亮的那个通道超过 0.72(255 里的 184)的像素,按超出多少取一部分亮光,用大、中、小三种范围糊开,再乘 0.8 加回画面。它本来是给眼睛、发光的缝这些小亮点加一圈光的。
下面是 43–46 秒的重建。镜头在机甲背后;机甲另一边、在它和远处的红色背景板之间,是一块 6 × 4 米的红色平板灯(面光),朝着镜头照过来——这就是背光,它本身设成了镜头看不见,只看得见它照亮的东西和它的倒影。灯的位置、功率、颜色,背景板的发光写法,相机,都照抄当时的脚本;只有机甲是方块搭的替身。它停在 v4 的灯上。
- 来自材料
- 红魔
set_mech.py、rmlib/stage.py里的背光、背景板(46 × 22 米,16 米外,中心最亮往外渐暗)、照机甲的五盏灯、反射卡和相机;三组灯的数出自脚本和改动记录;辉光照搬grade.py。天空是广州片正午那张(Poly Haven,CC0)。 - 本实验的设定
- 机甲是替身,没搭机库。在 Mac 上用 Blender 5.2 按灯分组各渲一张,这里按强度加回去——光是能叠加的,分开渲再加,和一次渲完只差在噪点和降噪上,平均 2–3%。AgX 是先让 Blender 对二十多万个颜色各算一次、存成表,这里查表,和它直接出图平均差不到 0.3 / 255。
grade.py的暗角、彩边、颗粒没做。 - 它能证明
- 在这套灯和这条后期上,哪些改动让画面一片亮、哪些把它救回来;曝光和改灯的差别。
- 它不能证明
- 真机甲的每一处高光:v4 的机甲、材质和环境都和这里不同,画面只像,不一样。
看读数:v4 的灯下,超过阈值的像素约三分之二。背景板最亮处的红通道是 2.8(系数 3.0 乘上渐变),过了 AgX 显示成(255, 152, 134)——三个数是红、绿、蓝,红是 255,也就是 1.0,早就过了 0.72。辉光于是给大半幅画都加了光,把剩下的层次冲掉。把强度拨到 0:背景只剩粉红,不再一片白。
05 · 5最后是改灯修好的
v5 第一次动手,改的是灯:背光从 22000 W 降到 5000 W,背景板从 3.0 降到 0.9,都降了两档左右。
其余不动(机甲的灯、反射卡、辉光阈值 0.72 都还在)。v5 第一次的 43–46 秒会是什么样?
- 已经是暗红背景前的剪影了:降了两档,够了
- 还是过亮:中间一团白,地板上一块白
- 比 v4 还亮
交片前的自查发现:还是过亮 C23。中间就是这一版,右边是再改一轮后的定稿。
v4背光 22000 W · 背景板 3.0
v5 第一次5000 W · 0.9
v5 定稿2000 W · 0.42 · 机甲的灯 15%在暗房里把「当时的灯」换成 v5 第一次:背景板最亮处是(221, 60, 15),红通道 0.87,还在阈值上面;地板上的白色长方形是背光在光滑地板上的倒影,降了两档,那一块的亮度还在 20 上下,比 AgX 到顶要的 7.6 还高得多。
定稿那一轮又改了几样(改动记录:背光 2000 W 且对反射不可见、背景板 0.42、照在机甲上的前方的灯降到 15%、反射卡隐藏):
| 改了什么 | v4 | 定稿 | 差几档 |
|---|---|---|---|
| 背光(6 × 4 米的红色面光) | 22000 W | 2000 W | −3.5 |
| 背景板的发光系数 | 3.0 | 0.42 | −2.8 |
| 照在机甲上的五盏灯(主光、两条长条灯、顶光、红色轮廓光,只照机甲) | 100% | 15% | −2.7 |
| 反射卡 | 在 | 这三秒藏起来 | — |
| 背光出现在反光里 | 是 | 否 | — |
后两样不是调亮暗,是决定光被谁看见。一盏灯可以照亮东西、却不出现在反光里:关掉背光在反光里的可见性,地板上的倒影没了,地板照样被照红(倒影是长方形,因为灯是长方形的:灯越大,倒影越大,影子边也越软)。反射卡是只在反光里出现的发光板,给金属一点东西可照;藏起来,黑漆盔甲只剩边缘一线反光。背景板 0.42 过了 AgX 是(164, 26, 0),最亮的通道 0.64,刚好落到阈值下面——这是暗房算的,当时的记录只写了「再减半」。
只拉曝光行不行?看表的前三行,三样都降了差不多三档——光看这三行,和整体暗三档差不多,曝光也做得到。做不到的是后两行。暗房里选 v4、曝光拉到 −3 档:背景板和机甲都暗下去了,可到顶的还有 5% 左右(定稿只有 1%),几乎全是地板上那块倒影——它比背景板亮几十倍,除以 8 还是到顶。再把「背光出现在反光里」关掉,到顶的就降到 1%。曝光把所有东西乘同一个数,比例不变;谁该出现在反光里,只能在灯上改。
05 · 6窗口要跟着光走
屏幕只显示一段亮度——这一节管它叫「窗口」——曝光决定这一段落在哪,所以曝光得跟着光走。太阳的方位和高度按日期、钟点、经纬度就能算:广州 9 月 26 日中午约 65°、偏南,18:00 只剩约 4°。广州片按太阳高度给每帧定曝光(sky.py),还按钟点把一天分成八段、换上七张天空照片(入夜前后两段共用一张),每张都转到那个钟点的太阳方位上:
| 太阳高度 | 曝光(档) | 这时候 |
|---|---|---|
| 60° | −0.8 | 正午前后 |
| 25° | −0.5 | 下午 |
| 10° | 0 | 傍晚 |
| 0° | +1.0 | 落山 |
| −6° | +1.8 | 天刚黑 |
| −12° | +1.9 | 入夜 |
暗房的「04 换一张图」切到那张正午的天空,曝光自动停在 −0.7 档:这张照片是在别处拍的,照片里太阳高 48°,在表里 25° 的 −0.5 和 60° 的 −0.8 之间按比例取,就是 −0.7(广州片实际按它自己算的太阳高度定曝光)。下面几次毛病,都是窗口和光没对上。另记一条:发光的不一定能当灯用。红魔的背景板在 Cycles 里就是面光源,自己把地板照红了;游戏引擎里一个小而亮的发光灯罩,却照不亮一条街。
| 案例 | 看到的 | 出在哪 | 怎么修的 |
|---|---|---|---|
| C34 | 《拾光》打包版晚上九点半一片白 | 曝光按钟点提亮了,可太阳一直挂着(打包版按名字找不到它) | 认编号找太阳(文章里的说法) |
| C33 | 太阳一落山,天立刻全黑 | 低于地平线 1° 就关掉太阳;晚霞要靠地平线下的太阳算 | 太阳一直开着 |
| C09 | 广州网页版夜里山体、树冠死黑 | 没有天光、月光:零乘任何曝光还是零 | 加一盏月光 |
| C32 | 《拾光》夜里灯罩亮着,街道却一片黑;主角成了黑剪影 | 灯罩是小而亮的发光材质,引擎算它的光又吵又没有影子;点光源放好以后,主角仍比身后的背景暗得多 | 按灯罩的位置放 240 盏点光源;再加一盏只照主角的补光 |
| C39 | 预告片预演里主角在逆光树荫里只剩黑影 | 机位和路线:人在暗处,身后是亮天 | 正式录制前,先低分辨率跑一遍、每个镜头抽 4 帧拼成一张检查,挑出来 |
带走一个问题
一张渲染:人站在窗前,脸刚好,窗外的天一片死白。想把窗外的云找回来,你能想到几种改法?每一种会顺带改变画面里的什么?(想一想:哪些是乘所有东西的,哪些只动一盏灯,哪些只能在渲染器里做、成片上做不了。)
不看上面,写下这一课撞上的几堵墙,再展开对照
- 调亮一点 → 屏幕没有「更亮」:超过 1 的一律 255,到顶的一片整批变大,层次被剪掉。
- 成片上再压暗 → 剪掉的救不回来,白的变成一片灰;要救只能回渲染器。
- 用色调映射压弯高光 → 多留几档,但辉光阈值按屏幕值算:画面大半过了 0.72,整幅一起发光。
- 只拉曝光 → 所有东西一起乘,比例不变;地板上的倒影要在灯上关掉,反射卡要藏起来。
- 曝光按时间定 → 光没跟上(太阳没落、没有月光),窗口就落在错的地方。