光源
一般的,一个场景中存在任意数量的点光及方向光(平行光)和单个环境光。
点光
如灯泡,点光具有位置和强度(光的亮度),假设从一个点向每个方向均匀的发射光,定义光向量(方向)\(L=Q - P\),其中\(Q\)为固定的光源发射位置,\(P\)为场景中任意点的位置。
方向光
如日光,太阳过于遥远,以至于到达我们身边的光线几乎都是平行的,若按照点光源处理,则会带来数值精度误差的问题,假设方向光没有位置,只有方向和强度。
环境光
光照射到一个物体后一部分被吸收,一部分被散射,这意味着光不仅可以来自光源,也可以来自场中物体的散射,如果把每一个物体当作光源,这将对于实时计算产生相当大的性能开销,类似的情况一般会使用全局光照技术渲染,所以假设环境光为场景中的每一个点贡献一些光,环境光只有强度,任意数量的环境光可以简单的组合成一个环境光。
传统光照模型
漫反射
假设当光照射到粗糙物体表面时会被均匀的散射到各个方向,这个过程称之为漫反射。
物体表面单位面积内所能接收到的光的能量与光线和物体表面之间的角度存在关系,如图,相同强度的两束光,分别以不同的角度照射到物体表面,显然右侧光线的能量分布在了更大的区域上面,也就是说右侧单位面积内所能接收到的能量比左侧更小,同样的所能反射的光线的量也更小。
做一个几何类比,用光线的“宽度”表示光的强度,当方向为L且强度为I的光线照射到法线为\(N\)的表面时,它的能量分布在了大小为\(A\)的表面上,若\(L\)与\(N\)方向相同,即光线垂直于表面时,此时\(I=A\),意味着单位面积反射的能量与入射的能量相同,即\(\frac{I}{A}=1\),当\(L\)与\(N\)的夹角接近\(90°\)时,\(A\)趋于\(∞\),因此单位面积内能量趋于0,即\(\lim_{A\to \infty}\frac{I}{A}=0\),\(\frac{I}{A}\)代表了反射光线的强度。
下图中“宽度”为\(I\)的光线以角度\(β\)照射到物体表面法线为\(N\)的点\(P\)处分布在了面积\(A\)上,从图中可得出\(\angle QRP=\alpha\),进而得到\(\cos\alpha=\frac{I}{A}\),由点积的性质:\(\cos\alpha=\frac{N\cdot L}{\lVert N\rVert\lVert L\rVert}\)可得\(\frac{I}{A}=\frac{N\cdot L}{\lVert N\rVert\lVert L\rVert}\),由此建立了某点处反射光线的强度与法线向量和光向量的关系。
漫反射方程:
\(I_P=I_A+\sum_{i=1}^nI_i\frac{N\cdot L_i}{\lVert N\rVert\lVert L_i\rVert}\)
- \(I_P\) 场景中点\(P\)所接受到的全部光线
- \(I_A\) 环境光
- \(I_i\) 点光或方向光的强度
- \(N\) \(P\)点的法线
- \(L_i\) 光向量(方向光是已知的,点光源则需要为每个点单独计算)
镜面反射
高光反射补充了漫反射,当一束光照\(L\)射到一面“完美抛光”的镜子上时,光线会按照同一个方向\(R\)反射,图中\(L\)的方向仅为方便计算。
但并非所有的表面都是“完美抛光”的,一部分的光线沿着\(R\)方向被反射,一部分的光线沿着接近\(R\)的方向被反射。
下图中,\(L_N\)是\(L\)的投影,\(N\)为单位法向量,其中\(L_P=L-L_N\),根据向量投影的性质,可知\(L_N=N(N\cdot L)\),R是反射方向,由图可见\(R=L_N-L_P\),替换\(L_N\)与\(L_P\)可得\(R=N(N\cdot L)-L+N(N\cdot L)\),化简得\(R=2N(N\cdot L)-L\),此时得到了反射方向向量。
高光反射的强度与反射方向\(R\)和视角方向\(V\)相关,当\(α=0°\)时,光线会在\(V\)方向和其附近反射,此时看到的高光强度最高,当\(α=90°\)时,没有光被反射到\(V\)方向,与漫反射类似,可用\(R\)与\(V\)的点积来确定高光的强度:
\(I_S=I_L\frac{R\cdot V}{\lVert R\rVert\lVert V \rVert}\)
- \(I_S\) 高光强度
- \(I_L\) 入射光强度
- \(R\) 反射方向
- \(V\) 视角方向
但每种物体的“光泽度”并非一致,由上述可知\(\frac{R\cdot V}{\lVert R\rVert\lVert V \rVert}=\cos\alpha\),此时便可利用\(cos\)函数的特性,如图\(\cos(\alpha)^s\)函数当\(s\)处于不同值的时候,呈现出不同的高光强度变化曲线,此时高光强度可表示为:
\(I_S=I_L\left(\frac{R\cdot V}{\lVert R\rVert\lVert V \rVert}\right)^s\)
\(s\)表示物体表面的光泽度,但这里只是调整s值让物体表面的高光反射看起来正确,并不符合现有的物理规律。
完整的光照模型
\(I_P=I_A+\sum_{i=1}^nI_i\cdot\left[\frac{N\cdot L_i}{\lVert N\rVert\lVert L_i\rVert}+\left(\frac{R_i\cdot V}{\lVert R_i\rVert\lVert V\rVert}\right)^s\right]\)
- \(I_P\) \(P\)点处的总光照度
- \(I_A\) 环境光强度
- \(I_i\) 光源\(i\)的强度
- \(N\) \(P\)点处法线
- \(L_i\) \(P\)点到光源\(i\)的光向量
- \(R_i\) 光源\(i\)在\(P\)点处的反射向量
- \(V\) 从\(P\)点到相机的视线向量
实际应用中的传统光照模型
Lambert 光照模型
\(C_D=I\cdot C_L\cdot M_D\cdot\max(0,\hat N\cdot \hat L)\)
- \(C_D\) 漫反射(Diffuse)最终颜色
- \(I\) 光源强度
- \(C_L\) 光源(Light)颜色
- \(M_D\) 材质(Material)的漫反射颜色
- \(N\) 表面法线
- \(L\) 光向量
Half Lambert 光照模型
\(C_D=I\cdot C_L\cdot M_D(0.5\cdot\hat N\cdot \hat L+0.5)\)
相较于Lambert 光照模型,将\(\hat N\cdot \hat L\)的结果从\([-1,1]\)的区间映射到了\([0,1]\)的区间,意味着模型的背面也将有不同的明暗变化。
Phong 光照模型
\(C_S=I\cdot C_L\cdot M_S\cdot\max(0,\hat R\cdot \hat V)^s\)
- \(C_S\) 高光反射(Specular)最终颜色
- \(I\) 光源强度
- \(C_L\) 光源(Light)颜色
- \(M_S\) 材质(Material)的高光反射颜色
- \(R=2\hat N(\hat N\cdot L)-L\) 反射方向
- \(V\) 视角方向
Blinn-Phong 光照模型
\(C_S=I\cdot C_L\cdot M_S\cdot\max(0,\hat N\cdot \hat H)^s\)
相较于Phone 光照模型,避免计算反射方向\(R\),而是计算半程向量(Bisector)\(H\),将视向量\(V\)和光向量\(L\)相加然后归一化,其中\(H=\frac{V+L}{\lVert V+L\rVert}\).
Blinn-Phong 光照模型相较于Phong 光照模型的高光反射部分看起来更大、更亮一些。
个人修改的Half Lambert 光照模型
\(C_D=I_F\cdot C_{LF}\cdot M_D\cdot H +I_B\cdot C_{LB}\cdot M_D\cdot(1-H)\)
- \(I_F\) 物体正面光源强度
- \(C_{LF}\) 物体正面光源(Light)颜色
- \(I_B\) 物体背面光源强度
- \(C_{LB}\) 物体背面光源(Light)颜色
- \(H=0.5\cdot\hat N\cdot \hat L+0.5\)
相较于Half Lambert 光照模型,加入背面光照强度的控制,由于在某些风格化的渲染中,背部表现过暗,故通过\(1-H\)反向控制背面亮度。
参考
《计算机图形学入门:3D渲染指南》
《Unity Shader入门精要》