自动曝光是什么?

场景里有的地方很亮,有的地方很暗

显示器能显示的亮度范围很有限

自动曝光就是:每帧看看画面整体有多亮,算出一个「曝光倍数」,把整张图统一调亮或调暗,让画面看起来舒服——类似人眼从暗处走到亮处会眯眼、从亮处进暗处会慢慢看清

游戏里也叫 Eye Adaptation(眼睛适应)

为什么需要?

场景亮度会变(进出室内、昼夜、动态关卡)。自动曝光要模拟眼睛对光线变化的反应,并选出「合适」的曝光。难点在于:什么叫合适——按太阳、按阴影,还是折中?画面该正常、欠曝还是过曝?这没有唯一答案,所以有人干脆手动定曝光

如何实现?

核心算法

自动曝光目前分为两种做法,但核心算法都是一样的,如下:

  • 量:这一帧有多亮
    • 每个pixel计算luminance
    • 计算所有luminance的平均值,得到一个平均亮度 L_avg
  • 比:离“该有多亮”差几档
    • 摄影里把 18% 灰(0.18)当成正确曝光的中灰,需要计算一个系数ExposureScale,使得ExposureScale * L_{avg} = 0.18
    • 人眼/相机用 档(EV) 想这件事,一档就是乘/除 2:EV = log₂(L_{avg})
  • 调:给美术额外参数
    • 夹紧(Min / Max):平均亮度只允许落在一个范围内
    • 曝光补偿 EV(Exposure Compensation):美术手动调节亮度档位
  • 用:每个像素颜色乘上ExposureScale

新派和老牌做法只在”量”上不同

老派做法

在”量”上,老派做法将所有luminance都纳入考虑,通过不断降采样,最终降采样一个数,这个数即为ExposureScale

新式做法

在”量”上,新式做法也将所有luminance都纳入考虑,但这些luminance会放入直方图按挡位划分,挡位外的(极亮、极暗)排除,剩下的加权平均,得到ExposureScale

  • 中心加权

    画面中心更重要,可只测中心圆,或给中心像素更大权重

  • 直方图

    小块极亮/极暗会拖垮简单平均;直方图可近似按「主导亮度」或中位数来适应。64 个 log2 档可盖约 16 EV,128 档可盖现实几乎全部曝光范围。建完后可丢掉大量最暗像素(约 50%–80%)和少量最亮像素(约 2%–20%),用中间部分求平均,曝光更稳

  • 滑动直方图 / 预曝光

    用上一帧曝光先乘回 HDR 缓冲,方便用 R11G11B10 等格式存 HDR 而不丢精度(Valve 也做过类似预曝光)

  • 曝光补偿曲线

    纯自动会把暗室和开窗后的亮室都拉成差不多亮,但我们更希望:暗环境最终画面偏暗,亮环境偏亮

    因此 Krawczyk 拟合过 key 随亮度变化的曲线;游戏里可以自己定函数,或让美术调 1D 查找表

  • 按照度适应,而不是按最终像素亮度

    只看最终亮度时,白墙和黑墙经曝光后可能看起来差不多。Hoffmann 建议按「照到表面的光」(illuminance)适应,材质反射率就不掺和进来;镜面也能少干扰。天空盒怎么进测光要单独定,并常给天空手工曝光补偿

自动曝光管线

记住,需要在Tonemap前,进行自动曝光

预曝光

  • 什么是预曝光

    在后处理前,计算Scene Color光照时,乘上预曝光缩放系数

  • 为什么需要预曝光

    Scene Color RT格式一般为R16G16B16A16_FLOAT,这样的精度看似较高,但对于自动曝光来说是有不足的,因为R16G16B16A16_FLOAT的精度只支持3-4位有效数字

    • R16G16B16A16_FLOAT如何表示数字?

      再继续下去之前,先看看半精度是如何表示数字的

      • R16G16B16A16_FLOAT使用± 1.xxxxxxxxxx × 2^档来表示(注意,小数点后的是二进制),其中小数点后有十位,这意味着每一档小数点的精度是1024

        来看一个例子就知道了,4096表示为1 x 2^12

        下一档是1x2^13 = 8192,在4096-8192间,有4096个数,但小数点后的精度是1024,这意味着,这种情况下每四个数,由小数点后一位表示

    若是处于很暗的室内,计算得到的曝光系数很低,比如0.00005,这种情况下得到的值为0,那么就是全黑,阴影层次将消失;若处于很亮的室外,计算得到的曝光系数很高,比如8000,那么层次过渡会非常差,因为8000挡位下,每四个数,由小数点后一位表示

  • 如何实现预曝光

    核心问题:如何计算预曝光?

    每次计算完曝光系数时,记录这一系数作为预曝光系数,传回CPU,下次计算Scene Color Lighting时,使用该预曝光系数

    若是第一次计算Scene Color Lighting,预曝光系数设为1

    需要注意,因为应用了预曝光系数,所以需要在计算曝光系数里,计算亮度时,乘上one over 预曝光系数,避免受到影响

时间平滑

  • 什么是时间平滑

    从暗处走到亮处,亮度从暗到亮一点点的平滑

  • 为什么需要时间平滑

    • 防止亮度突变
    • 模拟现实中从暗到明/从明到暗,眼睛的变化
  • 如何实现
    • 计算当前帧计算的亮度档位(平均亮度与中灰0.18的比值)
    • 上一帧的亮度档位计算差值

      根据大于/小于0,判断是从暗到明/从明到暗(因为两个方向的速度是不一样的)

    • 不断基于差值,插值平滑

      物理上眼睛的变化,是一开始快后面慢,因此时间平滑也需要模拟这一现象

      先线性,后指数

Reference

Automatic Exposure

Adaptive Exposure from Luminance Histograms

Automatic Exposure Using a Luminance Histogram

自动曝光

Epic Games如何在4.25版中处理自动曝光


他们曾如此骄傲的活过,贯彻始终