图形渲染(16):你绝B看不懂的PBR(1)——筑基·数学
补充在前:
今天是2022年12月11日,一年前的今天,毛星云前辈离我们而去,我为什么记得那么清楚,那天是我十八岁的生日,我们同处一个城市。星云前辈作为我游戏路上的领路人,当初拜读过他那本书,是他的文字让我在自己方向迷茫时,毅然决然的抛弃功利想法,全心投入到自己热爱的领域,去追寻自己的游戏梦。
虽未曾谋面,但前辈于我有着特殊的意义,在此缅怀前辈。
以下是正文:
最近一段时间一直在研究这个PBR,总体感觉还是比较有难度的,研究的时候也很吃力。同时学习的同时也暴露了自己在数学等方面的基础不足问题。
而这个PBR,他还越来越主流,研究的人越来越多,这就为很多数学基础差的同学,或者是那些偏美术的TA等同学带来了很大的阻力。
而这方面中文资料并不多,系统的入门的讲解也更加少,导致基础差的人敲开PBR的大门得费老大劲。
我一般也不想着去重复造轮子,但这方面很多文章都很零散,所以花点时间梳理一下,文章以入门为主,帮助各位敲开PBR的大门。标题叫:你绝逼看不懂,其实我想写的是让你绝逼能懂的PBR,哈哈。
目录部分:
图形渲染(16):你绝B看不懂的PBR(1)——筑基·数学
图形渲染(17):你绝B看不懂的PBR(2)——金丹·BRDF
图形渲染(18):你绝B看不懂的PBR(3)——元婴·DGF
图形渲染(19):你绝B看不懂的PBR(4)——化神·Kulla-Conty
图形渲染(20):你绝B看不懂的PBR(5)——炼虚·Diffuse
图形渲染(21):你绝B看不懂的PBR(6)——合体·Code
图形渲染(22):你绝B看不懂的PBR(7)——大乘·IBL
【这里为保证系列文章的连贯性,中间书写的时候也前前后后一直修改,因此是一起写完再发出来的。】
此系列文章不需要你有高等数学的基础,但是这并不意味着我对数学避而不谈,但是也并不意味着你没有高等数学基础就看不懂。
我主要从一个high level的角度来把微积分那些数学思想讲出来,随着文章的推进,我也不会刻意去抹掉很多数学不讲,我会像标题一样,反其道而行,我会引入越来越多的数学,原因是大多数人看那些公式第一次看多少都有点懵逼,看的多了就好了。
因此,我会让你逐渐接触这些东西,逐渐的熟悉他们,当然数学思想为主,以看懂数学符号背后的东西为主。
我尽力写的通俗,如果这你还看不懂,那就留言或者私信吧,到时候我看情况修改下文章,改到你懂为止,既然已经花时间做这件事情了,那就把他做到完美吧~
其实我感觉那种本身偏美术的同学就应该学点数学,我就挺羡慕这类同学,本身具有浓厚的艺术修养,再把数学这些搞明白,妈的学完之后理性感性皆通,老子天下无敌。哈哈哈哈哈哈~~
ok,废话说完了,下面开始正题。
本文尽可能通俗的去解释,但是也不可能对于每个人面面俱到,所有有些概念不懂的,用鼠标选中然后右键再点击在Web中搜索"XXX"基本上都能解决。
其实我觉着PBR也没啥,感觉搞定PBR就是搞定里面的数学公式,搞清楚公式逻辑,理清楚公式来由。但我又感觉PBR中的数学除去那些推导的部分,其实也根本没什么数学。为什么这么说呢?先看下图,这是后面要说的一个小推导:
关于上边公式,第一次看可能觉着,卧槽写这么大一坨,全是字母乱七八糟的,这哪看得懂。
这里划重点:其实关于PBR中的数学,大致分成两块,一块是 某个东西=一大坨,就类似上边推导出来的最后一个式子。还有一块是A=B=C=D=E=F......=Z数学推导过程(除了A,后面的字母都是一大坨的式子)。
相对来说前者其实更重要一些,而且这个想要理解根本用不了多少数学,这个式子的背后其实是我们所熟悉的物理现象,是形象化的东西,只是抽象成数学表达便于我们做一些运算而已,真正难的点在于后者,有些部分大量数学变换运算的技巧在里面,各式各样的数学混杂在一起,需要你很厚的数学底子才能看得懂。
综上,我的目的就是让你完全理解第一块的东西,加上第二块中相对简单的推导部分。下面开始:
这里说到PBR时,会连带这周边的东西,所以要想理解好PBR,我们需要先把周边的一些东西说清楚。同时我觉着理解一个东西最简单的方式就是从你熟悉的东西去下手。
之前说D3D的那篇文章,我从怎么画画来引入D3D程序。而今天就从怎么看/看什么的角度来说PBR相关的。
首先我们眼睛看到东西是因为东西发光或者反弹光,看到东西是各式各样的,是因为看到的亮度,看到的光的能量各不相同。
而游戏中我们看的是显示器,也就是显示器发光,显示器的背后是一张计算好的图片,图片中记录了屏幕要发出的能量。
因此看到的能量的多少就是渲染的图片中记录的能量,而图片记录的能量,也就是每一个个像素的所记录的能量,而每一个像素的能量是怎么来的呢?
我们知道,对于像素的能量计算,我们是模拟人眼看东西时的透视投影效果来算的。也就如下:
https://zhuanlan.zhihu.com/p/21489591像素展示的能量,也就是像素背后的那个物理场景中那个蓝色块射向像素的能量。
【这里其实涉及到两个概念,光线追踪和光栅化,前者是从摄像机出发去根据像素位置找到像素对应的蓝色块,也就相当于从上边的锥顶点部分连出来四条线构造出锥,而光栅化就是先有了蓝色块,然后投影到左边的面上找到对应的黄色块,这俩再构造出上边的四棱锥。】
但无论是光线追踪还是光栅化,都不是求解整个蓝色块射到像素上的能量,而是其中一点或者几点的能量,来作为最终整个块的代表。
那对于一个点是如何计算的呢?那肯定是光源发出的能量,然后照射到蓝色块,在他上边作用一波,然后蓝色块射出去的能量了。也就是我们要把光源能量摸清楚,如何作用摸清楚,就算出蓝色块射出的能量了。【这里说蓝色块射出是指的它折射或者散射反射等射出去的能量,当然也可以包括复杂的自发光情况】
而我们要基于物理的精确计算这些能量,就得引入一些标准的量来衡量我们看到的亮度。那么什么能够衡量我们看到的亮度呢?【注意实际传递的是能量,而最终能量会决定我们看到的亮度】
我们先简化一下,假设直接看到的是灯泡,然后从一个灯泡来解释一些概念,这里灯泡认为是一个会发光的球。
首先这个决定我们看到亮度的能量具体是什么?他并不是灯泡发出的全部能量,我们想象两个不同亮度的灯泡,暗的发光2分钟和亮的发光1分钟耗的电是一样的。【假设电能完全转化成光能】但是这个实际亮度并不一样。也就是说我们看到的亮度并非指这个发出的总能量:Energy,通常用Q表示。
我们可以看到一个2分钟,一个1分钟,和时间有关系,那么看到的亮度是否是单位时间内发出的总能量呢?单位时间内发出的总能量也就是用总能量除以时间,用 来表示,即
,t表示时间。
这里两个东西要说,一个是公式中的d是个什么玩意?【关于d的,后面再说】还有就是我们看到的亮度其实也并非是发光点单位时间内发出的总能量。为什么呢?
单位时间内发出的总能量,我们可以用这个量去衡量一个灯泡,也可以衡量他上边一小块面积单位时间内发出的总能量。然后我们遮住其他的地方,只看这一小块的亮度。然后我们选择另外一个大块,也是同样的方式处理,其实对于同一个灯泡,我们看哪一块,不论大小,亮度都是一样的。
但是这俩不同大小的块,单位时间内发出的总能量并不一样,但我们看到的亮度是一样的,也就说明了看到的亮度并非指的是单位时间内发出的总能量。
因此我们要把面积这个因素排除掉,也就是我们考虑单位时间内,单位面积发出的能量记作irradiance,E来表示。 。公式还是一会说,A表示面积。
这个量是否能够表示我们看到的亮度呢?考虑一个情景,我们如果把一个灯泡换成聚光灯,我们从不同的角度来看这个聚光灯的同一块小面积,其实看到的亮度是不同的,而这一块小面积单位时间发射出的总能量前后肯定不变。两次看的面积又是同一个的,即E相同,但是看到的亮度并不相同。
也就是说我们需要把角度的因素考虑进来,即单位时间内,单位面积,朝着某一个特定的角度发出的能量,记作radiance,用L表示。
,这里的角度用w表示,这个角度还有些特殊,后面介绍。
最后这个radiance表示的能量,就能准确的记录我们实际看到的亮度了。
还有一个概念,就是如果不考虑这个灯泡的体积,那么也就没有面积一说,我们从他上边的看到的亮度,应该是取决于:单位时间内,特定方向下发出的能量Intensity,记作I, 。
【上边只是为了感性的理解这几个概念,有些说的不严谨的地方,主要把概念理解了即可】
这里强调一点:上边我们说的都是发出的能量,其实接收也可以用来描述接收的能量,也就是Q可以表示一个物体总共接收的能量, 表示单位时间内物体接受到的能量,其他也类似了。
补充一点:你会看到什么A情况下,B情况下(代指上边那些单位时间/面积)的能量,其实多数情况下都是拿能量去除以A除以B代表的东西,比如时间或者面积,方向(除以方向,什么鬼?后面解释)。单位时间的能量,比如对于一段时间t下的能量N,就是N/t。
理解了这些物理量,我们第一步就做完了,也就是对于光源发出的能量以及物体接收的能量,我们可以用上边所说的量来精确描述。而接下来就需要探讨这些能量和物体如何作用,作用后射出去的能量是多少。
先来点数学,我们说过数学符号的背后其实是一些形象化的东西,这里就把这些形象化的东西来和符号做一个关联。
第一个: 积分符号,这里他往往和几个东西搭配出现:
。
说这些之前,先把微分和积分的思想介绍一下:
我们要求上边一个蓝色曲线,01位置俩竖线和x轴围成的一个面积,这个面积有点类似梯形,只不过梯形有一个边是曲边。【上边图0位置的值不是0,所以梯形】
思想就是:我们直接求,没有什么公式可以做到,但是我们会的是求矩形面积,那就把它切分一下,按照上边切分,如果我们求所有的矩形的面积之和,你会发现和要求的曲边梯形的面积是接近的,同时对比上边俩图,你会发现我们分割成矩形分割的越窄,最终累加之后就越近似真实的面积。
而我们引入一种无穷的概念,dx,就代表把x轴进行分割,每一份都分割成无穷小。这个时候累加所有的矩形面积之后就和实际的面积无限接近,也就认为相等了。
而上边说的把x轴分割成无穷小,这就叫微分。这些无穷小再去乘以相应的高得到一个对应的矩形面积,把这些无数多的矩形面积累加起来的过程叫做积分。
而我们积分的时候是把从0到1的所有矩形给积分起来,也就是式子中的a=0,b=1。表示积分的范围。同时微分的时候也是把0到1的给分成无穷小的dx。
另外有时会出现: 这种东西,这个没了f(x),也就是f(x)为1,那就是对dx乘以1进行积分,我们当初是把0到1给分成了无穷小,把每一份dx累加起来,得到的结果不就是从0到1的宽度么,其实也就是积分区域的宽度。
回到上边的公式部分
这种式子怎么看?上边dQ,你把能量分成无数多的份,每一份是dQ,dQ是什么能量?
记住这种式子从下往上看。下面是dt,我们知道t表示的是时间,因为随着时间不断流逝,灯一直在发光,就有一个隐含的时间轴。而dt就代表在这个时间轴上的很微小的一段时间。
重要的是:下面决定上面。dt是照射过程中很微小的一个时间段,然后dQ就是与之对应的该时间段内,光发出的能量。
那么一段时间内发出的能量,除以这段时间,不就是flux的定义么。
这里和 这种定义有什么区别?ΔQ或者Δt并不会是一个无穷小的值,往往是宏观上的一个时间段及对应的发射的能量。这里就类比平均速度和瞬时速度了,用后者计算的是宏观上一个时间段,比如2s对应的平均flux,而后者则是非常微小的一瞬间对应的flux,所以就是一个瞬间的flux。
上边说的情况是把一个轴进行微分,每一份也就是dx。而如果换成两个维度的微分呢?也就是对于面积的微分。
这里就类似的思路了,对于上边整个曲面柱体的体积怎么求?
其实就是我们把底面分成一个个的小矩形,把x轴分成很小的一份dx,y轴分成很小的一份dy,这样就可以组成一个小矩形了。然后每个底面小矩形,有一个对应的高度,这个高度是根据曲面来的,所以这就构成一个立方体。而我们这里就拿这些无数的立方体体积之和来近似这个柱体的体积,只要立方体分的足够小,你就能够无限接近于整个柱体的体积。
总之理解和之前类似,应该可以类比过来理解这一点。 这也就是这个irradiance的公式为什么这么写的,她下面是无穷小的一个小矩形面积,下面决定上边,上边就是这个小矩形对应的flux。
然后还剩下最后两个和
,这俩分母都是dw,这里刚刚我们说某一个特定方向上,其实并不够精确,所以这里详细解释一下这个w是什么。
说这个w立体角之前,先补充一下坐标系的知识。
首先先说坐标系中一个方向如何表示,或者说空间中一个点如何表示。先说二维的:
对于点:直角坐标系下(x, y)就表示一个点了,不多说了。而方向的话,其实我们也是用一个点(x, y)表示,如果表示方向这个就意味着从(0, 0)点指向(x, y)的方向。这都很简单不多说了。
这里想要引入的是另外一种表达方式:极坐标系。
在上边图中,我们把p点按照刚刚的说法用(x, y)来表示,而极坐标是如何表示点p的?他是利用一个角度配合一个长度来表示的。
我们假设一条射线,原点在o点,方向朝着x轴,如果我们要表示一个方向,其实指定一个角度即可,这个角度就是该射线逆时针旋转的角度。那这里要表示p点所在的方向,那就是θ了。
有了方向,我们只需要指明沿着这个方向走多少距离就可以确定一个点了,这里就是r。所以说用θ和r是可以表示点p的。而这里它对于方向的表示其实是更简洁的,直接一个角度就可以了。一个变量搞定。
二维了解之后,三维就简单了。三维的空间直角坐标系不论美术同学还是程序同学都很熟悉,表示点,那就(x,y,z),表示方向那还是(x,y,z),意味着从(0,0,0)指向(x,y,z)的一个方向。
而极坐标系的三维情况,成了球坐标系:
这里对于点p的表示,还是一个方向+一个距离,和二维不一样的是他的方向需要两个角度来表示,θ和φ。
对于θ,表示的是该方向和z轴正方向之间的夹角,确定了θ之后,这个方向还是有着无限多的可能,因为它可以和z轴夹角不变然后绕着z轴旋转,这个旋转的轨迹会经过上边p点所在的黑色的圆。因此我们还需要确定绕着z轴旋转多少角度。也就是φ
其实φ和刚刚二维下的θ是一个意思,表示的是x轴射线逆时针方向转的角度。其实也就是绕着z轴旋转的角度。
这样有了两个角度定义的方向之后,就可以加上一个距离r,来确定一个点了。同时关于方向,也只需要θ和φ两个变量就可以确定一个方向。
关于坐标系的东西,理解这些就差不多了,这里关于极坐标系和球坐标系补充两个东西:单位圆和单位球。
2D的极坐标系下,如果取r=1来绕着原点画一个圆,这样在圆上的点有一点性质:r=1,也就是说这上边的点我们只需要指定角度就可以确定他们的坐标了。
3D也是类似的,就是围绕着原点画一个球,球的半径为1:
这样球上的点只需要一个方向就可以确定他们的位置。
games101先说角是什么,角度的在弧度上的定义,他是
,也就是弧长除以半径。把定义变一下形:
这个下面会用到。
再来看关于立体角的定义:
games101他是定义在一个球上的,
,他就是空间中的一个角度,没啥可说的。
而我们用的时候,经常是以dw的形式出现。如下:
https://zhuanlan.zhihu.com/p/58545259而且我们研究的立体角往往是在单位球上定义的,所以这里的r直接等于1。也就有了下面:
这里的dA简单说一下:
这里就是对于面积微分,只不过是球上的一个面积,微分到dA,然后这里在球上的时候我们是对θ和φ进行微分。微分后确定一个小的宽和高。
对于面积依旧可以看作一个小的矩形,那么他的面积dA就是两个边相乘了。先来看竖着的边注意这个边是个什么东西?是一个弧长,弧长按照上边的定义等于角度乘以半径,而角度就是dθ了。
再看横着的,他也是弧长了,但是这里有些不一样的地方。他是弧长,但是我们并不知道它对应的角是多少:下图中的红色线就对应上边小矩形的下方的横边。
因此我们怎么做呢?就把这个弧往下垂直对应到xy平面上,也就得到一个和他一样的弧长,这个弧长也就是上图中的绿色的,这个弧长对应的圆心角我们就知道了,就是dφ。但是注意这里的半径已经不是1了,而是rsinθ。
这里有一个小的点说一下:
注意上图中我画的俩红线,其实他俩都是rsinθ,因为我们的dθ是无限小的,也就是矩形的上下两个边就无限接近,所以他们到z轴的距离是相等的。
而蓝色的线和红色下面那条是相等的,因为他是垂直投影下去的。所以他们仨都一样,都是rsinθ。那么我们说的小面积的宽度也就有了:1·sinθ·dΦ。算出来dA就是如上边公式写的了。
我们上边说到的dw中的w就代表着这个立体角,因为dw是对应了一个非常非常小的面积,所以整体来看这个立体角基本上就代表着一个方向。所以有些情况就直接把他当作方向,比如后面你会看到我们在最后的PBR结论的等式中,我们式子需要的参数是入射光的立体角,但是我们实际传递的参数就是 ,同时观察方向
。
在上边的微积分部分关于这俩没解释和
,现在来看就应该很简单了。就是针对一个无穷小的立体角,它对应的flux为
,那么用这个flux来除以它对应的立体角,就是:单位立体角下的flux了,也就是单位立体角下单位时间内接受/发出的能量。对于L也是一样的,就表示单位立体角下的irradiance。那就是单位立体角下单位面积单位时间内接受/发射的能量。
理解完了这个之后我们对于刚刚所有的概念定义就说明白了。
说完了立体角的微分,再来看关于立体角的积分:
先来看这个式子,我们的dw什么也没有乘就直接积分,而这里需要说的是积分范围,这个积分范围是
表示半球,这个后面你就会知道为啥在半球积分【由于这个半球已经表达出了积分的区域了,所以这里并不需要
上部分写什么了】。
所以这里意思就是:对于半球上的每一个微小的dw进行累加。这里网上大多数都是公式来推导的,这里我们还是从符号的本质来看,感性的去理解它,我们研究的立体角是基于单位球的,也就是半径为1,那么w在数值上是等于面积A的。
而对于整个立体角在半球上积分,你就想象无数多的立体角,那么这不就是:无数个dA在半球的球面上积分吗。而他俩恰好在数值上是相等的,所以最终的结果就是:半球的表面积,高中学过公式: ,所以这里就取一半,然后r=1,即积分的结果是:
。
这种trick,还有,因为我们待会要说一个投影的东西,会导致我们的式子中经常带有cosθ,因此下面的积分我们也会常常遇到:
这里还是照顾没学过高数的同学,延续上边的思路,dw他是和dA在数值上相等,这里也就相当于dA乘了一个cosθ然后再进行积分。
乘以cosθ就相当于投影到底面的圆上,所以最终的整个半球面上的每一个小面积dA都会投影到底面的圆上,整个半球面正好对应整个圆,那么这个圆的面积积分,巧了又学过: 所以这里r等于1,即最终结果
。
这里你如果对于上边说的投影那句不知道怎么来的,下面解释,看完投影是怎么搞得再来看这个:
这是上边的AB直线投影到ab直线方向上。长度关系ab = AB cosθ。而我们通常遇到的是面积的投影:
上边的θ就表示原面积所在面和投影面积所在面之间的夹角的余弦。灰色是投影面。两个面积之间得关系同样也是一个cosθ,这个面积为啥也是cosθ,这里你就可以用你学过得微分思想来理解,分割成无限多得长条矩形,然后每一个矩形去投影,那么矩形投影:
只是对长的两个边进行投影,另外微分的那俩极短的边不变,也就是矩形面积投影是:原面积*cosθ = 投影面积 的关系。那么我们一个是这样,无限多个也是这样。
这里没什么难度,注意不要把角找错就好了。原面积所在面和投影面积所在面之间的夹角是θ。
关于面积的投影,主要是在计算irradiance的时候,我们说单位面积下接收到或者发出的光照,这个面积必须是和光线垂直的。那么如果是倾斜的角度,就得如上图进行一个投影,投影到和光线垂直的方向上,投影后的面积才是有效的面积。
关于这一点的原因,就是一个叫做兰伯特余弦定理的东西:
也就是对于相同的面积,以不同的角度去接收相同的光线时,接收到光的能量是不同的。具体就如上,就看接收到几根光线就可以看出这一点差距。
补充完了上边的这些数学,回到之前说的,我们需要探讨这些能量和物体如何作用,作用后射出去的能量是多少。
我在学习的时候发现了一个点,我有时候看不懂公式是因为,公式中的变量太多太多,总是摸不清什么代表什么,所以一个式子稍微有那么几个自己不是很明确的量,整个式子就看不太懂了,有时候总觉着某个字符懂了,但是实际没有真的懂。所以在看渲染方程之前,先把这些符号,概念再梳理一下。
所以上完了数学课之后,来点英语课,背单词!并且深入理解他们的含义。
表示输入,一般作为下标。
表示观察方向。
表示立体角,
就表示入射光线的立体角,
表示指向观察点方向的立体角。
【这里声明一下,由于我们是求特定方向上看到的/接受到能量是多少,我们并不关心实际作用后其他出射光的出射方向和出射的能量(因为一个入射可以有多个出射方向的,比如漫反射)。关心的永远是入射,然后入射后朝着观察者出射的那些光能。所以说下面如果说到出射方向,永远指的是朝着我们观察者出射的那个方向,也就是观察方向的反方向】
表示法线。
表示着色点,求该点射出的能量。
【这里强调一点,因为整个PBR的研究中,除了特别提及基本上不会用到发射出/接收到的总能量Q,这样一个概念,所以说,很多的时候提到能量,就默认是单位时间的发出或者接受的能量了,因为研究的能量都是基于单位时间来说的。所以有时候注意这个约定俗成省去的单位时间限制。】
代表radiance,单位面积,单位时间,单位立体角的能量,加上括号里的参数就是:在点p单位面积下w方向单位时间内出射或者入射的能量。简单粗暴理解就是w方向这条光线的能量。
表示
方向的入射光的radiance,
表示
方向的出射光的radiance,
表示p点处朝着
方向的自发光的radiance。
【其实有时候对于这个 这种概念有些不好理解,说的什么p点单位面积下wi方向单位时间出/入射的能量,你可能会疑问,这一个点怎么有单位面积这么一说。
其实这个点并非是点,而是一小块面积,一个点也没办法接收光照啊,我们只是简化成一个点然后来计算光照而已,你就认为是很小的一小块面积。然后它单位面积某个方向接受的能量,其实就是它某个方向接受的能量除以他的面积。这么理解会好一些。】
这个表示在p点单位面积接收到的总能量,irradiance。还是类似的,就表示p点接收到的总能量去除以他的面积。
由于这个irradiance和radiance两个概念,非常重要,所以这里加深理解一下他俩的关系:
由于出射入射都是一样的,所以这里就拿入射光来说明上边的式子。
上边的E(p)其实就是该点单位面积接收到的总能量,那么乘以dA就表示上边的小圆圈面积接收到的总能量,那么这个小圈可能从整个半球的所有方向都接收到能量啊,所以这个总能量,应该等于各个方向上接收到的能量的总和。而这个过程抽象化成数学就是上边的式子。
主要看右边,Li表示某一个wi方向上单位立体角单位面积输入的总能量,他去乘以面积就是wi方向上单位立体角输入的能量,另外讲投影时讲过了,这里的面积需要做一个投影,也就是上边的cos 项,其中的
表示入射方向和法线夹角。最后乘以dwi立体角,就表示这个wi方向上输入的能量,也就是一个方向输入的能量,那么整个半球所有的方向上,就是对于整个半球进行积分,也就是最前面的
了。
这里稍微说一个数学上的知识,就是积分符号后面的东西,如果它不随着我们积分微元的变化而变化,那么这一项就可以拿到积分符号最前面,这里也就是dwi,随着dwi变化,也就是随着入射光的方向变化,对于上边dA是不会变化的,其他的都会变,所以dA可以拿到最前面去,而左边也有一个dA就可以被约分了。【如果他被包在和dwi内部是不能约分的】也就有了下面:
这个式子还有一种写法:
这个理解的话就是:E表示单位面积所有方向上接受/发射的能量,而对他的微分就是某一个方向了,或者你把右边的dw除过来,下面决定上边,也是对于一个立体角进行微分,这俩是一个意思。而右边的Li其实就是表示一个方向入射的能量,同时再考虑一下投影就是左边了。
【这里对微分的概念再拔高一层,主要解释一种: 这样的符号】
首先我们知道 就表示单位时间的能量。而我们对他进行一个面积上的微分:
得到的是单位面积上接受/发出的能量。然后在此基础上再对立体角进行微分,
,也就得到了单位面积单位立体角接受/发出的能量。
对于上边的这个 我们可以简化写成:
写法。就表示这个
对A和w各做一次微分,一共微分两次。
我们还是从刚刚的问题出发,问题是怎么求出来出射的能量。首先入射的我们知道了是Li,然后他会和平面作用,然后作用的结果就是Lo了呗。关于和平面作用,其实也就是不变要么打个折,所以也就是乘以一个系数,会根据平面输入和观察方向等等的信息来算出一个系数。注意说的是观察方向Wo一直表示的也都是观察方向。
所以应该是:
这就表示输入的能量Li去乘以一个
【即
】表示垂直射到p点的能量,然后乘以
表示和平面作用时打的折扣,然后打完折之后就射出了,就是出射的能量。【注意这里的打折会根据出射方向(即朝着观察者的方向)来打折】
但是上边欠考虑了一个点:就是我们的输入可以来自多个方向的光啊,也就是wi可以不只是一个啊,那就需要我们把所有的方向都进行一个累加了。而所有的方向(无穷多个)累加,这就涉及到了积分,把每一个无穷小的立体角方向进行计算然后积分起来。
这里还差了一点,就是关于自发光的问题,补上之后,就得到了大名鼎鼎的渲染方程了:
其实你会发现整个公式就很简单,就是入射,作用,朝着观察者出射是多少,入射可能有多个那就累加积分,可能自发光再朝着观察者发的光加进去。这就完了。
而这复杂的公式,其实就是把这个过程抽象化了,抽象化表达出来了。我们只需要做到:理解他背后的过程,这个往往都是很形象化的东西,然后明白符号之间的对应,就能看懂上边的式子了。
什么是BRDF? 就表示BRDF。 就是用来表示物体是如何与入射光作用,数值上就表示:朝着观察者方向射出的能量去比上该点各个方向入射的总能量。也就是刚才说的对入射的总能量打几折。
其实通过上边的渲染方程,你应该能对这个量有一个初步的判断,你觉着我上边这句话说的对不对,思考思考。
其实我这么说并不严格,宏观上可以这么理解,但是实际上是错的。为什么呢?因为这个fr是一个函数,会随着wi的变化而变化的函数。当我们在上边的渲染方程中积分的时候,是对于dwi进行积分,也就是对每一个入射方向积分,而这些个入射方向之间是不同的。他们有着不同的fr值。
所以我上边说的朝着观察者射出的能量去除以各个方向入射的总能量,我这里把他们的fr说成了相等,只有他们所有人的fr都相等的时候,可以先累加求和,然后再打折,也就是上边表述的,而实际是每一个都有着不同的折扣最后折扣完累加起来。
这就好比买东西,假如你买十件衣服,这个打折就类似brdf,每件衣服如果有着相同的折扣,你就可以先计算原价一共多少然后一起打折算出多少钱。而如果折扣不同,那就需要每一件打折算出多少钱,然后最后所有衣服累加起来。而实际每一件衣服打折并不相同。
那么正确的定义就是刚刚公式写的,第一次涉及到BRDF的公式,但是这个公式后面我们说它少考虑了积分: 由于这个式子少考虑了一个积分,左边是输出的能量,其实他表示的是对应于一个入射所输出的能量,对于最终朝着观察者输出的总能量L(先暂时写作L)来说,Lo是L的一个微分,怎么理解?因为最终的总能量L是表示所有半球上每一个入射方向对应的Lo累加起来的结果。也就是对于每一个Lo积分的结果,反过来每一个Lo是L的一个微分。
那么我们输出的总能量L,如果还是写成Lo,那么他的微分就要写成 了。所以上边的公式正确写法应该是:
我在上边写错,一方面是因为写错的样式更容易理解,同时也不想在那块详细引入BRDF。所以现在把错误纠正出来,并且把BRDF详细理解一下。
回到BRDF的定义,把上边正确的式子搞一下除法:
因此对于实际的BRDF定义就如上了。他的意思就是:在某一个立体角方向入射时,单位面积内光线出射的能量比上单位面积内入射的能量。对于分母部分,其实是关于E的一个微分,E表示单位面积上接受的所有能量,对他微分到每一个入射方向也就是这里的分母部分。
即有了下面的形式:
对于BRDF这里还只是说了他的定义,关于它具体的函数实现我们还没有说,其实你八成已经实现过了。
因为他的定义就是给定每一个方向的入射能量,求出特定方向出射的能量。我们刚刚玩光照时写的blinn-phong就是做的这件事情。blinn-phong这东西就是一个BRDF。
所以说BRDF就是一个函数,他有着各种各样的实现,blinn-phong是其中一种,但是这个并不是基于物理的,是经验性的一种BRDF。
而我们说的PBR就是去实现一个基于物理的BRDF。
当然,PBR的定义这里还是要声明一下:
寒霜引擎PBR分享PBR表示基于物理的渲染,主要是:Material材质基于物理,Camera基于物理,Light基于物理。
而这里的材质就是决定了光是如何在物体表面如何作用的,也就是我们说的BRDF,即狭义上的PBR就是指的对于材质/BRDF的基于物理实现。
最后给大家一个作业,把渲染方程中所有的字母捋清楚,能够做到半夜给你拽起来问你,你能对答如流,理解并且记住这些基本量是你看懂数学公式的基础。所以一定要做,否则你再看PBR实现的时候会有些吃力,公式看着看着就不知道看的是啥了,就不知道哪是哪了。
ok,这一篇,把PBR给讲明白是啥就行了,下一篇再见~~
【注意,我讲的时候尽量通俗的讲,并不意味着我只讲简单的部分,所以下一篇一开始就直接推导甩你脸上,所以上边的数学所有内容,请大家务必理解,公式中的字母都需要知道是什么意思。】
Next:
图形渲染(17):你绝B看不懂的PBR(2)——金丹·BRDF - 知乎 (zhihu.com)
Reference:
Microfacet Models (pbr-book.org)
Torrance–Sparrow BRDF Model公式推导_狂烂球的博客-CSDN博客
Cook-Torrance BRDF - YouTube
深入浅出基于物理的渲染一 - 知乎 (zhihu.com)
Microfacet BRDF: Theory and Implementation of Basic PBR Materials [Shaders Monthly #9] - YouTube
Disney Principled BRDF实现笔记 - 知乎 (zhihu.com)
如何看懂这些"该死的"图形学公式 - 知乎 (zhihu.com)
2022/12/11