Phong光照模型

首先来看一下Phong光照模型的计算式:

Lo(v)=(cosθicdiff+cosmαrcspec)BLL_o(\vec{v})=(cos{\theta_i}∗c_{diff}+cos^m{\alpha_r}∗c_{spec})\otimes B_L

其中,θi\theta_i为入射光i\vec{i}和法线n\vec{n}的夹角(cosθi=incos{\theta_i}=-\vec{i}\cdot \vec{n}),αr\alpha_r为反射光r\vec{r}和视线v\vec{v}的夹角(cosαi=rvcos{\alpha_i}=-\vec{r}\cdot \vec{v}),cdiffc_{diff}cspecc_{spec}mm都是材质本身的属性(分别对应漫反射项颜色、高光项颜色以及反光度),BLB_L是入射光的颜色,注意不是辐照度(irradiance)。

补充一下反射光方向的计算式:r=i2(in)n\vec{r}=\vec{i}-2(\vec{i}\cdot \vec{n})\vec{n}

Phong光照模型与Blinn-Phong光照模型的优劣问题

Phong光照模型示意图

Phong光照模型的BRDF版本

对于Phong光照模型的BRDF版本(Normalized Phong),入射光的颜色BLB_L与辐照度ELE_L的关系为BL=ELπB_L=\frac{E_L}{\pi}。引入修正系数,计算式为(此处推导见BRDF·基于物理的着色技术学习总结):

Lo(v)=kf(ik,v)ELkcosθikL_o(\vec{v})=\sum_{k}{f(\vec{i_k},\vec{v})\otimes E_{L_k}cos\theta_{i_k}}

其中双向反射分布函数(BRDF)为:

f(i,v)=cdiffπ+(m+2)cspeccosmαr2πf(\vec{i},\vec{v})=\frac{c_{diff}}{\pi}+\frac{(m+2)c_{spec}∗cos^m{\alpha_r}}{2\pi}


Blinn-Phong光照模型

Blinn-Phong模型与Phong模型的不同之处在于高光项的夹角计算方式。看一下Blinn-Phong光照模型的计算式:

Lo(v)=(cosθicdiff+cosmβhcspec)BLL_o(\vec{v})=(cos{\theta_i}∗c_{diff}+cos^m{\beta_h}∗c_{spec})\otimes B_L

其中,θi\theta_i为入射光i\vec{i}和法线n\vec{n}的夹角(cosθi=incos{\theta_i}=-\vec{i}\cdot \vec{n}),βh\beta_h为半角向量h\vec{h}和法线n\vec{n}的夹角(cosβh=hncos{\beta_h}=\vec{h}\cdot \vec{n}),cdiffc_{diff}cspecc_{spec}mm都是材质本身的属性(分别对应漫反射项颜色、高光项颜色以及反光度),BLB_L是入射光的颜色,同样注意不是辐照度(irradiance)。

补充一下半角向量的计算式:h=i+vi+v\vec{h}=-\frac{\vec{i}+\vec{v}}{\left\|\vec{i}+\vec{v}\right\|}

Phong光照模型与Blinn-Phong光照模型的优劣问题

Blinn-Phong光照模型示意图

Blinn-Phong光照模型的BRDF版本

对于Blinn-Phong光照模型的BRDF版本(Normalized Blinn-Phong),引入修正系数。计算式为(此处只列出BRDF的计算式,推导见BRDF·基于物理的着色技术学习总结):

f(i,v)=cdiffπ+(m+2)(m+4)cspeccosmαr8(2m2+m)πf(\vec{i},\vec{v})=\frac{c_{diff}}{\pi}+\frac{(m+2)(m+4)c_{spec}∗cos^m{\alpha_r}}{8(2^{-\frac{m}{2}}+m)\pi}

或近似为

f(i,v)=cdiffπ+(m+8)cspeccosmαr8πf(\vec{i},\vec{v})=\frac{c_{diff}}{\pi}+\frac{(m+8)c_{spec}∗cos^m{\alpha_r}}{8\pi}


两种模型的效果与优劣

首先对比两种模型的效果:
Phong光照模型与Blinn-Phong光照模型的优劣问题

两种模型的效果图1

第一张效果图中,我们可以发现使用Blinn-Phong模型时高光更亮。


Phong光照模型与Blinn-Phong光照模型的优劣问题

两种模型的效果图2,此处可以发现Phong模型的一个问题


第二张效果图中,我们可以发现Phong模型在一些情况下会导致显示效果不平滑。当反射光与视线的夹角大于90度时,由于在实际渲染时余弦值总是被限制在[0,1],在这些地方上高光项没有任何贡献。当物体的反光度非常小时,高光半径就会非常大,在反射角与视线夹角为90度的区域附近就会出现很明显的断层现象。而由于半角向量与法线夹角总不大于90度,使用Blinn-Phong模型时断层现象不会发生。

Phong光照模型与Blinn-Phong光照模型的优劣问题

效果图2的断层问题的产生原因示意图


可能的误区

通常在讲Blinn-Phong模型的优势时,都会提到Blinn-Phong模型的计算比Phong更高效。在Real-Time Rendering中提到,如果入射方向和视线方向保持不变,半角向量可以只计算一次并重用。此外,半角向量的计算比反射方向的计算量更少。

但是,回顾两个向量的计算方式:

r=i2(in)n\vec{r}=\vec{i}-2(\vec{i}\cdot \vec{n})\vec{n}
h=i+vi+v\vec{h}=-\frac{\vec{i}+\vec{v}}{\left\|\vec{i}+\vec{v}\right\|}

由于入射方向和法线方向都是单位向量,求反射方向需要数次乘法和加法,求半角向量需要数次加法和一次标准化。那么数次加法和一次标准化真的比数次乘法和加法快吗?

这里我们认为快和慢取决于具体的硬件平台,因为这些操作都有可能有相应的硬件指令,以加快一些常用运算。现代GPU通常支持向量点乘指令、平方根倒数指令,甚至支持归一化指令。实际上速度差距并不大。

以上结果反映Blinn-Phong的优势主要还是高光效果更平滑。


参考资料

Real-Time Rendering (3rd Edition)
BRDF·基于物理的着色技术学习总结
https://learnopengl.com/Advanced-Lighting/Advanced-Lighting
为什么说使用 halfway vector 可以提高效率? - Milo Yip的回答 - 知乎

相关文章: