Post-process 后处理
🚆

Post-process 后处理

💡
相当于美颜相机,加滤镜。
notion image
做后处理的目的:
  • 物理正确。让画面正确地被曝光。相机拍照的时候,整个光强变化的幅度是非常大的,太阳光可能是烛光的几亿倍。正确地被曝光,才能产生我们想要的效果(光晕)。
 

Bloom 光晕

notion image
notion image
为什么会有光晕?
  • 不是完美的小孔成像,不能完美地聚焦在焦平面上,就会产生 Airy disk。
  • 另一种,晶状体有半透明材质,像气溶胶 ,迎着光的方向有极向的反射。
notion image
首先把高亮的地方取出来,亮度可以从下面算:
当亮度超过某个阈值的时候,例如 1(不一定正确,用平均光场强度算会更好一点),取其强度和颜色。
notion image
然后做 Blur。这个 5*5 的 Blur 可以通过两次五个像素的卷积。
对每个点,第一个 pass,对上下相邻像素合一起。
第二个 pass,把第一个 pass 的结果左右合一起。
这样合一起的结果,相当于对每个点周边 25 个像素全部取一遍的结果。
对于 9*9 的卷积核,本来要卷 81 个数值,这种方法只用卷 19 个数值。计算量会少很多。
💡
得到 Blur 的区域后,这个区域其实是不够大的。因为真要实现上图右边朦胧的效果,需要三四十个 Kernel。
因此我们可以用 Pyramid 方法。
notion image
down sample 后,对最低一阶进行 Blur,再一级级放大回来,再进行加权混合。
其中混合有权重,到底是原图和 Blur 各 0.5,还是其他的比例,每一家公司都是自己设的,甚至还可以开放给艺术家。
计算量远远小于对最大的图进行超大的 Blur。
💡
这个思想在图像学也很常见。后面会有 half resolution,mid 的方法,都是降低复杂度的算法。
notion image
notion image

Tone Mapping 曝光

notion image
Tone mapping进化论
这几年,随着拍摄设备、渲染方法和显示设备的发展,HDR慢慢会成为标配。照相机和摄像机可以捕捉到HDR的影响,渲染过程中可以产生HDR的画面。这些内容如果需要显示到LDR的设备上,就需要一个称为tone mapping的过程,把HDR变成LDR。现在高端的显示器和电视也可以直接显示出HDR的内容。然而和LDR不同之处在于,LDR就是一个确定的范围,HDR是一个非常宽广的概念。即便两个都是HDR的,但它们的范围仍可能不同。因此有人把这个称为Variable Dynamic Range(VDR),可变动态范围,因为此H不一定是彼H。所以,即便在一个HDR世界,也仍然需要tone mapping来改变动态范围。 实际上tone mapping自古以来一直都有,不是计算机图形学的专利。早期因为颜料的对比度有限,达芬奇等的高手会把需要表达的内容用很有限的颜色画出来,即便色彩不真实。而刚发明电影的时候,胶片能表达的亮度范围有限,所以摄影师会把高亮区域和阴影区域向中等亮度方向压缩,发展出了S曲线的映射关系。这些都是tone mapping。 到了计算机图形学发展的时代,最早只有LDR,颜色就是0-255。这个情况一直持续了很长很长时间。到了90年代后期,软硬件的发展才让HDR变成一个可以考虑的问题。所以HDR转LDR的需求也就浮现出来了。随着2000年之后,GPU、游戏和电影特效的突飞猛进,tone mapping也经历了一系列的进化历程。每一个时期的代表作往往有强烈的流派特征,所以这里就按照流派来总结一下tone mapping。 直到2002年,有篇论文叫 Photographic Tone Reproduction for Digital Images ,提出了如何构造一个从HDR映射到LDR的方法。该方法也用其作者的名字命名为Reinhard tone mapping。从下图可以看出,用了tone mapping operator后,图片细节得以保留,而线性映射会造成最亮的区域和最暗的区域信息丢失。注意灯和书本。 Reinhard tone mapping非常简单,用代码描述就三行。 float3 ReinhardToneMapping(float3 color, float adapted_lum) { const float MIDDLE_GREY = 1; color *= MIDDLE_GREY / adapted_lum; return color / (1.0f + color); } 其中color是线性的HDR颜色,adapted_lum是根据整个画面统计出来的亮度。MIDDLE_GREY表示把什么值定义成灰。这个值就是纯粹的magic
Tone mapping进化论
大礼堂里面,白天窗户会非常亮,进去会发现窗子看的很清楚,里面的东西也能看得很清楚。
但如果掏出手机拍照,就会发现里面的东西看得很清楚,但是窗户那边已经曝掉了。要么就是窗户看得很清楚,里面看得很黑。
因为真实世界的光照的 range 是非常大的,如果曝光没有仔细调过,要么就是亮度过亮,要么就是暗部过暗。
notion image
现在游戏的渲染,基本都是 HDR 的渲染,光直射的地方非常亮,阴影里面亮度非常低。
如果我们不用一条曝光曲线把这么大范围的亮度数据映射到 LDR 或 SDR 上,就会是上图左边的图,天空已经过曝掉了,出现了色偏(亮度超过 1 的截掉,HDR 会产生色偏)。我们需要 Tone Mapping 使其曝光对。
差不多就是把 0~40 的值映射回 0~1。
Tone Mapping 的映射曲线有很多。随着行业发展,最经典的曲线,就那么几条。

Filmic

notion image
名字起的太厉害。曲线能让游戏产生电影的画质,顽皮狗提出。
算出任何一个点的光强后,要算出新的映射的时候,变成纹理进行采样,好像效率有点低。
因此他们实际上是用多项式的拟合来做的 Tone Mapping。
float3 F(float3 x) { const float A = 0.22f; const float B = 0.30f; const float C = 0.10f; const float D = 0.20f; const float E = 0.01f; const float F = 0.30f; return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F; } float3 Uncharted2ToneMapping(float3 color, float adapted_lum) { const float WHITE = 11.2f; return F(1.6f * adapted_lum * color) / F(WHITE); }
 
现在行业中慢慢在切的是 ACES。

ACES - Academy Color Encoding System

notion image
美国电影协会,结合多年经验提出了这个曲线,还解决了非常厉害的问题。
notion image
我们渲染出东西的时候,实际上需要在不同设备上播放,例如 HDR 显示器、非 HDR 显示器,最后颜色怎么映射?人眼对颜色的感知都是相对的,比如一个绿色在打印的白纸上,和在电影院里黑暗的环境中,要感知到一样的绿色,其实这两个颜色是需要调过的。
曲线调过颜色之后,还能加一道工序,无差别地适应到各种各样的现实终端。
📖
ACES 为的是解决所有设备之间的颜色空间转换问题。所以这个 tone mapper 不但可以用于 HDR 到 LDR 的转换,还可以用于从一个 HDR 转到另一个 HDR。也就是从根本上解决了 VDR 的问题。这个函数的输出是线性空间的,所以要接到 LDR 的设备,只要做一次 sRGB 校正。要接到 HDR10 的设备,只要做一次 Rec 2020 颜色矩阵乘法。Tone mapping 部分是通用的,这也是比之前几个算法都好的地方。
目前一些新的游戏,比如 Rise of the Tomb Raider、UE 4.8,也都切换到 ACES 的 tone mapping 曲线。
所有的数值、曲线都是由大量视觉艺术家调效果的。
叛逆者那里拿来的
叛逆者那里拿来的
上图显示了同样场景,用不同曲线曝光。

Color Grading 调色

彻底的“美颜”。
现代游戏中非常重要,非常简单,对游戏效果有质的飞跃。
notion image
notion image
善于表达清晰,例如打 Boss 非常难打,可能会发现色相偷偷的在变化。
Color Grading 又有种叫法叫 LUT,本质上是原始颜色和想调到摄像空间的映射,这个表格就是下图中的样子。
notion image
给一个颜色,变化到另一种颜色。
早期一些硬件不支持 3D Texture,我们就将其拍平为 2D Texture,一样存 Shader 里面。
我们不需要存 ,太大了。实际上 就够用了,因为颜色是连续的,在两个值之间插值即可。
notion image
非常实用,因为写完之后,其他的都可以交给艺术家发挥。
例如 PS 里面,艺术家可以方便自己调各种想要的效果,插件还能导出 Color Grading 的 LUT。
💡
Color Grading 是游戏引擎里面性价比最高的功能,非常简单,对游戏效果有质的飞跃。
notion image