,而有的就没有?我们使用BRDF时输入是什么?输出又是什么?
有些文章对这些问题进行了全面深入的讨论,但这部分文章往往包含了大量的公式推导,让人看得昏昏欲睡进而产生了些信息损失,让人难以完全理解。而有的文章则是只探讨了PBR中得BRDF这一小部分或者是BRDF中的部分内容,同样会让人产生些误解或理解偏差。
本篇文章旨在尽可能的减少公式和理论推导,来讲述一个从基础光源到基础材质的PBR流程。让读者能够清晰明了的理解光源与BRDF间的关系以及是如何交互的。
我买了一个电灯泡,把它看作一个理想的点光源:
这是一个40W的光源,从生活的角度来看这意味着这个光源每亮25小时就会消耗1度电。从物理角度来看,这表示这个光源每秒消耗40J能量。这些能量不会全部转换为发出的光能,而是有一部分转换为了热能,但通常灯具厂商不会标注出这里的能量转换效比,我们就假设其能量100%转换为了光能。那么这个点光源每秒就会发射出40J的光能。
Radiant Power 表示一个光源每秒发射出的光能量,单位 也即 。对于上面这个光源来说,它的 Radiant Power 就为 40W。本文中以 表示
我们人眼对于不同波长光的感知能力是不同的。例如尽管紫外线能量高,但是我们人眼并不能看到紫外线,因此我们可以认为紫外线能被人眼感知到的能量为0。
,CIE(国际照明委员会) 对此有过实验测量和结果,称之为 CIE photometric curve(CIE 光度曲线):
但灵敏度为1并不代表着这个光的能量能够被人眼全部接收。
(流明)
对于辐射通量为 1/683 W 的 555nm 的绿色光来说,这意味着 1lm = 1/683 W,也即 683 * 1W = 1 lm
那么对于其它波长的光,我们就可以看作:
是上面提到的光度函数。
表示
为什么要特地选择 1/683 W 的 555nm光?1W的555nm光不是算起来更简单吗?
这与人类对于光学研究的历史有关。以前人们把 将一磅鲸鱼油脂制成六支蜡烛,以每小时120格令的速度燃烧时,在水平方向产生的烛光 规定为 人眼对其感受到的强度为 1,称之为 1cd(坎德拉)。现在看来烛光这种定义过于抽象和离谱,因此后面这个定义又做过些修改和更新,最终认为 1/683W 555nm 的激光被人眼感受到的强度跟前面这个烛光的强度一致,因此选择 683 这个数字。
称之为 luminous efficacy(光视效能):
可得:
(坎德拉) ,本文以 表示。
什么是立体角?
。公式推导就不上了,直接给结论:
和,也就是这个光线方向的极坐标,也就是只与方向相关。因此要定义像光强度这类只与方向相关的量时,就需要用到立体角这个概念。
回到点光源,我们对球体做立体角的积分可以得到:
,点光源是朝各个方向均匀发射光线的,因此就可以得到任意方向上点光源的光强度:
其被定义为材质表面每单位面积受到的光通量(per area Luminous Power),单位为 (勒克斯),本文以 表示。
如果你足够细心,就会发现这里的定义与前面的不一样了。前面与光能量相关的定义都是光源发射出的能量,而这里变成了材质表面接受到的能量。这是因为照度与距离有关(后面会具体解释这里与距离的关系),而理论上光源发出的光是会朝一个方向一直运动到无限远的,也即光源发出的光量都应该和距离无关。而一旦引入距离概念,那么就说明光撞到了一个材质表面,这样才产生了距离,所以这里是材质表面接受到的光量。
照度与光强度存在距离平方反比关系,推导如下:
),在单位距离() 的位置上的单位立体角:
而单位立体角上的光通量就是单位光强度:
这个距离上时,此时的立体角为:
那么这个距离上,这个单位面积受到的光通量也即照度为:
也能看出是这么一回事。
(尼特) 或 ,本文以 表示。
材质表面受到光照后会朝一些方向反射出光能量,因此这些反射出的光能量具有方向性,所以我们在照度的定义上再引入立体角,就产生了亮度这一概念。
和 亮度 之间的转换关系是什么呢?我们定义它们之间的关系为这样一个函数:
这样就有:
就是我们所说的 BRDF 函数。
我们的光能量从光源出发经历了上面这些旅程,名字变了又变,这段旅程可以用一张图表示:
这趟旅程间的转换公式为:
回到点光源,在我们推导光强度时是基于球体计算的,基于此得到的照度也是球体表面上的单位面积,这与实际照射到的材质表面单位面积是有区别的。
,照度为 ,物体表面的单位面积为 ,照度为 。
而 BRDF 的分母应该是物体表面的照度,因此我们将其更新为:
和 存在这样的转换关系:
因此 BRDF 函数也就可以更新为:
:
这部分对于上面这些定义和推导做个总结,以便下面我们直接套公式即可,依然是以点光源为前提。
Radiant Power 辐射通量,定义为光源每秒发出的光能量,单位 或
Luminous Power 光通量,定义为人眼感知到的光源每秒发出的强度,单位
Luminous Intensity 光强度,定义为光源单位立体角发出的光通量,单位
Illuminous 照度,定义为材质表面单位面积受到的光通量(基于以光源为球心的球体得出), 单位
Illuminouse 材质表面照度,具体到一个法向为的表面,其单位面积受到的光通量, 单位
Luminance 亮度,材质表面反射出的单位面积单位立体角光通量,单位
luminous efficacy 光视效能,定义为
BRDF 双向分布反射函数,定义为
存在转换关系:
和 镜面反射部分 ,进而转换关系可以更新为:
碍于篇幅关系和B站这沟槽的还不支持MarkDown的专栏,Disney BRDF 的具体内容大家可以自行去查看。Disney BRDF 是开源的,在文章最后的参考部分我会给出链接地址。
这些推导是基于点光源,那么对于其它光源呢?
方向光是对于太阳光照射到地球上局部小面积的抽象概念。而太阳也可也看作是一个点光源,因此这些推导完全适用。并且我们这样的推导还可以把太阳照射的这个小面积推广到整个地球表面(如果你想要开发一个超大世界游戏或者是星球游戏的话这非常重要)。
聚光灯可以看作是从点光源的球体中取出一个圆锥。上面推导的公式不再完全适用,但也只需要做出一点点修改,具体修改为:把光通量到光强度的转换进行修改:
为 聚光灯这个圆锥投影到平面上其展开的角度
至于其它光源本文不作讨论(因为我还没推到过)
和信息的,我们最终只能得到光强度 ,这也就是我们对材质的输入,其前面的这些转换都可以在材质外计算好。
和计算出的 , 可以计算出当前材质表面受到的照度 ,这就是我们对 BRDF 的输入
乘上 就能得到材质的输出,即 亮度
至此光源从发出能量到被材质表面接受再到被材质表面发射,这一段旅程就全都被我们经历过了。
但完整的PBR流程远不止于此,材质表面反射出的光能量还要被人眼接收或者是被相机接收,这之间的关系如何?被相机接收到的光能量具体到玩家屏幕上发出的颜色和亮度又是关系如何?这些都是一个完整的PBR流程要考虑的问题。
不过这些都不是本文要探讨的重点,因此只做抛砖引玉,供读者思考。
https://seblagarde.wordpress.com/wp-content/uploads/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
https://tigoe.github.io/LightProjects/color-spaces-color-temp.html
https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
https://zhuanlan.zhihu.com/p/60977923
https://google.github.io/filament/Filament.md.html#listing_diffusebrdf
https://blog.selfshadow.com/publications/s2015-shading-course/#course_content
https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function
Disney BRDF:
https://github.com/wdas/brdf/blob/main/src/brdfs/disney.brdf