原文链接
原文写得很好,但是主题格式我不太喜欢,所以我对文章的格式和部分错误的地方进行了修整校正,方便自己日后阅读
正文
美术大佬天天跟你谈,我要你给我实现 PBR 渲染,我问嘛玩意是 PBR 渲染呐?然后他就给你甩一堆图出来,什么荒野大嫖客啊、狂战士信条啊、使命召唤啊,说我就要这个效果,这就是 PBR 渲染。我吓一跳,要不咱拉一车面包人去育碧公司门口把他们图形程序绑票回来,然后让他来实现一个 PBR 可好。他说那可不行,公司不给报销,还是得你做。
现在很多人在说 PBR ,但是很多人的理解都不到家 ,认为 PBR 除了材质球其他都没啥。但是 PBR 意思是基于物理的渲染,整个渲染系统中还有基于物理的光照、基于物理的摄像机这两块内容也很重要,但是很多人的认识都是比较少的,所以我也补习了一下这块的资料,发出来抛砖引玉。
光学单位概念理解
立体角**(sr)
以观察点或者说是从摄像机镜头为中心,构造一个单位球面,也就是说用一个半径为 1 的球体罩在摄像机上。
问题:半径为 1 的球体,到底是半径为 1 m 还是 1 cm 还是什么其他的?
在平面上的一个二维角度,对应到单位圆上是一个弧线,在空间中的一个立体角(也叫弧面度),对应到单位球面上,就是一个弧面。
立体角事实上可以看作是 一个从原点出发的圆锥体(也可以是其他形状的锥体),这个圆锥体的尖端就是球心,而长度可以无限延升。
一个球体的表面积计算公式是 4πr² ,一个立体角被规定为面积为 r² 的弧面 ,所以说一个球体上有 4π 个立体角,近似的说,一个球体上有 12.5664 个立体角。
需要明确的是,在球体上只要是表面积为
r²的弧面对应的连接到球心的张角就是一个立体角,和这个弧面的形状没有关系,不一定非得是圆形,也可以是正方形等各种形状。一般来说,立体角直接用 “立体角” 这个单位计算就可以了,不过立体角还有一个单位叫 “平方度”,这个单位是用平面欧拉角进行推广而得到的,单位圆上每欧拉角对应的弧线长为 1 ,对应欧拉角规定一平方度的表面积为 1 ,而一个球体的表面有 41252.96 平方度。
回到开始的问题,球面度和球体的大小并没有什么关系,它是从球心出发的一个锥体。所以半径为 1 的球体,这个 1 的单位是可以人为规定的。
发光强度:坎德拉(cd)
在物理光照中,点光源的发光强度单位会使用 cd 来做单位,这个单位的英文名称就是 candles,一支普通蜡烛的发光强度约为 1 cd。
一个光源发射的光强是恒定的,但是随着距离光源越来越远,光线的衰减也越来越多。因此坎德拉这个单位 描述的是光源本身的亮度,而不是光源投射的光线照亮周围物体的亮度。
光通量:流明(lm)
一个强度为 1 坎德拉(cd)的光源在 每立体角(sr)均匀辐射出的光照总量为 1 流明(lm)。
流明这个单位相比坎德拉多了一个 范围的概念,坎德拉只描述光源本身发射的总能量的亮度,而流明则需要考虑这个光源是否对所有方向都发射了光线,如果一个光强为 1 cd 光源向所有角度都发射了光线,则它的光通量为 4π lm ,如果它只向正前方范围为 2 sr 的范围发射光线,则它的光通量就是 2 lm 。
这个概念在后面讲解光源的时候,可以分别对比 聚光灯 和 点光源 来理解。
亮度:坎德拉每平方米(cd/m²)
亮度其实很好理解,就是物体表面的亮度,不论是它自身在发光还是被照亮,只要人眼或者摄像机看到是相同的亮度,那它就是一样的亮度。
亮度的单位是 cd/m² 坎德拉每平方米 ,以前旧称为尼特 nit ,所以以后见到这两个单位名称应该知道是同一个东西。
可以做参考的是一台 27 寸显示器的亮度是 300 cd/m² ,在这个亮度下,其光通量约为 230 lm , 其光源强度约为 70 cd 。
照度:勒克斯(lux)
表示物体单位面积上接受到的可见光的能量。被光线均匀照射的物体在 1 平方米的面积上所得的光通量为 1 lm 时 ,它的照度为 1 lux。
自然中的物体表面受到很多光源影响,表面的照度就是 所有光源施加光通量的总和。当物体表面仅仅受一个光源影响,光源的发光强度恒定时,光源距离物体表面的远近会影响物体表面的照度,毕竟越近就会接收到更多的光线。但是对应到日光时候则有所不同,太阳和地表的距离足够远,因此基本上不需要考虑距离的因素。
游戏引擎中的各种光源
平行光
平行光一般用来作为场景的主光源,模拟日光的照射,均匀的照亮场景中的每个物体。
不论是 Unity 还是 UE4 中平行光(日光)的强度单位都是 lux,在游戏引擎中 1 lux 的光照看起来到底是什么样的?
在 UE4 中建立空场景,左边是一个 1 平米的平面,表面完全粗糙,基础颜色为 1 纯白,平行光照度 1 lux 。右边是半径为 1 的内凹球体,材质与平面相同,其中是光强为 1 cd 的点光源。
所以,排除一切干扰之后,1 lux 照度的平行光看起来就是这样的。如果想要让平面的颜色看起来为 1,就需要将平行光设置为 3.14 lux 。
上面的平行光数值为 3.14 lux,点光是 3.14 cd 。
所以,在排除一切其他影响之后,平行光强度为 3.14 时可以把垂直于平行光的面的颜色还原到物体本身的颜色。
在维基百科上显示日光在不同的条件下会在 111000 lux 和 <1 lux 的范围之间波动,按照这个规律来理解,是不是在这个范围内调整 UE4 中日光的强度再配合后处理的眼部适应就可以得到完全物理的画面效果?
但是并不是这样,UE4 中 DirectionalLight 的亮度滑条最大只有 150 lux。如果超出这个范围,画面就完全白了,后处理都不管用。
这是原场景:
当我把阳光改到 10000 lux :
不是物理灯光吗?难道是假的?这里需要在项目中开启以下选项。否则默认的自动曝光不够给力。
当修改了自动曝光的范围之后,再看场景:
确实是有了正午大太阳的感觉了。
所以还原真实的光照效果是需要靠 物理光照 和 自动曝光 共同作用才能完成的。
天光
天光一般是捕获周围环境储存到一张 HDR 贴图中,或者是由美术自行指定 HDR 贴图。天光主要是 为场景提供均匀的间接光照,当场景中仅仅有一个平行光的时候,物体的暗部会是完全的黑色,天光可以防止这种情况。
天光是这所有的光源中最为特殊的一个,因为别的光源都是直接光照,而天光却是间接光照,在真实世界中,所有的间接光照都是由直接光照反射之后产生的,但是实时渲染中无法计算直接光照的每束光线是如何反射的,所以就需要预先捕捉或者指定一个周围环境的 HDR 贴图作为间接光照的来源。
天光的单位是 cd/m² ,关于这个单位应该怎么设置,网上的资料比较少,甚至于这个单位本身的介绍也比较少,我这边也只是寻找资料加上自己推论得出的想法。
第一,cd/m² 是一个描述亮度的单位,不论是物体自己发射的光还是被别的光源照亮,都可以被描述。在现实生活中一般会在显示器的说明书上看到它。那么作为天光,它指的是天空球本身的亮度吗,就像是把天空球作为一个显示器,而亮度单位 cd/m² 用来描述它本身的亮度?很显然不是的,天光并没有距离和方向的概念,它只是均匀的作用在场景中的每个物体上。
所以 天光的亮度 指的是被天光影响之后,场景中的物体可以产生的亮度。
以下是我做的一个测试,在场景中放置了一些白色的几何体,而天光则指定了一张纯白色的 HDR 贴图,其强度设置为 1 cd/m² ,排除一切其他(曝光,直接光源、雾)影响,以下是照明结果。
几何体的朝上的部分被还原成了白色,朝下的部分是灰色,看来天光影响场景的时候也是会考虑物体法线的朝向的。
所以这里可以确定,1 cd/m² 的纯白色天光可以还原物体本身颜色。
第二个问题 是,在物理渲染中,各个时段的天光强度应该怎么设置?上面讲平行光的时候有一个图表,其中光照强度的变化非常大,从十万到零点几 ,那么天光到底该怎么设置才能配合平行光,成为物理正确的光照效果?
这个方面的资料更少了,基本上没有一个比较权威的专家来指出天光到底设置成什么数值才是物理正确的。我只找到一个由经验值总结的表格,表示天光的亮度数值应当是 平行光的 5%。
虽然对这个表格的数值是否物理正确还有疑惑,但是我实践过后,感觉上图的数值问题不大,毕竟图形学嘛,看起来对就是对了。
那么有没有更加物理的设置呢?
这里借用 nnnd 大佬的文章中做的总结:物理灯光亮度值参考
上图中是实际测量得到的数值,单位是 lux 。
- Sky+Sun 是站在地面无遮挡的位置测得的光照度。
- Sky 可以简单理解为站在 太阳被遮挡 的位置测得的光照度。
- Sun 则是上面二者做减法得到的。
上面表格中的各个时段的阳光和天光的比值是 非常重要 的,可以在制作场景的时候作为参考。
上面讲的都是在 室外场景 中如何设置天光,那我在 室内场景 中到底该如何设置天光?
这是一个简单示意图,可以看到在室内一般是 300 lux 左右的光照强度。
如果要更详细的理解,可以看看 @逍遥剑客 大佬这个文章 游戏中的自动曝光(一): 光照单位
这里写的单位都是 lux ,那 lux 和 cd/m² 该怎么换算?
简单的说 3.14 lux 强度的光线照在纯白的表面上可以让这个表面呈现 1 cd/m² 的亮度。
美术同学可以直接理解为
3.14 lux = 1 cd/m²问题也不大。
点光源
点光源在游戏中一般用来模拟灯泡,在空间中的一个点向四面八方均匀发射光线。
点光源使用的单位是 cd(坎德拉) 和 lm(流明),在设置点光源强度的时候这两个单位是可以固定转换的,1 cd = 12.56637 lm 。
那么 1 cd 的点光源看起来到底是什么样的?
可以参考上面讲解平行光的部分,1 cd 的点光源可以让半径 1m 的球体呈现深灰色,3.14 cd 的点光源可以还原物体本身颜色。
需要说明一下的是,点光源的影响范围(衰减半径)不会改变点光源的衰减程度,因为在物理渲染中,光线的衰减是由物理测量结果来决定的。
上图中调整点光源的半径不会影响点光源的亮度和衰减。这也是为什么在搭建游戏场景的时候需要按照真实世界的比例来搭建,因为如果太大或者太小的话,打光的时候会有一种不论怎么调都没那味的感觉。
从 cd 这个单位的定义可以知道,1 cd 最初指的就是一支蜡烛的发光强度,在后来电灯的时代,基本上功率 1 W 的电灯发光强度和 1 cd 差不多,所以在游戏中放置一个 100 W 的灯泡的时候,直接设置点光源强度为 100 cd 是没什么问题的。
现在几乎所有的电灯包装上都会注明其发光强度,而且由于科技发展电灯的发光能力变强,1 W 的电灯也不一定对应 1 cd 的发光强度了,所以最好是查看淘宝或者是灯具厂家的数据标注。
在不开启自动曝光的情况下,各种强度的点光源的光照效果如下:
聚光灯
聚光灯作用也非常好理解,用来模拟舞台聚光灯、手电筒这类光源。
虽然聚光灯的单位也是 cd 和 lm ,但是这里就有讲究了,点光源的 cd 和 lm 的转换关系都是 1cd = 12.56 lm ,但是在聚光灯这里就不同了。在 lm 单位的定义中不仅有 光强 的概念需要考虑到 立体角 的概念,意思就是说如果一个 1 cd 的光源向所有角度发射光线,那它的光通量就是 12.56 lm ,但是如果只是向一个方向发射光线呢?那它就要考虑这个范围的大小了。
这里做个展示:
同一盏聚光灯,只是张角变了,其强度中的 lm 就变了。聚光灯打光的时候,如果使用 cd 标明单位,则不论怎么修改锥体大小,视觉上的亮度都不会变。如果使用 lm 标明单位,则缩小锥体的时候会明显感觉到光线变亮了。
上图中是亮度为 100 lm 的聚光灯,随着张角的改变,其光线逐渐聚焦,看起来也就越亮了。
内容就是以上这些,看到这里的大佬,你觉得有用就点个赞,你点赞的样子特有范,要是以后还要把这篇文章看,点个收藏也很好办。