# 一、Blinn-Phong 模型

​ 在硬件还没有现在这么好的时候,想要完全模拟现实世界有点难,尤其是实时渲染。基于此便有了标准光模型。标准光都是经验模型,渲染出来的与现实世界有点差距,好就好在对硬件要求不高,硬件不好也能跑。在标准光模型中,人眼能看到的光分为三类,环境光,漫反射,高光反射。

# 1. 环境光

​ 在现实世界中,有个只有一个点光源的黑暗空间照向一个物体,仍然能看到物体的背面,是因为光在照射物体后又反射到周围其他物体或者墙壁,之后在不断反射,反射到了物体上。而在标准光模型中,光照射到物体后有一次反射,之后就不管光之后的反射,光线追踪太耗费性能了,一直到 2018,英伟达才在 20 系显卡上使用光线追踪。在此之前实时渲染都不会管光之后的反射。因此需要给物体一个环境光,这个环境光是其他物体反射光得到,在 threejs 中给场景添加环境光后,所有标准光模型材质都会获得这个环境光。也就是 threejs 中会认为在同一个场景中,每个物体获得环境光相同,这明显与现实世界不同不过这样能减少计算量。所以这个环境光是一个全局常量,在一个场景中的不同的物体的环境光相同。

# 2. 漫反射

​ 当一束光照射一个平面,如果这个平面足够光滑如镜子则只有反射,此时反射叫做镜面反射。如果比较粗糙,平面则会吸收一部分的光,吸收的光一部分会反射,此时的反射为漫反射。漫反射向四周反射,所以无论往那个方向看都一样,所以漫反射与观察者的角度无关,但是与光线的角度有关。如果光线的方向与法线相反也即垂直照射平面,此时平面接受的光最多,漫反射的强度也就大,如果光线与平面平行,此时平面没有接受光线也就没有漫反射。根据兰伯特定律 (Lambert’s law)

cdiffuse=(clightmdiffuse)max(0,nl)c_{diffuse}=(c_{light}*m_{diffuse})max(0,n*l)

​ m 为物体漫反射的颜色,也即物体的颜色。众所周知当一个白光照射一个物体,此时物体呈现的颜色就是未被吸收的光,除此之外的光都被吸收了。n*l 为 n 与 l 的点积。因为法线 n 与光线 l 都归一化了,模长为 1,所以此时的点积就是 cosθ。可以发现,这里的漫反射与物体的粗糙程度无关,只与光线以及入射角,物体漫反射颜色相关,这点现实世界相违背。因为理论上漫反射还与物体的粗糙程度相关,物体越粗糙,漫反射越强。只能为了减少计算量,近似模拟,这里所有的物体粗糙都一致,所以在 threejs 中,标准光模型的材质无法改粗糙度,还有金属度。

# 3. 高光反射

​ 如果一个平面比较光滑,则会产生镜面反射,如果此时视线与镜面反射的角度差不多时便会看到高光。

​ 首先要求镜面反射 r。很明显法线等于光线 l 加上镜面反射 r

n=(l+r)/(r+l)n=(l+r)/(|r+l|)

​ 因为法线归一化,模为 1,所以还需除 r+l 的模。而 r+l 的模为 2cosθ 也即 2 倍的 r 与 l 的点积。因此就可以求出 r

r=2cosθnl=2(ln)nlr=2cosθn-l=2(l*n)n-l

​ 由此可以得出高光

cspecular=(clightmspecular)max(0,vr)mglossc_{specular}=(c_{light}*m_{specular})max(0,v*r)^{m_{gloss}}

​ mspecular 为镜面反射颜色也即物体颜色,mglass 为物体光泽度,光泽度越大,高光区域越小。

​ 上面为 Phong 模型,此外 Blinn 提出了 Blinn 模型即计算视线与光线中间的向量 h,根据 h 与 n 计算高光。

h=(v+l)/v+lh = (v+l)/|v+l|

cspecular=(clightmspecular)max(0,nh)mglossc_{specular}=(c_{light}*m_{specular})max(0,n*h)^{m_{gloss}}

​ 将这三种光相加就是标准光模型下一个物体最终反射的光。

# 二、BPR(基于物理渲染)

# 1. 辐射度量学

​ 辐射物理学有很多单位,在 bpr 中需要了解的主要是,辐射率,辐照度,光强,辐射通量。

  1. 辐射能 辐射通量 流明

​ 辐射能即光具有的能量,单位为焦耳,不过在渲染中不考虑这个物理量,取而代之的是辐射通量。辐射能除于时间即为辐射通量也即功率,单位为瓦特。因为当一束光一直照射在物体上,物体上的辐射能不会增加,如果会一直增加那么这个物体必然会越来越亮,这与现实世界观察不符,原因是物体单位时间反射的光的能量是一样的也即辐射通量一致,所以一般使用辐射通量描述。由于人眼对于不同波长的光的感受不同,相同功率的灯泡发射的不同波长的光,对于人眼来说亮度感受是不同的,所以就有了流明衡量光的亮度。相同功率的灯,发射的光的波长在 550 纳米左右,大概是绿光,流明最大。另外流明与距离无关,只与辐射通量和发出光的频率有关,而辐射通量与灯泡本身有关。

  1. 辐射强度

​ 辐射强度指的是辐射通量 (功率) 与立体角的比率。在平面上弧度制下,角度为角度对应圆弧与半径的比值,单位为弧,而立体角则为立体角对应球面面积与半径平方的比值,单位为 sr (球面度)。如果要求立体角,可以将其投影到半径为 1 的球面上,在球面上的投影面积即为立体角,对于一个球来说,立体角为 4π。辐射强度也与距离无关,只与辐射通量和立体角有关。在相同的立体角下,当距离变大后,面积也会变大。如果有一个以某立体角发射光的手电筒照射墙面,墙面越远照射范围就越大,实际的辐射通量并没有发生改变。

  1. 辐照度

​ 辐照度指的是辐射通量与面积的比率,描述的是单位面积下的辐射通量。当有一个以某立体角发射光的手电筒照射墙面,墙面越远照射范围就越大,但是辐射通量却没有变化,那么单位面积下的辐照度就变小。如果是一个平行光照射范围不会随距离发生变化,辐照度就不变。

  1. 辐射率

​ 辐射率指的是辐射通量与面积和立体角乘积的比率。人眼真正感受到的亮度与辐射率有关。如果是一个平行光照射墙面,墙面离人越来越远的时候,辐照度没有变化,辐射率也不会发生变化。

参考资料:辐射度量学 - 维基百科,自由的百科全书 (wikipedia.org)

辐射度量学(Radiometry/Photometry)和物理光照 - 知乎 (zhihu.com)

# 2.BRDF

​ 对于光滑的平面而言,当光照射后就只有镜面反射,没有漫反射。对于不光滑的平面,如果是金属,光进入金属就会吸收,所以金属没有漫反射。如果不是金属,则会发生漫反射。

f(l,v)=dL0(v)/dE(l)f(l,v)=dL_0(v)/dE(l)

​ 上面为 brdf 函数即双向反射分布函数。指的是光线以 l 方向入射,以 v 方向观察,当然也可以反过来以 v 方向入射,以 l 方向观察所以才叫双向反射分布函数。L (v) 为表面射出的辐射率,E (l) 为表面入射的辐射度,入射包括其他表面的漫反射或者点光源和平行光源的入射光线。这个比值对于不同的材质来说是不同的。关于为啥是射出辐射率与入射辐射度的比值。brdf 为什么要定义为一个单位是 sr-1 的量? - 知乎 (zhihu.com)

​ 入射辐照率等于辐射通量除于面积和立体角,也等于辐射度除于立体角。

Li(l)=dφ/dωidAcosθi=dE(l)/dωicosθi,dE(l)=Li(l)dωicosθiL_i(l)=dφ/dω_idAcosθ_i=dE(l)/dω_icosθ_i,dE(l)=L_i(l)dω_icosθ_i

​ 由此推出反射方程

L0(v)=f(l,v)E(l)=f(l,v)Li(l)ωicosθiL_0(v)=f(l,v)E(l)=f(l,v)L_i(l)ω_icosθ_i

​ 如果有多个光源

L0(v)=k=1nf(lk,v)Lk(l)ωkcosθkL_0(v)=\sum_{k=1}^{n}f(l_{k},v)L_{k}(l)ω_kcosθ_k

​ 对某个平面入射到某一点的光线,反射到 v 方向求积分

L0(v)=Ωf(l,v)L(l)ωcosθL_0(v)=\int_Ω f(l,v)L(l)ωcosθ

参考资料:基于物理着色:BRDF - 知乎 (zhihu.com)

由浅入深学习 PBR 的原理和实现 - 0 向往 0 - 博客园 (cnblogs.com)