前言:一些读书笔记
引用闫令琪老师的课程内容,GAMES101,老师讲的很好,可以看原课程视频。
Shading
这部分内容主要讲在光栅化后,怎样将每个像素或者每个顶点去染色。
1)着色
在一个特定的点去计算相机中看到的光反射。
假设这个点是一个小平面,那么我们有观测的方向,光线的方向,法线和平面。
(这里是考虑局部的着色情况,不考虑其他物体导致的阴影)
2)Blinn-Phong Reflection Model
1.漫反射
在同样的范围内接受的光照一样。
Lambert's Law:每个单位所接受到光的能量与光线和平面的夹角成正比,,其中nl表示法线和光线方向向量。
光会随时扩散使得每个点上的能量越来越小
因此我们得到漫反射的光为:
其中,在实际中,不同材质对光的吸收程度是不一样的,因此可以用表示吸收系数。
注意,漫反射从不同角度观测光是一样的,所以v的角度我们并不在乎。只在乎l的角度
2.镜面反射
高光处的材质一般比较光滑偏向镜面反射。当我们观察的方向接近镜面反射的方向时,我们能感受到高光。
Blinn-Phong:观测方向接近镜面反射方向=法线方向接近半程向量方向
这个改进点在于半程向量比反射向量好算。
注意,公式上的指数p是为了让cos的容忍度不那么高,即h离n远些时高光下降的快。正常取100~200。
3.环境光
当没有光照时,物体有可能接受到环境反射过来的光线。但由于太复杂,因此假设不论什么时候接收到的环境光都一样为。
总结:当这三种光加起来,则称为Blinn-Phong Reflection Model
3)着色频率
1.Flat shading
根据每个三角形是个平面求法线来着色。
2.Gouraud shading
在任意一个顶点上求法线来着色。每个三角形内部的颜色通过插值来求。
3.Phong shading
在任意一个顶点上求法线来着色。每个三角形内部的法线通过插值来求。每个像素都求一次shading。
求顶点的法线:把顶点关联的面的法线求加权平均。
4)渲染管线
一系列操作使得一个物体渲染到屏幕上。
GPU:可以提供图像管线的计算。
5)Shader Programs
这个函数用来处理每个顶点或者像素做的事情。
Snail Shader Program提供了一个实时渲染的网页,只用写顶点渲染。
6)纹理
3维物体的表面是2维的。因为我们可以将一个3维物体的表面展开为2维的纹理来映射。即3维物体的表面三角形的顶点坐标与2维纹理的uv一一对应。
纹理可以用来表示环境光。
1.一个简单的纹理映射过程为:
在三维空间中找到纹理对应的二维坐标的颜色。然后对应计算Blinn-Phong,设置新的颜色。
2.纹理过小
当纹理的分辨率不足时
a.Nearest
采用附近纹理一样的纹理。比如说1.5处就采取2的纹理,这样会导致一个区域的纹理会形成一个块。
b.Bilinear
找邻近的4个点进行线性插值。
c.Bicubic
找邻近的16个点进行三次插值。
3.纹理过大
远处的像素一点覆盖了很大一片纹理区域。如果使用MSAA,此时消耗过大。
因此采用MipMap,使用更多空间存储,此时多使用的空间是原来的1/3。
可以通过微分方法求得当前像素点在纹理上的区域(边长L),然后在层MipMap查询。如果层数不为整数,可以用三线性插值(即在D层得到双线性结果,再在D+1层得到双线性结果,对这两个结果插值)来查询。
但是MipMap会导致过分的模糊,因此采用各项异性过滤会更好。因为MipMap把区域限制为正方形了,对不规则的形状适应性不好。
4.纹理的作用
a.spherical environment map:将环境光记录在球上,但是展开为平面图后会发生扭曲。
->cube map:用一个立方体包围住球,把环境光信息记录在立方体上,这样就不会发生扭曲现象。
(二者本质都是一样的,都是为了描述不同方向的光照信息。)
b.凹凸实现
通过改变贴图,法线扰动。
在平面情况下法线扰动的原理是:原本的法线是(0,1),通过改变高度,然后计算切线,旋转90°得到法线,即由,再做归一化即刻得到扰动后的法线。
在3D情况下法线扰动的原理是:原本的法线是(0,0,1),求导,,同样旋转90°,可以得到新的法线为,再做归一化。
注意这里是假设局部坐标
c.displacement mapping位移贴图,实际上真的去移动了顶点
7)重心坐标
当知道顶点的着色的时候,为了让颜色更好的过渡,所以需要对三角形内部进行插值。此时可以用到重心坐标。
三角形内任意一点的重心坐标可以通过面积比来得到:
三角形的重心就是,此时刚好三块面积相等。
将上述公式可以简化为坐标。
因此,可以通过重心坐标线性插值:
插值三维空间的重心坐标时,需要在投影前来插值。