人们常说,夜晚的星斗是天堂里幸福的象征;你的眼睛照彻我的心灵。

# Phong 光照模型

首先,我们要考虑光照模型是在做什么:给定一个光源,物体表面的一个点,一个观测者,我们需要一个模型去计算那个点在观察者眼中的颜色。

注意,所谓的光强、看起来亮、暗本质上都是因为颜色和颜色的对比产生的结果。所以光照模型也是在计算物体表面各个点的颜色。

# 光源的刻画

Phong 光照模型认为,光源与物体表面有三种相互作用:Specular (镜面反设)、Ambient (环境光)、Diffuse (漫反射)

当然这只是对现实世界的一个建模,并没有什么办法推导出确实光与物体就是这样作用的。

然后我们认定有一个理想点光源,即它向所有方向都均匀地发出相同的光。Phong 模型用一个9×99\times 9 的矩阵去描述这个光源:

I=(LraLgaLbaLrdLgdLbdLrsLgsLbs)I=\begin{pmatrix} L_{ra}&L_{ga}&L_{ba}\\ L_{rd}&L_{gd}&L_{bd}\\ L_{rs}&L_{gs}&L_{bs} \end{pmatrix}

其中,LraL_{ra} 表示该光源的环境光 (ambient) 的红色 (red) 强度为多少。同理,对于三种作用和三种颜色,我们一共有 9 个数去刻画这个光源。

你可能很奇怪,想象中好像漫反射或者环境光和光源没什么关系,我们是否就应该用一组(R,G,B)(R,G,B) 值描述光源颜色就足够了,而环境光、漫反射应该根据环境参数决定。我认为是这样的,只不过所有的和光有关的环境因素,在这里都被整合统称为光源了。也就是说我们不用考虑白天、黄昏之类的因素,它们都在光源矩阵II 里了。

# 物体、观察者、光源的相互作用

关于物体表面上的某一个点,Phong 模型认为需要四个向量(都是单位化了的,所以需要的信息是方向)来计算它在光照下的颜色:

1

  1. l\mathbf{l} 是物体表面上的这个点指向光源的向量。

  2. n\mathbf{n} 是物体表面在这个点的法向量。

  3. v\mathbf{v} 是物体表面这个点指向观察者的向量。

  4. r\mathbf{r} 是从光源射来的光,完美反射后的出射光方向。也就是说,l,n,r\mathbf{l},\mathbf{n},\mathbf{r} 共面,且n\mathbf{n} 平分了l,r\mathbf{l},\mathbf{r} 的夹角。

然后我们来分别考虑三种作用对这个点的光照颜色的贡献。

  • 对于环境光,Phong 模型认为它不受光源位置、观测者位置的影响,即处处相等的。所以我们只需要加它加一个权重,最后加到最终光照颜色中即可:Ia=kaLaI_a=k_aL_a

  • 对于漫反射,Phong 模型认为,之所以正午我们感觉光强,黄昏感觉光弱,其实是因为光线是否垂直地照射到表面并被反射出来。即漫反射光的强度正相关于光线和物体表面的夹角。光线越是垂直地射到表面,漫反射光越强。基于此,Phong 模型刻画漫反射光为:

    Id=kd(ln)Lda+bd+cd2I_d=\frac{k_d(\mathbf{l}\cdot\mathbf{n})L_d}{a+bd+cd^2}

    其中,dd 是光源到物体表面点的距离。我们认为光强随着距离会减小,减小的速度就是除以一个二次函数。

    上式中,很显然ln\mathbf{l}\cdot\mathbf{n} 越大,说明光线越贴近法向量,即入射光越垂直于平面。上式中,kd,a,b,ck_d,a,b,c 均为参数可以用来柔化光照。

  • 对于镜面反设,Phong 模型认为,就像我们玩尺子反射光,当反射的光斑找到人眼睛时就会感到刺眼。因此这部分的光强取决于反射光方向r\mathbf{r} 和观测者方向r\mathbf{r} 的接近程度。若r\mathbf{r}v\mathbf{v} 共线,则说明反射光正好进入观测者眼睛,此时镜面反射光强最大。类似漫反射,Phong 模型刻画为:

    Is=ksmax((rv)α,0)Lsa+bd+cd2I_s=\frac{k_smax((\mathbf{r}\cdot\mathbf{v})^\alpha,0)L_s}{a+bd+cd^2}

    不同的是,如果rv<0\mathbf{r}\cdot\mathbf{v}<0 时,说明反射光完全背对着观测者而去了,我们就认为这完全没有任何贡献。此外,除去参数ks,a,b,ck_s,a,b,c,还有参数α\alpha,它反映了光照的 shininess。当α\alpha 较大时,很显然只有rv\mathbf{r}\cdot\mathbf{v} 接近于 1,也就是反射光和观测者方向非常接近,才会有显著的非零值,否则 (<1) 的数高次幂后就接近于 0 了。故α\alpha 实际上起到了 “聚光” 的效果。

故最后 Phong 模型认为的光照强度公式为:

I=1a+bd+cd2(kd(ln)Ld+ksmax((rv)α,0)Ls)+kaLaI=\frac{1}{a+bd+cd^2}(k_d(\mathbf{l}\cdot\mathbf{n})L_d+k_smax((\mathbf{r}\cdot\mathbf{v})^\alpha,0)L_s)+k_aL_a

# Blinn Phong 光照模型

Blinn-Phong 模型实际上就是为了简便一点 Phong 模型的计算量。

很显然,Phong 模型中,知道了l,n\mathbf{l},\mathbf{n} 实际上是可以计算出r\mathbf{r} 的,但这个计算可能比较麻烦。注意到我们最后需要的值是r\mathbf{r}v\mathbf{v} 的夹角ϕ\phicos(ϕ)cos(\phi) 值,而n\mathbf{n} 又是l,r\mathbf{l},\mathbf{r} 的中间向量,所以我们考虑构造一个h\mathbf{h},它是l,v\mathbf{l},\mathbf{v} 的中间向量,这样r,v\mathbf{r},\mathbf{v} 的夹角,就是二倍的n,h\mathbf{n},\mathbf{h} 的夹角:

2

我们有:

h=l+vl+v2ψ=θ\mathbf{h}=\frac{\mathbf{l}+\mathbf{v}}{|\mathbf{l}+\mathbf{v}|}\\ 2\psi=\theta

因此,可以修改 Phong 模型的结果为:

I=1a+bd+cd2(kd(ln)Ld+ksmax((nh)e,0)Ls)+kaLaI=\frac{1}{a+bd+cd^2}(k_d(\mathbf{l}\cdot\mathbf{n})L_d+k_smax((\mathbf{n}\cdot\mathbf{h})^e,0)L_s)+k_aL_a

注意只改动了镜面反射 Specular 部分。而指数是我们选择cose(ψ)cosα(2ψ)cos^e(\psi)\approx cos^\alpha(2\psi) 的值,去接近原 Phong 模型中的反射光部分。

# 关于 Flat,Gouraud,Phong Shading

  1. 假设每个面都是平的,即面上所有点的法向量n\mathbf{n} 都是常数,那么若l,v\mathbf{l},\mathbf{v} 我们也假设是常量的话,显然此时同一个面会都成了一个颜色,这就是 Flat shading。它假设了光源就是平行光,而且观察者也是正投影观察。此时对于每个面我们只需要计算一次光照就行了。

    3

  2. 若一个模型表面不是连续可微的,就像现实中的模型大多都是三角面片拼接而成。此时对于每个顶点,我们就认为它的法向量就是所有与他相关联的面的法向量的平均值:

    4

    对于 Gouraud shading,我们像这样计算出每个顶点的法向量,然后计算它的光照颜色,然后对于面内部的点,它们的光照颜色就是根据顶点的颜色插值而成。很显然,Gouraud shading 中,一个面内最亮的和最暗的点,必然都是顶点,其余的点颜色因为是对顶点颜色插值而成,故都介于此之间。

  3. 而 Phong shading 就不是对顶点颜色插值,而是对顶点的法向量插值。即面内每个点的法向量都可以由顶点的法向量插值而成,再依此去计算面内点的颜色。故此时最亮的点可能是在面内了。

Edited on Views times