请选择 进入手机版 | 继续访问电脑版

开源计算机图形学社区(Open Source Computer Graphics Community) |OpenGPU Forum (2007-2013)| OpenGPU Project

 找回密码
 注册
搜索
查看: 1748|回复: 7

KlayGE 4.10中渲染的改进(二):Tone mapping [复制链接]

Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28

注册时间
2009-3-31
积分
14266
发表于 2016-12-29 14:11:40 |显示全部楼层
转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=3497

上一篇讲了新的材质系统。本篇将讲tone mapping的改进。

Tone mapping的进化
KlayGE早在2006年的时候就引入了HDR的流水线。和当年的其他引擎一样,HDR的内容经过渲染,需要通过tone mapping转成LDR之后送去显示。这时候,tone mapping的质量就可以决定最后的画面细节度和对比度。

在KlayGE的发展过程中,tone mapping这个看似简单的步骤经历了多次进化。

Reinhard
早期的普遍做法是一篇叫做Photographic Tone Reproduction for Digital Images的论文,大家就用作者的名字称它为Reinhard tone mapping。这是个经验公式,把HDR到LDR的变换简单的描述了出来。
1
2
3
4
5
6

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 number了,根据需要调整。Reinhard的曲线是这样的,可以看出总体形状是个S型。


从结果上看,经过Reinhard tone mapping是这样的。


这种tone mapping的方法更多地来自于经验,没什么原理在后面。它的优点是简单直接,把亮的变暗,暗的变量。这样暗处和亮处细节就都出来了。但缺点也很明显,就是灰暗。个个颜色都朝着灰色的方向被压缩了,画面像蒙了一层纱。

CE
后来在2007年学习了CryEngine 2的tone mapping处理法之后,就改成用这种方法。这个方法更简单,只要一行,而且没有magic number。用一个exp来模拟S曲线。
1
2
3
4

float3 CEToneMapping(float3 color, float adapted_lum)
{
    return 1 - exp(-adapted_lum * color);
}

CE的曲线中间的区域更偏向于小的方向,这部分曲线也更陡。


这个方法得到的结果比Reinhard有更大的对比度,颜色更鲜艳一些,虽然还是有点灰。


Filmic

CE的tone mapping就那么用了好几年,直到2010年,看到了一个叫Filmic tone mapping的方法,来自于Uncharted 2。当年我也写过一篇文章讲这件事情。这个方法的本质是把原图和让艺术家用专业照相软件模拟胶片的感觉,人肉tone mapping后的结果去做曲线拟合,得到一个高次曲线的表达式。这样的表达式应用到渲染结果后,就能在很大程度上自动接近人工调整的结果。最后出来的曲线是这样的。总的来说也是S型,但增长的区域很长。


从结果看,对比度更大,而且完全消除了灰蒙的感觉。


而代码就有点复杂了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

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);
}

那些ABCDEF都是多项式的系数,而WHITE是个magic number,表示白色的位置。这个方法开启了tone mapping的新路径,让人们知道了曲线拟合的好处。并且,其他颜色空间的变换,比如gamma矫正,也可以一起合并到这个曲线里来,一次搞定,不会增加额外开销。缺点就是运算量有点大,两个多项式的计算,并且相除。

因为Filmic tone mapping的优异表现,大部分游戏都切换到了这个方法。包括CE自己,也在某个时候完成了切换。

ACES
到了2016年,美国电影艺术与科学学会,就是颁布奥斯卡奖的那个机构,在推广一个叫Academy Color Encoding System(ACES)的东西。这是一套颜色编码系统,或者说是一个新的颜色空间。它是一个通用的数据交换格式,一方面可以不同的输入设备转成ACES,另一方面可以把ACES在不同的显示设备上正确显示。不管你是LDR,还是HDR,都可以在ACES里表达出来。这就直接解决了在不同设备间互通数据的颜色转换问题。然而对于实时渲染来说,没必要用全套ACES。因为第一,没有什么“输入设备”。渲染出来的HDR图像就是个线性的数据,所以直接就在ACES空间中。而输出的时候需要一次tone mapping,转到LDR或另一个HDR。也就是说,我们只要ACES里的非常小的一条路径,而不是纷繁复杂的整套体系。

那么这条路径有多小呢?只要几行,系数来自于Krzysztof Narkowicz的博客文章
1
2
3
4
5
6
7
8
9
10

float3 ACESToneMapping(float3 color, float adapted_lum)
{
    const float A = 2.51f;
    const float B = 0.03f;
    const float C = 2.43f;
    const float D = 0.59f;
    const float E = 0.14f;
    color *= adapted_lum;
    return (color * (A * color + B)) / (color * (C * color + D) + E);
}

看着很像Uncharted 2的做法吧,都是多项式拟合。但是式子比Uncharted的简单,并不需要算两个多项式并相除,只要算一个,一次搞定。它的曲线是这样的。


S感很浓,并且比Uncharted的更向小的方向移,即便很小的数值和接近1的数值也有梯度。这样能很好地保留暗处和亮处的细节。至于视觉效果如何呢?看看这个。

可以看出来,比之前的任何一个都要鲜艳,并且没有因此丢掉细节!当之无愧成为目前最好的tone mapping算法。

更好的地方是,按照前面说的,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曲线。

总结
本文介绍了KlayGE的tone mapping在几个阶段的不同实现。最新的ACES不但可以用于HDR转LDR,还能兼容与未来的HDR输出。是目前为止最好的tone mapping算法。

下一篇,我会讲一下KlayGE 4.10对渲染的优化。

最专业的游戏引擎、图形编程、业界资讯,请见http://www.klayge.org

Rank: 13Rank: 13Rank: 13Rank: 13

注册时间
2011-5-7
积分
1736
发表于 2016-12-29 20:16:50 |显示全部楼层
学习了,

使用道具 举报

Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17

注册时间
2013-11-27
积分
5001
发表于 2017-1-6 19:08:32 |显示全部楼层
微软不是也推过scRGB色彩空间吗?感觉跟ACES很像。
还有理论上tone mapping之前是要做IDT的吧,RRT要求输入在ACES色彩空间,而游戏渲染出来的linear color如果用的sRGB色彩空间的white point和primaries,跟ACES不一样,需要做一次颜色矩阵乘法。

使用道具 举报

Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28

注册时间
2009-3-31
积分
14266
发表于 2017-1-7 15:16:57 |显示全部楼层
浙滨 发表于 2017-1-6 19:08
微软不是也推过scRGB色彩空间吗?感觉跟ACES很像。
还有理论上tone mapping之前是要做IDT的吧,RRT要求输入 ...

对于颜色空间的话,scRGB是wide color gamut,ACES更广,支持hdr和wcg。

这里只用到了ACES的tone mapping,完成的是从一个线性空间转到另一个线性空间。不涉及ACES空间本身。渲染的linear color就是linear的,不是sRGB。相当于IDT是单位阵,可以直接去ACES tone mapping。tone mapping输出的结果才去sRGB等。

Save

使用道具 举报

Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17

注册时间
2013-11-27
积分
5001
发表于 2017-1-10 13:45:52 |显示全部楼层
gongminmin 发表于 2017-1-7 15:16
对于颜色空间的话,scRGB是wide color gamut,ACES更广,支持hdr和wcg。

这里只用到了ACES的tone mapping ...

那是不是需要渲染用的材质文件就是ACES编码的?

使用道具 举报

Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28Rank: 28

注册时间
2009-3-31
积分
14266
发表于 2017-1-11 03:47:41 |显示全部楼层
浙滨 发表于 2017-1-10 13:45
那是不是需要渲染用的材质文件就是ACES编码的?

那些要么是线性的,要么是sRGB并在shader读取的时候自动转成线性的。保证光照在线性空间。

使用道具 举报

Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17

注册时间
2013-11-27
积分
5001
发表于 2017-1-11 11:33:16 |显示全部楼层
gongminmin 发表于 2017-1-11 03:47
那些要么是线性的,要么是sRGB并在shader读取的时候自动转成线性的。保证光照在线性空间。 ...

Soga,这样就解释得通了

使用道具 举报

Rank: 12Rank: 12Rank: 12

注册时间
2011-9-29
积分
834
发表于 2017-1-11 15:15:45 |显示全部楼层
谢谢分享

使用道具 举报

最近看过此主题的会员

您需要登录后才可以回帖 登录 | 注册

‹‹
我的工具栏

关于我们|手机版|Archiver|开源计算机图形学社区(Open Source Computer Graphics Community) | OpenGPU Project | OpenGPU Forum (2007-2013)

GMT+8, 2017-3-28 21:48 , Processed in 0.054007 second(s), 11 queries .

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部