开启辅助访问
 找回密码
 立即注册

[总结] 漫谈HDR和色彩管理(三)SDR和HDR

回答数13 浏览数158
这一节是为HDR和ACES做铺垫,以我们最为熟悉的sRGB色彩空间为例,主要回顾和学习之前提到的各种知识点是如何在SDR这条线里运作的。包括:
    颜色空间的Viewing Environment和Image State游戏渲染的SDR Color Pipeline如何工作什么是以及为什么需要Tonemapping
# 理想的世界:HDR

在PBR渲染中,我们经常会参考现实世界的光照数值来给场景打光。例如明亮的日光环境可达到120k lux,而月光只有大约0.25 lux(参考wiki)。我们会使用亮度(Luminance)来衡量给定方向上单位面积的发光强度(Luminous Intensity,单位为cd坎德拉),它的SI单位(International System of Units)是cd/m²(坎德拉每平方米),即nits(尼特)。这里注意区分明度(Brightness)亮度(Luminance)的区别,明度更多是一种主观视觉描述,而亮度则是一种光度测量值:
Brightness and Luminance are not the same thing! Brightness is an attribute of visual perception and Luminance is a photometric measure.
—— From this article
常见的LCD显示器的亮度在250尼特左右,HDR电视可以达到450至1500尼特的亮度值,荧光灯的亮度值可以达到12000尼特,而太阳的亮度在16亿尼特左右:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-1.jpg 来源:HDR in Call of Duty
与亮度是衡量给定方向上每单位面积所发出的发光强度类似,另一个我们经常看到的物理量是照度(Illuminance),它的SI单位是lm/m²(流明每平方米),即lux(勒克斯)。照度是衡量物体表面每单位面积入射的光通量(Luminous Flux,单位为lm流明)的物理量。总结下,亮度(Luminance,单位cd/m²)与发光强度(Luminance Intensity,单位cd)、照度(Illuminance,单位lm/m²)与光通量(Luminous Flux,单位lm)之间的关系如下(这些光学物理量之间的详细数学关系可以参考wiki):
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-2.jpg 来源:HDR in Call of Duty
目前,UE4和Unity HDRP都支持物理灯光参数,可以让美术在引擎里更加方便地模拟和还原现实世界中的各种光源,推荐李文磊大佬写的关于物理灯光环境的UE4 Blog。这里以UE4为例,UE4在4.21版本引入了物理灯光单位,其中:
    平行光:使用照度(Illuminance)来衡量强度,即以lux为衡量单位天光和其他作为静态光源的自发光材质:使用亮度(Luminance)来衡量强度,即以cd/m²为衡量单位点光、聚光灯、面光:可以从发光强度(Luminance Intensity)和光通量(Luminous Flux)之间二选一,即以cd或lm为衡量单位
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-3.jpg 可以看出,真实世界的光比是非常大的,而我们想要在渲染里还原这种高动态范围渲染(High Dynamic Range Rendering,HDR rendering),来让渲染出来的画面可以保留更多的细节和对比度。Nvidia曾总结过使用HDR的三点动机:
Bright things can be really bright, dark things can be really dark, and details can be seen in both.
—— From Nvidia
当我们在这样一个和光照值成比例相关的颜色空间下工作时,我们会把这个颜色空间称为“Scene Referred Color Space”或“Rendering Space”或“Working Space”:
A scene referred image is one whose light values are recorded as they existed at the camera focal plane before any kind of in-camera processing. These linear light values are directly proportional to the objective, physical light of the scene exposure. By extension, if an image is scene referred then the camera that captured it is little more than a photon measuring device.
—— From this article
渲染里最常见的Scene Referred颜色空间就是sRGB颜色空间。大多数情况,游戏渲染里使用的颜色贴图大多是在sRGB色彩空间下制作的。以Photoshop为例,我们可以在PS里的颜色设置里选择里选择当前的工作空间(下面的sRGB IEC61966-2.1虽然名字很长,但就是我们最常使用的那个sRGB颜色空间):
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-4.jpg 这些sRGB贴图会经过sRGB OETF函数进行编码存储成各种贴图格式。我们把这些sRGB贴图喂给渲染引擎,引擎在读取这些贴图时会再次经过sRGB EOTF函数将其中的编码值解码成原本的线性颜色值,并结合其他物理灯光进行相应的BDRF光照计算。
# 骨感的现实:SDR

HDR渲染虽然很美好,但当我们需要把渲染结果呈现出来的时候,就遇到了骨感的现实——SDR显示器。SDR显示最常见的两个颜色空间标准是sRGB和Rec. 709/BT.709。这里回忆下之前文章中的内容:
    Rec. 709:全称是ITU-R Recommendation BT.709,经常被缩写表示为Rec. 709、BT.709、ITU 709等。它最早是于1990年被提出来的用于HDTV(high-definition television)等领域的颜色空间标准sRGB:全称是standard Red Green Blue,它是一个从Rec. 709衍生出来的、由惠普和微软在1996年制定的被用于网络、Windows、印刷等领域的RGB颜色空间标准,之后由IEC委员会(International Electrotechnical Commission)制定的IEC 61966-2-1:1999标准化,它也是所有没有指定颜色空间的图像所使用的“默认”颜色空间
这些与显示设备相关的颜色空间被称为是“Display/Output Referred Color Space”或“Display/Output Space”:
A display referred image is one defined by how it will be displayed. Rec.709 for example is a display referred color space meaning, the contrast range of Rec.709 images is mapped to the contrast range of the display device, a HD television.
—— From this article
之前的文章里对这两个颜色空间只是一带而过,其实有很多细节我们都没有讲到,这里再展开说明下。sRGB和Rec. 709的三原色和白点值是完全相同的,这意味着它们和CIE 1931 XYZ颜色空间的变换矩阵是完全相同的,而它们的不同点在于传递函数。之所以需要使用不同的传递函数,是因为sRGB和Rec. 709的Viewing Environment是不同的。
那么什么是Viewing Environment?为了方便之后理解各种术语,这里花一些篇幅解释下之前没有提到的颜色空间的另外几个属性。当我们在定义一个完整的颜色空间时,除了三原色、白点和传递函数外,还需要定义其他几个属性:
    Image State:它把颜色空间分类成了几种不同的图像状态,最常见的就是之前提到的Scene Referred Image和Display/Output Referred ImageViewing Environment:Viewing Environment的严格定义我一直没有搞清楚,只能靠我自己的理解尝试解释一下为什么需要这个属性。由于人眼的视觉是自适应的,大脑对颜色的理解是依赖当前所处的观察环境的。例如,同样一张白纸在明亮的天光环境和钨丝灯光照下我们都认为它是白色的,但实际上在两种光照环境下它真正反射的光线是不同的。因此,我们需要给颜色空间定义一个它的观察环境,这个观察环境会影响颜色空间的白点值、传递函数等数值。例如DCI-P3的白点和伽马一定程度上就是为了适应影院这样较为昏暗的放映条件Data Type:它指定了这个空间下颜色数据的范围和精度,例如数据是8-bit、10-bit还是16-bit,格式是integer还是floating point
回到sRGB和Rec. 709的差异点。之前提到,sRGB和Rec. 709的Viewing Environment是不同的。sRGB标准假定的观察环境是照明条件良好的办公环境,也就是PC常见的应用场景。而Rec. 709标准的观察环境是用于家庭影院这种更为昏暗的照明环境的。因此,它们的传递函数被选择成能够更好地在这两种环境中表现图像细节的函数曲线。对同一张图像分别使用这两种传递函数的效果对比如下(图像背景暗示了观察环境,可以看出右边图像在暗部的对比度更强):
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-5.jpg 来源:HDR in Call of Duty
值得说明的是,Rec. 709标准实际上只为数字相机定义了一个精确的OETF传递函数(encoding function,也被称为camera gamma/scene-referred gamma),而并没有指定一个用于显示的EOTF传递函数。这个精确的OETF函数如下:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-6.jpg 其中,L表示被归一化到0~1的场景亮度值,V表示编码后的数字信号值。由于Rec. 709本身并没有指定一个EOTF(display referred gamma),委员会们在ITU-R BT.1886(BT.1886)里为Rec. 709指定了它的显示伽马函数EOTF(decoding function),这个函数如下:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-7.png 其中,a和b是两个常量参数,它们可由目标显示器的black level和white level值推导而来。对于一个理想条件下的显示设备来说,可以认为它的black level为纯黑色,此时上述EOTF就变成了一个纯2.4的伽马曲线。这也是ACES Rec. 709 Output Transform所使用的函数曲线(后面会详细讲ACES)。
相比之下,sRGB颜色空间标准的OETF函数定义如下:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-8.jpg 其中,L表示归一化到0~1的场景亮度值,V表示编码后的数字信号值。sRGB的EOTF函数定义如下:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-9.jpg 尽管IEC 61966-2-1:1999给出的标准如上,但关于sRGB图像的EOTF到底用什么是存在一些争议的。由于sRGB的传递函数近似一条2.2的伽马曲线,一些人认为sRGB OETF的线性部分仅仅是为了防止在接近0的部分减少量化误差,其本质就是一条2.2的伽马曲线,因此他们认为应该使用纯2.2的EOTF伽马曲线来校准显示器。这使得用户终端的sRGB显示器上显示的到底是什么亮度值变得更加不确定。这些复杂混沌的情况在此就不再深入讨论了。
至此,游戏中常见的从HDR渲染到SDR显示的流程可以归纳如下:
    在Photoshop等绘图工具里制作的sRGB空间下的颜色图像,经过sRGB OETF将线性颜色值编码成非线性信号值进行存储并传递给渲染引擎渲染引擎经过sRGB EOTF将非线性数据重新解码成线性颜色值,输入到线性渲染流水线中线性渲染流水线使用物理灯光参数和线性的物体材质属性进行相应的BRDF计算,最终得到高动态范围的scene referred image根据所使用的SDR显示器的颜色空间标准,对上述scene referred image进行颜色空间转换,并使用显示器颜色空间的OETF将其编码成可供显示器读取的视频信号,得到display referred imageSDR显示器应用EOTF将编码后的display referred image信号值最终转换成显示屏发光亮度值
对于大多数情况来说,游戏使用的SDR Color Pipeline里的scene-referred和display referred颜色空间都是sRGB/Rec. 709所使用的三原色和白点值,因此第4步中的颜色空间转换通常可以省略,而直接使用sRGB OETF(PC)或Rec. 709 OETF(TV)来将scene referred image转换成display referred image即可。也就是说,对于最为简单的以sRGB PC显示器为输出的SDR Color Pipeline来说,游戏引擎需要做的过程可以简化如下:
    对sRGB颜色贴图进行sRGB EOTF解码在线性渲染空间下进行场景渲染利用类似LinearTosRGB的函数对最后输出进行sRGB OETF编码并发送给显示器
这也就是我们经常谈到的线性空间渲染和伽马矫正的过程。
# 从HDR到SRD:Tonemapping

上述SDR Color Pipeline存在一个致命的问题,从scene referred image转换到display referred image的过程中,我们需要把那些高动态范围的亮度值转换成非常有限的显示器亮度值。回顾sRGB的OETF函数,其中的输出值V要求是0~1范围的视频信号值,这也就要求输入值L的范围同样只能在0~1之间。如果我们直接把HDR渲染得到的场景颜色值作为L输入到OETF函数里,那些超过1的亮度值就完全丢失了。这使得最终的渲染画面对比度很低,中灰值太亮,且高光区域被完全截断掉了:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-10.jpg 来源:https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
为了解决这个问题,我们需要在把scene referred image转换到display referred image的过程中间在插入一个转换步骤——Tonemapping。Tonemapping不需要我们去真的改变场景里的光源亮度和材质属性,它改变的是我们查看图像的方式,在电影和摄影领域也有类似的概念。Tonemapping虽然是近年来被提出来的一个新的术语,但这个概念早就被用于艺术家绘制写实风格的创作过程中了。早期画家在绘画时受限于有限的颜料特性和种类,会想尽办法把真实的现实场景利用颜料栩栩如生地复现在画布上,这种行为本身就是一种应用tonemapping的最佳实践。在电影领域,我们同样需要类似tonemapping的操作来把场景亮度重新映射到胶片可表达的有限亮度范围中。
在图形学里,tonemapping的本质是使用一个函数来把高动态范围的亮度值映射到0~1范围。在游戏开发的历史上出现过很多种tonemapping曲线,从最早最简单的经验派Reinhard,到神秘海域2使用的拟合派Hable Filmic,以及之后为了提高易用性和性能的改进版Filmic Curves,再到一统江湖的ACES Filmic Tonemapping,更详细的对比可以参考龚大的Tone mapping进化论一文,不同tonemapping曲线的效果对比也可以参考MJP的博客
Tonemapping进化到现在,基本上已稳定成使用一条S曲线来控制各个区域(shadow、midtone、highlight)的表现,使得曲线中间部分的对比度被提高而两端部分的对比度则被降低:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-11.jpg 来源:https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
在ACES Filmic Tonemapping曲线里,亮度为1的值被重新映射到0.86左右,也就是说原场景中超过1的高亮部位被重新映射到0.86~1的范围内了。这使得最终的渲染画面可以保留更多的光照细节和对比度,画面也更为鲜艳:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-12.jpg 来源:https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
除了Tonemapping,和HDR渲染另一个紧密相关的计算是曝光(Exposure)。简单来说,曝光就是一个亮度缩放系数,例如对于使用天光照明的场景来说,我们可以参考摄影领域著名的阳光16法则作为曝光参数,对渲染出来的图像进行亮度缩放。这部分内容可以参考李文磊写的真实物理属性的灯光环境在UE4中的应用探讨一文和聊聊自动曝光直播课程。
如此一来,加上Tonemapping和Exposure之后我们就可以得到一个比较完整的早期SDR Color Pipeline了。下面给出在使用HDR Color Pipeline之前,使命召唤无限战争和高级战争这几部前作里使用的SDR Color Pipeline:
[总结] 漫谈HDR和色彩管理(三)SDR和HDR-13.jpg 图中各个步骤过程如下:
    蓝色框内的步骤表示Scene Referred空间下的操作,该空间使用了以sRGB三原色表示的线性颜色值,渲染出来的场景亮度值可达到上千尼特。在这个HDR Scene Referred颜色空间(sRGB linear space)下,还会应用一些后处理计算使用曝光和Tonemapping曲线把场景亮度重新映射到一个可供显示的区间范围之后,使用sRGB OETF传递函数对数据进行编码,到这一步我们就转换到了Display Referred颜色空间即sRGB gamma space下了(图中绿色框)继续在sRGB gamma空间里进行后续SDR后处理计算、Color Grading、AA和UI渲染等操作最后将信号发送给SDR显示器,由显示器应用EOTF来编码后的电信号再次转换成真正的显示亮度
# 未来的趋势:HDR Display

随着硬件技术的不断更新,现有的SDR Color Pipeline的缺点逐渐暴露出来。首先,sRGB/Rec. 709颜色空间的色域范围十分有限,只占了CIE 1931颜色空间的大约35.9%区域。其次,不同SDR显示设备的亮度峰值是不同的,SDR TV普遍比SDR PC显示器峰值更亮。例如,sRGB CRT显示器的亮度大约在80 cd/m²,经过校准后可达到120 cd/m²,而大多数LCD液晶HDTV显示器的亮度可达到200到300 cd/m²。因此,我们可能更希望针对不同亮度峰值的SDR显示器使用不同的Tonemapping曲线以得到更好的视觉效果,但这也意味着我们需要针对不同输出设备进行兼容。
这种设备兼容工作在引入HDR显示器后会变得更加复杂,如何花费尽可能少的代价来让我们的渲染画面在各种SDR和HDR显示器上都能得到尽可能一致的画面效果,成为越来越多3A游戏渲染所需要考虑的方向。所幸的是,影视行业提出的ACES(Academy Color Encoding System)提供一个大一统的解决方案,为我们减少了非常多的兼容工作,这就是下一篇要讲到的内容了。
# 参考文献

1. https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
2. Digital Dragons 2018: HDR in Call of Duty
3. https://www.tftcentral.co.uk/articles/pointers_gamut.htm
4. https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html
5. https://64.github.io/tonemapping/
使用道具 举报
凡尘莲花1
女神的文章还是一如既往的高质量[赞]
回复
使用道具 举报
墙和鸡蛋
颜色管理是个非常蛋疼的问题,不知啥时候各家系统都能有个系统自行管理色彩的api,这样只要完成线性输出的数据丢给api就好了
回复
使用道具 举报
方方圆圆272
这种愿望似曾相识[飙泪笑]
回复
使用道具 举报
便宜老鼠药沼
文章前后顺序应该反过来编辑吧?先有需求,再有理论,再有硬件实现的限制和规格吧?
回复
使用道具 举报
茉莉707
哈某些方面是应该这样,但写的时候是按我的学习曲线走的,我对硬件标准最不熟所以把它放前面了,pipeline我比较了解所以容易的放后面
回复
使用道具 举报
知足常乐77
嗯对,认坑罢了。因为国内没有可以正向渐进的学习路径,所以只能直面工作中的,最终老外的硬件工业标准了,其原因历史由来都是找不到北的。
回复
使用道具 举报
王建新1
您好,请问为什么广色域渲染结果看起来会更好了?在ACEScg色域中渲染似乎比在SRGB中颜色鲜艳饱和很多。
回复
使用道具 举报
123456835
有点疑惑一个问题,为什么要有EO(OE)TF?
以前看书里面说的是,因为我们传统的显示器将输入的RGB值转换成相应的光信号时,天然自带EOTF,所以输出到显示器的RGB值需要提前OETF。
但是也看了很多文章,指出原因是因为可以用更多的bit来存储对HSV更敏感的色调。比如作者的这个系列文章第二篇。
那到底是因为什么原因呢?还是两者都有.......................
回复
使用道具 举报
丁侦球
早期的与CRT“奇妙的巧合”,现在我认为是要节省带宽给最需要的bits,这几篇里也有提到。所以OETF/EOTF的制定和color space的viewing environment很相关,人眼在各个观察条件下对不同区间的颜色敏感程度不同
回复
使用道具 举报
12下一页