游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2444|回复: 0

从真实世界到渲染

[复制链接]

1万

主题

1万

帖子

3万

积分

论坛元老

Rank: 8Rank: 8

积分
36572
发表于 2020-4-15 15:45:42 | 显示全部楼层 |阅读模式
1.jpg


问题

在PBR的渲染方程中,最常见的一个就是 1.png   ,虽然看起来含义很直观,但是仔细一想就会想到很多问题,这些量的单位究竟是什么?进一步思考,显示器是如何模拟现实世界的颜色的?HDR究竟是啥?带着这些问题,我们开始来阅读本篇文章.

辐射量

辐射量是使用纯物理的方式来描述电磁波和辐射.简要介绍常用的辐射量.

1.辐射能(energy) 2.png ,单位是焦耳 3.png ,单个光子的辐射能表示为 4.png .

2.辐通量(flux) 5.png ,单位时间内发射,接收或传输的能量 6.png ,单位是瓦特 7.png .

3.辐照度(irradiance) 8.png /辐出度(radiant exitance) 9.png ,辐照度表示单位面积受到的辐通量 10.png ,辐出度表示单位面积发出的辐通量 11.png ,单位都是 12.png .辐通量为 13.png 的点光源在距离 14.png 处球面上的辐照度为 15.png .

4.辐强度(radiant intensity) 16.png ,元立体角内的辐通量 17.png ,单位是 18.png .

2.jpg
立体角

立体角(solid angle)可以看作平面角在球体上的扩展,单位是球面度 19.png .整个球面的总立体角是 20.png ,半球面的总立体角和是 21.png .

5.辐亮度(radiance) 22.png ,表示单位面积和单位立体角上的辐通量, 23.png ,单位是 24.png .辐亮度是用来描述传感器(摄影机,人眼等)感受辐射最常用的量,也是最重要的量.

3.jpg
辐亮度定义

光度学

辐照学的量都是用纯物理的方式来描述,然而其实人眼只能看到波长在400nm-700nm波长的电磁波,所以需要单独用来描述人眼感知的光学量.

光度学中的量其实是跟辐照学中的量是一一对应的,这里不再逐个说明.包括光通量 25.png (单位流明 26.png ),光照度 27.png (单位勒克斯 28.png ),发光强度 29.png (单位坎德拉 30.png ),光亮度 31.png (单位 32.png ).

5.jpg
对应关系

其中发光强度是光学的基本量,是国际单位制七个基本单位之一.

一些常见表面的亮度值:

6.jpg
常见光亮度

辐射量和光学量的转换

光在不同波长上的分布,叫做光谱功率分布(spectral power distributions/SPD).

7.jpg
三个不同的SPD,第一个是单色光,第二个是混合光,第三个是户外自然光

人眼作为一种探测器,输入是辐射量表示的可见光辐射,输出感受值的光学量.辐射能到发光能的转换可以表示为 33.png .

34.png 是光谱功率分布,单位是 35.png ;

36.png 是光度函数,没有单位;

37.png 是波长,单位是 38.png .

8.jpg
光度函数

渲染公式

我们在所有的渲染公式中用到的都是光度学单位(因此本文后面说讲的单位都是光度学单位,不再用下标区分).而描述我们看到的颜色的最终结果的单位都是 39.png .

鉴于点光源和平行光源的不同特性,在游戏引擎中其实是使用不同的单位来描述其强度,点光源用发光强度 40.png ,单位是 41.png ,平行光源是用光照度 42.png ,单位是 43.png .

对于点光源 44.png ,发光强度为 45.png ,对于距离 46.png 处的形成的光照度为 47.png .可见点光源在某处的光照度和距离平方成反比.

这样,我们再看反射方程,就清楚地理解其中的含义了:

48.png

物体表面的出射亮度等于所有入射光在在半球表面反射后的积分.

49.png 单位是 50.png , 51.png 单位是 52.png .

CIE标准色度学系统

虽然自然界真实的光照有很复杂的SPD,但是因为人眼的颜色感受细胞其实只有三种,分别感受红绿蓝三种颜色.所以其实可以将复杂的光谱功率分布转换成RGB表示.

根据CIE-RGB标准,指定三原色 53.png (645nm), 54.png (526nm), 55.png (444nm),用下面的光谱映射函数和SPD求内积,来将一个任意的SPD表示为三个刺激值.

9.jpg
RGB

但是这种方式得到的值有负数,不便于计算,因此又有了CIE-XYZ系统,在CIE-RGB的基础上改进.

将SPD 56.png 通过求内积转换成三个数字 57.png 三刺激值:

58.png

10.jpg
XYZ

值得注意的是 59.png 的曲线其实就是前面讲过用来计算光度学量的光度函数,即 60.png 值可以作为颜色的亮度值.

为了把颜色的亮度和色度区分开,再定义

61.png

62.png 值忽略,用 63.png 的值来做出一张图,得到CIE色品图(hromaticity diagram).

图中的边缘的曲线表示纯色.图中黑色的点是白点,代表D65纯白色.在图中任取一颜色,连接白点和颜色点延长后和边缘相交处的颜色叫做色相(hue),白点到颜色点的距离与白点到边缘的距离的比值叫饱和度(saturation).

11.jpg
CIE1931色品图,图中的白色三角形表示sRGB的色域,黑色的点表示D65白点

从色品图中取色,再加上亮度值,就可以构成 64.png 坐标系统来描述任意颜色.

在色品图中选取三点作为纯色RGB颜色,构成一个三角形,就组成一个色域(gamunt).色域中的颜色可以任意进行线性混合.上图中的白色三角形就是电视和显示器中最常用的sRGB的色域.需要注意的是,色相图中的色域只是一个投影,真实的色域应该是一个立体形的,包括亮度值.

为了使颜色在色品图中分布更加均匀,在CIE 1931 XYZ色品图的基础上又推出了CIE 1976 UCS色品图.

12.jpg
CIE1976 UCS色品图,以及三个不同的色域

RGB色域有很多种,上图是常见的三种.sRGB(这里指的是线性sRGB)是显示器中最常见的色域,也是目前绝大部分实时渲染中用到的色域. REC 709和sRGB白点相同,常用于高清电视.一些用来做照片剪辑的显示器使用Adobe 1998色域. DCI-P3是苹果系列产品使用的色域. ACEScg是一种设计用来计算渲染的色域.

从RGB色域到 65.png 三刺激值的互相转换也非常简单,其实就是一些线性的运算,可以用两个3X3矩阵来表示.

比如在sRGB色域中,得到[ 66.png .上面说过 67.png 值其实就是亮度值,所以这也是实时渲染中常用来计算亮度来进行自动曝光的一个公式.

尽管从严格意义上来说RGB颜色并不能完全反映真实世界中物体对光SPD的反馈,但是在绝大多数情况下效果都是非常不错的.目前只有少部分工业级电影的离线渲染使用频谱渲染.

下面就来讲讲显示器的显示.

伽马校正

早期的CRT显示器,输入的电压和显示的亮度并不是线性关系,而是大概是 68.png 的关系.现代的液晶显示器基本沿袭了CRT显示器的输入输出关系.液晶显示器的显示亮度和输入值的关系也称为EOTF(electrical optical transfer function),由硬件来实现,在电视,显示器,电影等不同的场合亦有不同的标准.

实时渲染中的颜色计算都是在线性空间中进行的,因此要想让显示器输出正确的颜色值,需要在最后一步输出到FrameBuffer时进行伽马校正,来抵消EOTF的效果.

13.jpg
伽马校正

sRGB编码

人眼可以识别很大范围亮度的光照,这也导致了人眼对亮度的感受会随着亮度的增高而减弱.比如下面图中的线性编码的亮度,会明显觉得人眼对低亮度时的变化更加敏感.

14.jpg
线性编码和伽马校正编码

假设我们用8bit(0~255)来编码颜色,如果线性地按照亮度的关系进行编码,就会导致人眼在低亮度时感觉相邻颜色变化很大,而在高亮度时感觉相邻颜色变化很小,导致编码空间的浪费.

所以我们将线性的sRGB色域颜色值先应用一次伽马校正,组成sRGB伽马编码.这样即可以完美利用编码空间,又不需要在显示时再进行伽马校正,可谓是一举两得.

平常我们见到的大部分各种格式的图片,都是按照sRGB伽马来进行编码的.

sRGB与渲染

为了保证渲染结果计算正确,在计算的时候需要采用线性的颜色值.所以在从图片中取像素值的时候,需要先将伽马校正后的像素值解码回来成线性的颜色,渲染计算完后,再伽马校正输出到framebuffer.

15.jpg
sRGB渲染

如果忽略伽马校正,就会导致颜色计算失真,也会对AA有影响.

有的手机出于性能考虑,会使用 69.png 来加速伽马校正,也有的会完全忽略伽马校正.

HDR(high dynamic range)显示器

先说明下HDR一般有两种意思,这里的HDR和SDR(standard dynamic range)对应,指的是HDR显示器.而在渲染中所说的HDR,其实是指tone mapping,后面会讲到.

随着现代显示器不断升级,可以支持的更大的色域,支持的最大亮度也更高.HDR显示器使用Rec. 2020和Rec. 2100标准.Rec.2020 定义了一个比sRGB大得多的色域,Rec. 2100定义了PQ和HLG两种非线性编码.

从应用向显示器传输HDR数据的时候,有HDR10,scRGB,Dolby Vision三种方式.


Tone Mapping

现代的PBR渲染中,在计算渲染和光照时,都是按照真实世界的光亮度来计算.计算完成后还需要把亮度值转换成可以在显示器中显示的范围,这个过程就叫做tone mapping.可以说, tone mapping在绘画,摄影,电影等领域早已得到广泛地应用.

渲染中所说的HDR,和LDR相对应,tone mapping就是把HDR范围的光亮度转化成显示器可以显示的LDR光亮度.

现实世界中和人眼可以识别的光亮度范围要比显示器的亮度范围要大得多,tone mapping的目的,就是尽可能还原图像中的细节,而不是单纯地线性对光亮度进行缩放.所以tone mapping实现的光亮度映射,是一条S型的曲线,这样可以保留亮部和暗部的细节.

比如最早期的Reinhard tone mapping,实现非常简单.颜色的映射关系是这样的: 70.png , 71.png 表示图像的平均亮度.

16.jpg
Reinhard tone mapping

后来出现了各种各样的tone mapping方式,对Reinhard tone mapping进行改进.

ACES是美国电影艺术与科学学会提出的一种用来在电影中使用的一整套的编码显示方案.实时渲染中借用了其中tone mapping的部分,目前已成为游戏引擎中的主流方案.

17.jpg

如果输出的目标是HDR显示器,因为显示器的最高亮度往往较高,且有的显示方式自带tone mapping,所以需要根据具体的显示方案做出调整.

曝光度和EV100

不管以何种方式进行tone mapping,计算图像的整体平均亮度都是必须的.计算图像的整体亮度一般采用log平均的方式.

传统的方式是算出图像的亮度log值后,不断DownSample直到一个1x1的texture,即可算出图像的平均亮度. 现代的做法是使用ComputerShader,统计每个亮度范围的像素点数,再综合计算得到一个亮度值.

EV(exposure value)在摄影中表示需要的曝光值.EV100表示在ISO100标准下的EV值,和光亮值的关系可以用公式表示为 72.png , 73.png 表示光在光学系统中传递时的损耗,游戏引擎中是一个模拟值,常取 74.png .在游戏引擎中也常用EV100的值来定量地描述曝光值。

参考链接
https://learnopengl.com/Advanced-Lighting/Gamma-Correction
https://zhuanlan.zhihu.com/p/37800433
https://en.wikipedia.org/wiki/Luminosity_function
https://en.wikipedia.org/wiki/Chromaticity
https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
https://zhuanlan.zhihu.com/p/21983679
https://zh.wikipedia.org/wiki/%E6%9B%9D%E5%85%89%E5%80%BC
<Real Time Rendering 4th>
<工程光学 郁道银>


作者:TC130
专栏地址:https://zhuanlan.zhihu.com/p/118272193

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

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2024-4-26 22:13

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表