之前学习计算机图形时学到光照模型这一部分,在双线性光强插值(Gouraud明暗处理)这一部分,课本上讲解起来连个图都不带,看闫令琪老师的课程也只讲了计算,中文互联网上的资料也不全,还是看了这里 的讲解才弄懂一点,就结合这个网站的内容、闫令琪老师的课程和课本讲解写个学习笔记。
复习一下Phong光照明模型的三个公式
I d = I p K d ⋅ ( L ⋅ N ) I_d=I_pK_d·(L·N) Id=IpKd⋅(L⋅N) I s = I p K s ( R ⋅ V ) n I_s=I_pK_s(R·V)^n Is=IpKs(R⋅V)n I e = I a ⋅ K a I_e=I_a·K_a Ie=Ia⋅Ka
在Phong光照模型中,由于光照L和视点V都被视为无穷远,因此对于同一个多边形中所有点来说,因为它们的法向量也是一致的,计算出来的光强也都是一致的。如果就这么处理的话,法向量就只计算到面,每个多边形内部像素的明暗/颜色都是一致的,这就是Flat明暗处理。它的实现简单,运行速度快,我的实验也是这种实现。缺点是实现效果完全依靠物体复杂度,如果模型较为简单,显示效果就会很差,此外还有不同多边形邻接处的光强突变、马赫带效应等问题。
为了保证多边形之间的光滑过渡,优化显示效果,出现了增量式光照明模型。其基本思想是在每一个多边形的顶点处计算合适的光照明强度或其他参数,然后在各个多边形内部进行均匀插值,最后得到多边形的光滑颜色分布。它包含两种主要形式:双线性光强插值和双线性法向插值,又被分别称为Gouraud明暗处理和Phong明暗处理。两者均在顶点处计算出平均法向,但区别是前者是对光强进行插值(法向量只计算到顶点),后者是对法向量进行插值(法向量计算到像素)。前者计算量小但高光处显示效果仍不好,后者则与之相反。这篇笔记主要介绍双线性光强插值(Gouraud明暗处理)。Phong明暗处理的步骤也基本相同。
这张从闫令琪老师视频里借来的图很好地说明了三种明暗处理方法的区别。由上到下物体点数逐渐增多,左中右三列依次是Flat、Gouraud、Phong明暗处理,它们处理法向量的精度分别是面、顶点、像素。
3,4步的两个插值合起来就是所谓的双插值。下面依次进行介绍这些步骤
使用与顶点相邻的所有多边形的法向的平均值近似作为该顶点的近似法向量。假设顶点A相邻的多边形有 k k k个,法向依次为 N 1 , N 2 , … , N k N_1,N_2,…,N_k N1,N2,…,Nk,则顶点A的法向为
N a = 1 k ( N 1 + N 2 + … + N k ) N_a=\frac{1}{k}(N_1+N_2+…+N_k) Na=k1(N1+N2+…+Nk)
即相邻面法向的平均值。也可以根据面的大小使用加权平均。
使用Phong光照明模型计算顶点处的光亮度即可。Gouraud提出此方法时Phong模型还没有出现,他使用的是 I = I a K a + I p K d ( L ⋅ N a ) / ( r + l ) I=I_aK_a+I_pK_d(L·N_a)/(r+l) I=IaKa+IpKd(L⋅Na)/(r+l)
使用双线性插值,可以计算出多边形上各点和内部点的光强。就上图这个三角形进行分析。已经求出点 P 1 ( x 1 , y 1 ) , P 2 ( x 2 , y 2 ) , P 3 ( x 3 , y 3 ) P_1(x_1,y_1),P_2(x_2,y_2),P_3(x_3,y_3) P1(x1,y1),P2(x2,y2),P3(x3,y3)的光强 I 1 , I 2 , I 3 I_1,I_2,I_3 I1,I2,I3。
则边 P 1 P 2 P_1P_2 P1P2上点 P 4 ( x 4 , y 4 ) P_4(x_4,y_4) P4(x4,y4)的光强为 I 4 = y 4 − y 2 y 1 − y 2 I 1 + y 1 − y 4 y 1 − y 2 I 2 = 1 y 1 − y 2 [ ( y 4 − y 2 ) I 1 + ( y 1 − y 4 ) I 2 ] I_4=\frac{y_4-y_2}{y_1-y_2}I_1+\frac{y_1-y_4}{y_1-y_2}I_2=\frac{1}{y_1-y_2}[(y_4-y_2)I_1+(y_1-y_4)I_2] I4=y1−y2y4−y2I1+y1−y2y1−y4I2=y1−y21[(y4−y2)I1+(y1−y4)I2]
边 P 2 P 3 P_2P_3 P2P3上点 P 5 ( x 5 , y 5 ) P_5(x_5,y_5) P5(x5,y5)的光强为 I 5 = y 5 − y 2 y 3 − y 2 I 3 + y 3 − y 5 y 3 − y 2 I 2 = 1 y 3 − y 2 [ ( y 5 − y 2 ) I 3 + ( y 3 − y 5 ) I 2 ] I_5=\frac{y_5-y_2}{y_3-y_2}I_3+\frac{y_3-y_5}{y_3-y_2}I_2=\frac{1}{y_3-y_2}[(y_5-y_2)I_3+(y_3-y_5)I_2] I5=y3−y2y5−y2I3+y3−y2y3−y5I2=y3−y21[(y5−y2)I3+(y3−y5)I2]
线段 P 4 P 5 P_4P_5 P4P5上点 P ( x p , y p ) P(x_p,y_p) P(xp,yp)的光强为 I p = x p − x 4 x 5 − x 4 I 5 + x 5 − x p x 5 − x 4 I 4 = 1 x 5 − x 4 [ ( x p − x 4 ) I 5 + ( x 5 − x p ) I 4 ] I_p=\frac{x_p-x_4}{x_5-x_4}I_5+\frac{x_5-x_p}{x_5-x_4}I_4=\frac{1}{x_5-x_4}[(x_p-x_4)I_5+(x_5-x_p)I_4] Ip=x5−x4xp−x4I5+x5−x4x5−xpI4=x5−x41[(xp−x4)I5+(x5−xp)I4]
此外,我们可以结合扫描线算法,用增量算法来计算。当扫描线纵坐标由 j j j变成 j + 1 j+1 j+1时,新的 P 4 ∗ 和 P 5 ∗ P_4^*和P_5^* P4∗和P5∗的光强为 I 4 ∗ = I 4 + Δ I 4 I_4^*=I_4+ΔI_4 I4∗=I4+ΔI4 I 5 ∗ = I 5 + Δ I 5 I_5^*=I_5+ΔI_5 I5∗=I5+ΔI5其中 Δ I 4 = [ ( y 4 + 1 ) − y 2 y 1 − y 2 I 1 + y 1 − ( y 4 + 1 ) y 1 − y 2 I 2 ] − [ y 4 − y 2 y 1 − y 2 I 1 + y 1 − y 4 y 1 − y 2 I 2 ] = I 1 − I 2 y 1 − y 2 ΔI_4=[\frac{(y_4+1)-y_2}{y_1-y_2}I_1+\frac{y_1-(y_4+1)}{y_1-y_2}I_2]-[\frac{y_4-y_2}{y_1-y_2}I_1+\frac{y_1-y_4}{y_1-y_2}I_2]=\frac{I_1-I_2}{y_1-y_2} ΔI4=[y1−y2(y4+1)−y2I1+y1−y2y1−(y4+1)I2]−[y1−y2y4−y2I1+y1−y2y1−y4I2]=y1−y2I1−I2同理 Δ I 5 = I 3 − I 2 y 3 − y 2 ΔI_5=\frac{I_3-I_2}{y_3-y_2} ΔI5=y3−y2I3−I2
在扫描线内部,从 P 4 P_4 P4到 P 5 P_5 P5之间的点同样可以使用增量算法,当横坐标由 i i i变成 i + 1 i+1 i+1时,新的 P ∗ P^* P∗的光强为 I p ∗ = I p + Δ I p I_p^*=I_p+ΔI_p Ip∗=Ip+ΔIp其中 Δ I p = I 5 − I 4 x 5 − x 4 ΔI_p=\frac{I_5-I_4}{x_5-x_4} ΔIp=x5−x4I5−I4
大体步骤与Gouraud明暗处理算法是相似的,只要把光强 I I I替换为法向量 N N N即可,在像素处再计算使用Phong光照明模型计算光强。 N N N是三维的,因此计算时间也会随之增长。
水平有限,如有错误疏漏,欢迎指出