GAMES101-08- Shading 2(Shading,Pipeline and Texture Mapping)

Shading 2(Shading,Pipeline and Texture Mapping)

高光(Specular Term)

光滑的平面通常会出现镜面反射,当观察方向与镜面反射方向接近的时候就能看到高光。

高光向量与光源向量是以法线为对称轴对称的。

image-20220319094815770

Blinn-Phong模型计算高光的能量

image-20220319095050584

Blinn-Phong模型引入光源向量\(\vec l\)和观测向量\(\vec v\)的半程向量\(\vec h\)来方便计算。一定程度上,\(\vec h\)\(\vec n\)接近,能反映\(\vec v\)(观察方向)和\(\vec R\)(镜面反射方向)的接近。而观察方向与镜面反射方向越接近,所看到的高光效果越强。

当然也可以直接用\(\vec v\)\(\vec h\)的接近来表示公式,那就是Phong模型。而Blinn-Phong模型是Phong模型的改进,因为Blinn-Phong的半程方量更好算些。

所以Blinn-Phong就巧妙地得到表示高光强弱的公式:

\[L_s=k_s(I/r^2)max(0,cosα)^p=k_s(I/r^2)max(0,\vec n \cdot \vec h)^p \]

按道理Blinn-Phong模型考虑了光的到达量\(k_s(I/r^2)\),也应该考虑光的吸收量\(max(\vec l \cdot \vec n)\),但Blinn-Phong模型为简化模型,就没有考虑物体吸收能量的部分了。

为什么要引进指数p?

答:下面的函数图像是带有指数的余弦函数的值。可以看出,对于cosα,结果值都非常大,这样高光就范围特别广,这是不合理的。因为我们希望高光都是集中在很小的区域里的。因此我们要引入惩罚项指数p。比如观察\(cos^{64}α\)的值就比较合理了,这样的话只要\(\vec v\)\(\vec h\)偏离一点就不算它在高光范围内,这样就实现了高光集中在很小的区域内。(正常情况下,p的范围在100~200)

image-20220319100557191

下图给出了高光系数\(k_s\)\(p\)值(给出了高光和漫反射都存在的观测结果)发生变化时的球体观测情况:

image-20220319101140486

环境光(Ambient Term)

环境光的相关定义

image-20220319120450060

①环境光与光照方向和观测向量无关。
②环境光是一个常数(是某一种颜色)。
③本节学的环境光计算是一种简化的计算。

Blinn-Phong反射模型

Blinn-Phong反射模型的单点着色=环境光着色+漫反射着色+高光着色

image-20220319150028510

着色频率(Shading Frequencies)

着色频率是指对某一片大小区域着色,考虑的是面。下面是三种不同着色频率对应的观察结果。

image-20220319152017641

左图,一个平面就做了一次着色。

中图,一个顶点就做了一次着色。

右图,一个像素就做了一次着色。

三种不同着色频率的着色模型

Flat Shading

逐三角形进行着色,每个三角形颜色一致。

image-20220319152647772

Gouraud Shading

逐顶点进行着色,每个三角形内根据三个顶点进行插值着色,看起来比较平滑。

image-20220319152747403

Phong Shading

逐像素点进行着色。

image-20220319152911159

三种着色模型的对比

如果模型的顶点/面越多,三种着色模型的差距会变小直至相同。(当然不太复杂的模型,还是Phong着色效果更好些)
模型越复杂,前两种着色模型的效果会增强,但同时开销也会越大。

如果三角形面数多于了像素数,flat的工作量甚至会小于phong

image-20220319153116334

如何计算顶点的法线

image-20220319153529147

考虑如上的模型

  • 方法一:通常一个顶点都会属于多个平面,对这些平面的法线之和求平均即可得到顶点的法线

image-20220319153600624

当然每个平面多占比重不同,比如上图中法线\(\vec N_2\)所在平面比较小,法线\(\vec N_3\)所在平面比较大,那么对于顶点法线的贡献也会更大一些。

所以,根据各个面的面积进行加权平均,效果会更好。

如何计算像素的法线

假设我们已知两侧的顶点法线,如下图中间的法线就是顺着法线方向一一排开(注意,所有的法线都是反向,所以要对所有的顶点法线都进行归一化处理变成单位向量,保证它们的长度相同)。

给出顶点的法线,怎么样计算出中间的插值法线呢?

答:使用重心坐标可以进行计算得到内部的各个点的法线。

image-20220319154046685

管线(Pipeline)

管线指的是从模型到像素的整个绘制流程,可以看成是从模型到绘制成图的一个流水线。管线分为以下几步:

image-20220319154704647

顶点处理\(\rightarrow\)三角形处理\(\rightarrow\)光栅化\(\rightarrow\)像素处理\(\rightarrow\)混合所有的像素成一张图像
注意
如果着色模型是Phong Shading,则着色步骤是在像素处理环节进行;

如果着色模型是Gouraud Shading,则着色操作可以在顶点处理环节进行。

Shader Programs

现在的GPU支持自己编写顶点或者像素的着色程序。

在Shader里面只需要管一个顶点或者像素就行,定义顶点着色器或者像素着色器。

下图是简单的OpenGL的着色语言GLSL的像素着色器的小程序:

image-20220319161049227

推荐网站shadertoy:https://www.shadertoy.com/view/ld3Gz2

只需要定义好着色器,将程序写出来后在网页上就能看到对应的结果。

纹理映射(Texture Mapping)

我们希望定义在物体不同位置定义不同属性,根本上就是定义任何一个点的不同的基本属性。

image-20220319162132257

纹理映射

image-20220319162335863

任何一个三维物体的表面其实是二维的。那么我们可以把纹理定义为一张图。
纹理映射:在物体表面应用纹理可以理解为是对其进行贴图。找到物体上的一个点跟纹理上的点的关系。

image-20220319162556761

纹理坐标系

我们知道纹理应该怎么“贴图”,是因为我们知道三角形对应的纹理坐标。也就是说我们需要定义了一个纹理坐标系(u, v)image-20220319162917384每个三角形都对应纹理坐标系上的一个位置,实际的纹理映射结果如下:

image-20220319163145635

而不同位置也可以映射到同一纹理,也就是说纹理可以被重复使用,如下图的地面部分,纹理就被重复使用了。

image-20220319163256863

从上图可以看出,纹理之间有个非常明显的缝隙,而想要纹理无缝衔接(tiled)的合成是很困难的,需要各种各样的算法。这里就是简单提一下。

image-20220319163604049

回到上面纹理映射的话题,我们已经知道三角形三个顶点对应的纹理坐标(u,v),那么我们怎么知道三角形内部各个点对应的纹理坐标(u,v)呢?如何实现三角形内部的平滑过渡?

答:这又涉及到插值问题,跟重心坐标相关,下节课解释。

posted @ 2022-03-19 16:42  L-Yeeky  阅读(71)  评论(0)    收藏  举报