飞道的博客

5、计算机图形学——着色

480人阅读  评论(0)

简介

shading就是计算出每个采样像素点的颜色是多少。本文所要介绍的是局部光照模型,并不是真正准确的模型,但是优点是计算快,效果可以接受,至今依然广泛的运用在各种游戏之中。具体会从最基础的泛光模型,Lambert漫反射模型,再到Phong反射模型,Blinn-Phong反射模型一步步推进详细详解我们如何得到一个局部光照模型

局部光照模型的基础是物体能被我们观察,是因为人眼接收到了从物体来的光,那么究竟有几种类型光线能从物体到人眼呢

从上到下分别为:镜面反射、漫反射、环境光

具体模型

泛光模型

** 泛光模型即只考虑环境光,这是最简单的经验模型,只会去考虑环境光的影响,并且不会去精确的描述,而只是用一个简单的式子表示**

其中Ka代表物体表面对环境光的反射率Ia 代表入射环境光的亮度,Ienv存储结果,即人眼所能看到从物体表面反射的环境光的亮度

泛光模型只能让我们看到一个物体的平面形状

其中反射率还是光的亮度都是一个3维的RGB向量,为什么一个物体能够有颜色,就是它吸收了一定颜色的光,将剩下的光反射出来,也就有了颜色

Lambert漫反射模型

Lambert漫反射模型其实就是在泛光模型的基础之上增加了漫反射项。漫反射便是光从一定角度入射之后从入射点向四面八方反射,且每个不同方向反射的光的强度相等,而产生漫反射的原因是物体表面的粗糙。Lambert漫反射使得物体有体积感


这种漫反射我们该去怎么模拟呢?首先应该考虑入射的角度所造成的接收到光强的损失

只有当入射光线与平面垂直的时候才能完整的接受所有光的能量,而入射角度越倾斜损失的能量越大,具体来说,我们应该将光强乘上一个c o s θ = l ⋅ n,其中l 是入射光方向,n为平面法线方向。

好了!除了入射角度之外,光源与照射点的距离也应该考虑,直观来说,离得越远当然强度也就越弱!具体来说如图所示

中心为一个点光源,光线均匀的向周围发射,可以想象光源发射出来的能量其实是一定的,那么在任意两个圈上接受到的能量之和一定相等。而离圆心越远,圆的面积越大,单位面积所接受能量也就越弱,因此会将光强 I 除上一个r^2

其中Kd为漫反射系数,I 入射光强,n , l 分别如图中所示为法线向量和入射方向,max是为了剔除夹角大于90°的光。

注意漫反射光线强度是与出射方向无关的,因此无论人眼在哪观察接收到的强度都是一样的

将环境光与漫反射一起考虑之后

通过改变漫反射模型的3维反射系数Kd,我们就能够得到物体表面不同的颜色

Phong反射模型

因为漫反射的存在我们已经能够很明显的看出茶壶的体积感了,但依然感觉不是很真实,因为缺少了高光!即镜面反射

R 为镜面反射方向,v为人眼观察方向

**除了考虑漫反射中提到的光源到反射点的距离r之外,需要注意的是,观察方向在镜面反射时是很重要的,具体来说,只有当观察方向集中在反射方向周围很近的时候才能看见反射光,因此在镜面反射中会考虑 R 与 v的夹角 α **

其中 Ks 为镜面反射系数,I 为入射光强,r 为光源到入射点距离,注意这里在max剔除大于90°的光之后,我们还乘了一个指数p,添加该项是因为离反射光越远就越不应该看见反射光,需要一个指数p加速衰减

Blinn-Phong反射模型

对phong模型计算反射方向与人眼观察方向角度的一个优化

将反射方向与人眼观察方向夹角替换成如下图所示的一个半程向量和法线向量的夹角

这样的得到的结果其实是与真实计算反射与人眼观察夹角的结果是非常近似的(具体来说该角度是正确角度的一半),但好处在于大大加速了角度计算的速度,提升了效率!

反射向量可由入射方向在法线方向投影的两倍减去入射方向得出

着色方法(频率)

局部光照模型,主要利用了观察方向,入射光线与法线向量的位置关系,但并没有具体说究竟是三角形面的法线向量还是三角形顶点的法线向量,这也就着色频率(面着色,顶点着色,像素着色),这3种不同的着色频率其实也就对应了三种不同方法

Flat Shading

面着色,顾名思义以每一个面作为一个着色单位。模型数据大多以很多个三角面进行存储,因此也就记录了每个面的法线向量,利用每个面的法线向量进行一次Blinn-Phong反射光照模型的计算,将该颜色赋予整个面

Flat Shading 虽然计算很快,只需对每一个面进行一次着色计算,但是效果确是很差的,可以很明显的看到一块块面形状

Gouraud Shading

对三角形面的每个顶点进行着色,再对三角形面内的颜色插值

我们只有每个面的法线向量,要得到每个顶点的法线向量,将所有共享这个点的面的法线向量加起来求均值,最后再标准化就得到了该顶点的法线向量了

有了每个三角形的顶点向量之后,自然就可以计算出每个顶点的颜色了,再利用重心坐标来插值计算三角形内部的每一个点

其中c 0 , c 1 , c 2为三角形三个顶点的颜色,α , β , γ为三角形面内一点的重心坐标,c为该点的插值之后得到的颜色。

我们实际上只对每个三角形顶点进行了着色,然后其它的颜色都是通过插值得到,还不是最好的做法

重心坐标一定要是原世界坐标空间中的重心坐标,但实际计算中一般会使用投影之后的二维平面来计算重心坐标,存在着一个误差需要校正

Gouraud用的是双线性插值,这里直接用了重心坐标插值

Phong Shading

要对每个点都进行光照计算,那么要有每个点的法线向量,对于三角形内部的每一个点的法线向量自然也可以像插值颜色一般得到

其中n 0 , n 1 , n 2分别是三角形三个顶点的法线向量,α , β , γ为三角形面内一点的重心坐标,n为该点插值之后得到的法线向量。如此便得到了任意一点的法线向量了,可以对任意一点进行Blinn-Phong模型的计算。

可以明显看出Phong Shading对于高光的显示相比于Gouraud Shading是更真实的。有一点的要注意的是,这里所有的茶壶所使用的都是一个低精度模型,这点可以从Flat Shading的结果可以看出,面片是有限的,那么如果随着模型精度的提升,各种shading type又会有怎样的区别呢

变换法线向量

法线向量不是一直存在于世界坐标空间之中吗,为什么要去变换他呢,其实原因很简单,因为模型变换可能会导致模型位置形状发生改变,如果属于该模型的各个三角形面的法线向量不跟着改变的话,那么此时所记录的法线向量就是错误的。因此法线向量一定也要跟着模型本身发生改变。

那么是否简单的将作用在模型本身的变换也作用在对应的法线向量之上就可以了呢?答案是否定的,这也是为什么要在这里探讨这个问题,如下图所示,一个简单矩形经过一个剪切变换M之后

在经过一个简单的剪切变换之后,不难发现矩形右边的法线向量没有改变,如果此时简单的用变换矩阵M ⋅ n 得到的结果就是图中的所标注为Mn的向量,并不是与该面垂直的法线向量,那么对应的真正的变换矩阵应该是什么呢?


转载:https://blog.csdn.net/weixin_50973728/article/details/125915775
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场