【图形系统03】光照模型
[!tip] 约定
约定
L 光照方向
N 法线方向
V 视角/相机观察方向
T 切线方向
H 半角向量
这些向量为世界空间下的向量且是单位向量
着色 shading
[!NOTE] RTR4 中关于术语 “着色”(Shading),“着色器”(Shader)及相关的词汇的解释
遵循公认的计算机图形学用法,在本书中,术语 “着色”(Shading),“着色器”(Shader)及相关的词汇用于指两个不同但相关的概念:
着色(Shading):是计算机生成的视觉外观(例如,“着色模型 Shading Model”,“ 着色方程 Shading Equation”,“卡通着色 Toon Shading”)
着色器(Shader):是渲染系统的可编程组件(例如 “顶点着色器 Vertex Shader”,“着色语言 Shading Language”)。
定义
shading 指的是根据材质属性(如漫反射属性等)、光源信息(如光源方向、辐照度等),使用一个等式去计算沿某个观察方向的出射度的过程。笼统地说是将材质应用到对象的过程
这个等式称为光照模型(Lighting Mode)
着色方式 shading mode
根据光照情况在图中引入明暗不同的
在渲染三角形面内的具体像素时,按法线、颜色的来源途径,可以分为三种方式:
已知三角形内每个顶点的法线、坐标
- Flat shading
先平均各顶点的法向量,在计算每个像素的颜色时,共用这个平均法向量。这种方法在渲染圆滑物体时很不好用。 - Gouraud shading
先计算各顶点的颜色,三角形内的像素颜色由插值各顶点得出。 - Phong shading
在绘制每个像素时,先插值计算出当前像素的法向量,用这个法向量计算颜色。
Gouraud 与 Phong 着色有何不同?
Gouraud着色(Gouraud shading):在顶点着色器中逐顶点计算光照
在每个顶点上计算光照,然后再渲染图元内部进行线性插值。
- 顶点数目小于像素数目,因此计算量小于 phong 着色
- 但是由于以来线性插值获得像素光照,当光照模型中有非线性的计算(例如计算高光反射)时,就会破坏原计算的非线性关系,我们会发现高光部分明显不平滑。
- 由于在渲染图元内部对顶点颜色进行插值,导致渲染图元内部的颜色总是暗于顶点颜色,会产生明显的棱角现象
Phong 着色(Phong shading):片元着色器中逐像素计算光照:
又称法线矢量插值着色,以每个像素为基础得到法线(对顶点法线插值得到或从法线纹理中采样得到)
- @ 注意:着色方式不是光照模型,不要将 phong 着色和 phong、blinnphong 光照模型混为一谈。
兰伯特余弦定律
我们可以将光看作是光子的集合,在空间中按特定的方向传播。每个光子都载有 (光)能量。
光源每秒发出的 (光)能量称为辐射通量 (radiant flux)。
在光学里,我们使用辐照度 (irradiance) 来量化光。物体接收的单位面积上的辐射通量称为辐照度, 因为我们将用它来确定表面某区域所接收到的光量 (即眼睛感受到的明亮度)。
一般来讲,我们可以认为辐照度是照射到表面某区域的光量,或者是通过空间中某假想区域的光量。
光线垂直照射到表面 (即光向量 $L$ 与法向量 $n$ 相等时)的强度要大于以某个角度照射到表面的强度。试想有一小束辐射通量为 $P$ 且横截面面积为 $A$ 的光束。如果将此光束正向垂直打向表面(见图 8.10a ), 则光束照射到表面上的面积为 $A_1$,而 $A_1$ 内的辐照度为 $E_1 = P/A_1$。
现假设转动光源,使光束以某个入射角度照射到表面上 (如图 8.10b ), 则光束将覆于表面上的更大面积 $A_2$。此时, 该面积的辐照度为 $E_2=P/A_2$ 根据三角学可知,$A_1$ 及 $A_2$ 的关系为:
$$
\cos\theta=\frac{A_1}{A_2}\Rightarrow\frac{1}{A_2}=\frac{\cos\theta}{A_1}
$$
所以,
$$
E_2=\frac{P}{A_2}=\frac{P}{A_1}\cos\theta=E_1\cos\theta=E_1\left(\boldsymbol{n\cdot L}\right)
$$
换句话说, 面积 $A_2$ 内的辐照度就相当于将受垂直方向光照的面积 $A_1$ 内的辐照度按比例 $n·L =\cos \theta$ 进行缩放。这就是传说中的兰伯特余弦定律 ( Lambert’s Cosine Law)。考虑到光线照射到表面另一侧的情况(此时,点积的结果为负值),我们用 $max$ 函数来钳制”“缩放因子”的取值范围: $f (\theta) = max (cos\theta,0)= max (L\cdot n, 0)$
兰伯特余弦定律物理意义:表面辐照度与入射光和表面法线之间的夹角余弦成正比。
标准光照模型
早期的游戏引擎中往往只使用一个光照模型,这个模型被称为标准光照模型。实际上,在 BRDF 理论被提出之前,标准光照模型就已经被广泛使用了。
在 1975 年,著名学者裴祥风 (Bui Tuong Phong)提出了标准光照模型背后的基本理念。标准光照模型只关心直接光照 (direct light), 也就是那些直接从光源发射出来照射到物体表面后, 经过物体表面的一次反射直接进入摄像机的光线。
它的基本方法是,把进入到摄像机内的光线分为 4 个部分,每个部分使用一种方法来计算它的贡献度。
- **自发光(emissive)**,本书使用 $C_{emissive}$ 来表示。这个部分用于描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。需要注意的是,如果没有使用全局光照 (global illumination)技术,这些自发光的表面并不会真的照亮周围的物体,而是它本身看起来更亮了而已。
- **高光反射 (specular)**,本书使用 $C_{specular}$ 来表示。这个部分用千描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。
- **漫反射 (diffuse)**,本书使用 $C_{diffuse}$ 来表示。这个部分用于描述,当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。
- **环境光 (ambient)**,本书使用 $C_{ambient}$ 来表示。它用于描述其他所有的间接光照。
[[03 光照向量#光的散射(scattering)]]
为了区分反射和折射这两种不同的散射方向,我们在光照模型中使用了不同的部分来计算它们:
- 高光反射部分表示物体表面是如何反射光线的,
- 漫反射部分则表示有多少光线会被折射、吸收和散射出表面。
根据入射光线的数量和方向,我们可以计算出射光线的数量和反向,我们通常使用出射度(exitance) 来描述它。辐射度和出射度都是辐射度量学里的名词。
在本章中,我们假设漫反射部分是没有方向性的,也就是说,光线在所有方向上是平均分布的,同时,我们也只考虑某一个特性方向上的高光反射。
环境光 Ambient
虽然标准光照模型的重点在于描述直接光照,但在真实的世界中,物体也可以被间接光照 (indirect light)所照亮。间接光照指的是,光线通常会在多个物体之间反射,最后进入摄像机。
在标准光照模型中,我们使用了一种被称为环境光的部分来近似模拟间接光照。环境光的计算非常简单,它通常是一个全局变量,即场景中的所有物体都使用这个环境光。
$$
C_{ambient}=g_{ambient}
$$
自发光 Emissive
光线也可以直接由光源发射进入摄像机,而不需要经过任何物体的反射。标准光照模型使用自发光来计算这个部分的贡献度。它的计算也很简单,就是直接使用了该材质的自发光颜色:
$$
\boldsymbol{c}{emissive}=\boldsymbol{m}{emissive}
$$
漫反射 Diffuse
我们认为光在 shading point 向各个方向均匀的散射,从各个观察方向看颜色都是相同的。
![[Pasted image 20230510111300.png#pic_center|270]]
![[Pasted image 20230510111136.png#pic_center|293]]
Lambert
$$
c_{diffuse}=c_{light}\cdot m_{diffuse}\max(0,n\cdot l)
$$
- $n$ 是表面法线
- $l$ 是指向光源的单位矢量
- $m_{diffuse}$ 是材质的漫反射颜色
- $c_{light}$ 是光源颜色
需要注意的是,我们需要防止法线和光源方向点乘的结果为负值,为此,我们使用取最大值的函数来将其截取到 0,这可以防止物体被从后面来的光源照亮。
HalfLambert
广义的半兰伯特光照模型的公式如下:
$$
\mathbf{c}{diffuse}=\left(\mathbf{c}{light}\cdot\mathbf{m}{diffuse}\right)\left(\alpha\left({n}\cdot{l}\right)+\beta\right)
$$
绝大多数情况下, $\alpha$ 和 $\beta$ 的值均为 0.5 , 即公式为:
$$
\mathbf{c}{diffuse}=\left(\mathbf{c}{light}\cdot\mathbf{m}{diffuse}\right)\left(0.5\left({n}\cdot{l}\right)+0.5\right)
$$
通过这样的方式,我们可以把 $n\cdot l$ 的结果范围从 $[-1 , 1 ]$ 映射到 $[0, 1]$ 范围内 , 不会出现 Lambert 的死黑颜色,也不需要用 max 来处理了。
左:Lambert 右:HalfLambert
高光反射 Specular
高光反射的强度取决于观察方向和反射方向之间的夹角
phong
首先计算反射向量 $r$:
$$r=2(l\cdot n)n-l$$
$$
\mathbf{c}{specular}=(c{light}\cdot\mathbf{m}{specular})\max(0,{\mathbf{v}}\cdot\mathbf{r})^{m{gloss}}
$$
- $m_{gloss}$ 是材质的光泽度 (gloss), 也被称为反光度 (shininess) 。它用于控制高光区域的“亮点”有多宽, $m_{gloss}$ 越大,亮点就越小。
- $\mathbf{m}_{specular}$ 是材质的高光反射颜色,它用于控制该材质对于高光反射的强度和颜色。
- $c_{light}$ 是光源颜色
同样,这里也要防止 $\mathbf{v}\cdot\mathbf{r}$ 为负数
BlinnPhong
引入半程矢量 $h$,避免计算反射方向 $r$
计算半程向量:
$$
h=\frac{v+l}{||v+l||}
$$
使用们 $n$ 和 $h$ 之间的夹角进行计算:
$$
c_{specular}=\left(\mathbf{c}{light}\cdot\mathbf{m}{specular}\right)\max\left(0,{n}\cdot{h}\right)^{m_{gloss}}
$$
两大模型对比
综上,Phong 光照模型和 BlinnPhong 光照模型主要区别在于计算高光的方式不同。
外观对比: BlinnPhong 高光更平滑
性能对比:
在硬件实现时, 如果摄像机和光源距离模型足够远,此时可以认为 $v$ 和 $l$ 都是定值, 因此 $h$ 将是一个常量。即入射方向和视线方向保持不变,半角向量可以只计算一次并重用。此外,半角向量的计算比反射方向的计算量更少。这时 BlinnPhong 模型性能优于 Phong 模型。
但是,当 $v$ 和 $l$ 不是定值时, Phong 模型计算量更少一些。
其他漫反射模型
Banded
条带
WrapLight
Wrap Light(环绕光照) 直译的话就是用光包裹住整个物体,让原来黑暗(即 $N\cdot L<=0$)的部分亮起来的意思。如果是标准 Lambert 的话,有很大一部分地方是黑的,让整个物体显得比较平,而 Wrap Light 会有一个光的过度,并且”soft“整个物体的感觉。
早期的皮肤材质就是用这样的方法来制作的
Minnaert
Minnaert 光照主要是用来模拟月球光照的,这种光照模型的渲染效果很接近 Oren-Nayar 光照模型,后者也常被称为毛绒模型或月光模型
Oren-Nayer(未学习)
这是一个针对粗糙表面的光照效果模型,它提供了一种比较简单的方法来实现粗糙表面的漫反射光照效果(漫反射还是兰伯特式的)