前言
网上有许多关于主流tonemap的实现代码,但都没有讲清楚这些主流tone map之间究竟有何区别、每个tonemap的特点,以及为什么需要定制,这样当美术需要某种画面感时,TA才知道如何去定制
本文将一一解析这几个存在的问题
什么是tonemap?为什么需要tonemap?
关于这两点网上已经说的很明白了,tonemap将HDR空间的颜色,映射到LDR空间,以适配只能显示[0,1]的显示器,防止颜色被截断导致的曝光
每种tonemap都由三部分组成:控制暗部的toe、控制整体亮度的Linear、压制高光的Shoulder,且几乎所有的tonemap都有着如下图所示的s形曲线

如果你看过ue的ACES Tonemap,一定不会对这三个参数感到陌生,它们代表的含义如下:
- toe:控制暗部对比度
用于处理HDR中的暗部,将暗部信息往下压,让画面更加干净
优点:当toe越平缓,说明暗部颜色都往极暗区域靠,对比度越小,画面的纯黑色越干净,也就是常说的“电影感”
缺点:会牺牲暗部细节
-
Linear:控制整体明暗的对比度
Linear会极大幅度的影响曲线走势,因为linear越陡,曲线大部分区域都分配给了linear,整体的中间色被映射后的颜色差距越大,导致整体对比度越高
越陡的linear会带来越强的明暗对比度,所以像ACES这种电影感的tonemap,它的linear就较陡
-
Shoulder:控制高光细节、层次感
把极高的 HDR 值强行映射到 0.8∼1.0 的区域,防止大部分纯白
主流Tonemap之间的不同及特点
ACES

- 特点
- linear曲线较陡,意味着大部分中间色都在linear曲线,整体对比度高
- toe、shoulder曲线较缓,尤其是最靠近0、1的部分,暗部、亮部偏向纯黑、纯白
- 缺点
- 因为linear陡对比度高,会损失暗部、亮部细节
- 使用场景
- 具有电影感的场景
Neutral

- 特点
- linear:占绝大部分,且接近1:1映射。所见即所得,美术画的 Albedo 是什么颜色,引擎里就是什么颜色
- toe:只占一点点,个人感觉是用于将噪点映射到纯黑
- shoulder:前面陡后面缓,对于极亮像素映射到纯白,较亮的对比度拉高
- 缺点
- 画面较平,缺少强的光影对比度
-
极亮区域容易出现color band
由于非高亮区域[0,0.8]都是线性映射,只剩0.2给高光,能用的bit是很少的,尤其显示器还是255bit,给高亮的也就50+bit
- 当一个pixel从暗到亮到极亮的过程,变化很不自然
当pixel在toe、linear都是比较正常的,但一旦刚刚进入shoulder区域且不断变白,会因为shoulder前面陡后面缓的特性,导致最开始颜色饱和度很高,后面慢慢变白
-
适用场景
- 材质编辑器预览、PBR验证
GT Tonemap

https://www.desmos.com/calculator/6tothm2tko?lang=zh-CN
- 特点
- 开放大量参数给美术,且将toe、shoulder、linear拆分成多个参数,完全可控。最重要的一点,参数几乎完全解耦,不像其他tonemap,部分参数互相牵连 (改了高光暗部变亮)
- 能在保留极高局部对比度和色彩饱和度的同时,优雅地压平天空的过曝
- 调节Black tightness、b,可以让toe能比ACES更陡,暗部对比度高,也可以手动将toe调的更平缓,让暗部偏纯黑
- 调节Contrast,可以控制linear,Contrast更大曲线更陡,对比度越高;Linear section start、Linear section length可以控制linear区域大小,让黑白区域对比度更高
- 调节Maximum brightness,可以控制峰值亮度,适配HDR显示器
- 缺点
- 没有很好的基础,参数不好掌控,容易调崩
- 对材质反光和局部对比度要求极高的场景
Filmic

- 特点
- Filmic toe先缓后陡,极暗部分对比度低,更偏纯黑,较暗部分对比度高
- linear较缓,中间色偏灰
- shoulder先陡后缓,较亮部分过渡丝滑,高亮部分偏白
- 缺点
- 画面可能会发灰,对比度欠佳
- 适用场景
- 对后处理性能极其敏感的
总结
| 方案 | Hue Shift | 暗部对比度 |
|---|---|---|
| ACES | 强(高光偏白) | 极高 |
| Neutral | 无(偏向原色) | 线性 |
| GT Tonemap | 参数可控 | 参数可控 |
| Filmic | 较弱 | 略发灰 |
为什么需要定制
可以看到上述tonemap多少都有些缺点,但GT参数是完全可控,且解耦的,还有定制的必要吗?
答案是有的,但不是定制曲线。大致有三种情况需要定制:
- 场景亮度的突变
- 假设从一个昏暗的室内走到阳光灿烂的室外,一套固定的GT参数是没法同时满足这种情况的
会导致昏暗时大部分是暗的,大部分都在toe处,使得都变暗;室外亮度很高,导致大部分都在shoulder,都偏白。也就是说toe、shoulder会很影响画面的整体性,会很大程度地丢失画面信息
如何在不同亮度情况下,让画面变化统一呢?观看GT的曲线,不难发现中间有一段几乎直的linear线段,如果pixel color亮度都在这个区域,那么不会丢失pixel的信息
- 如何实现所有pixel都在linear呢?没错,就是自动曝光
当画面整体较暗/亮,计算画面的曝光度,将整体pixel亮度乘上曝光值,使得变亮/暗,让亮度值落在linear区域
- 但需要注意的是自动曝光不能统计所有pixel,有些pixel需要被剔除的
在统计阶段对于少数极暗、极亮的pixel需要剔除掉,由于自动曝光需要计算所有pixel亮度的平均值,将这种极端pixel算入,会计算错误的曝光值。这种pixel不该管,让其将给toe、shoulder处理
-
极端亮度的影响
- 虽然自动曝光能控制画面整体性,但对于极亮、极暗的pixel处理依旧不好,虽然toe、shoulder可以处理这种pixel,但它们会丢失暗部细节、发白
-
要解决这种的问题,需要用到Local Tonemapping
通过Bloom的降升采样扩大感受野,再采样像素得到平均亮度来微调 GT 曲线的参数
比如,平均亮度极低的话,降低toe的曲率从而降低对比度;平均亮度极高的话,降低shoulder曲率从而有更多空间来平滑白色
-
color grade
- 虽然tonemap可以改变亮度,但不能改变颜色。当需要定制某种风格时,如蒸汽朋克、欧洲中世纪,就需要额外定制画面颜色
-
解决方案是Color Grade,流程如下:
-
先将linear space转到log space
- Color Grade
- 降低饱和度
- 色调分离: 针对暗部(Toe)染上冷色,针对高光(Shoulder)染上暖色
- 转回linear space
-
Tonemap
-
为什么不是Tonemap后color grade
Tonemap会破坏极暗、极亮的细节,且当由于亮度被映射到[0,1],在对高亮pixel去饱和,会导致错误的效果
- 为什么是log space不是linear space
因为人眼的感知更符合log space
定制管线
- 由于增加了自动曝光、local tonemap、color grade,那么管线将不一样了,大致流程如下:
- light pass HDR
- Auto-Exposure
- Linear to Log
- Color Grade
- Log to Linear
- Tonemap
- Gamma Correction/ ODT




Comments | NOTHING