Games101阶段性总结③(坑)
一、Shader着色
一般我们所求的都是方向,而不是一个值
所以对于normal、light、view都是要经过normalize之后才会使用的
对于简单经验模型而已
漫反射就是将颜色值与dot(n,l)的值所得到的,要将值取(0,1)
高光就是pow(dot(n,h),glass)
环境光没有,但是一般我们环境光会采用静态烘培的方法来取得
对于Shader一些成熟技术,我打算自己整理之后再发布,这里就不详谈了。
漫反射

对于每一个光源,都是有能量的,我们设半径为1时,能量为I,而当半径为R时候,通过球的表面积公式
可以得到一个I/R平方的能量
高光的产生是当反射方向与我们view方向足够接近时产生的,通过Blinn——Phong的经验模型可以得到,我们这个关系,就相当于把viewDir与LightDIr相加求个方向,就是平行四边形定理,取名为半高方向h,观察法线与半高方向的距离就可以得到高光

环境光是个复杂的计算值,在全局光照中通过烘培,将其颜色印在场景中产生影响,在这先用常量进行计算

最后在这个实验模型中的表面颜色就是将上述的式子进行相加

二、着色频率
有三种着色频率:
-
(flat)着色,对面着色,对三角形两边做叉积,得到一条法线,将这条法线与光照方向点积可得表面颜色。
-
(Gouraud Shading)逐顶点着色,对顶点的法线进行上述操作
-
(Phong Shading)逐像素着色,对像素的法线进行上述操作
如何得到顶点着色器的法线
- 模型自带的法线数据
- 或者用相邻三角形的法线求平均得到(对三角形加权的平均,看谁面积大,谁的比率越多)
如何得到逐像素着色器的法线
-
对上述顶点着色器得到的法线,进行插值

-
利用重心坐标
三、重心坐标
得到一个重心坐标对我们如何得到插值的像素点很重要,我们假设我们已经得到3个顶点的坐标和一个任意一个包含在三角形内的点,那么都有这个定式

其中α、β、、γ的条件都要大于0,因为要是有一个是负数,这个点在不在三角形内就不好说了。
有了这个规定之后,我们也就可以通过三角形的面积比来得到α、β、、γ

已知三个顶点,那么这三个顶点围成的三角形的面积就等于S=1/2*(x1y2+x2y3+x3y1-x1y3-x3y2-x2y1)
这样就可以求出α、β、、γ了
当然也可以使用现有公式

那么知道了重心坐标在哪了,就利用它做各种插值,如Color、Depth、Normal等信息的插值
(3D中 取3维空间的坐标,且不能在投影之后算,要在世界空间做)
那么光栅化采样之后的(x,y)就要映射到我们采样的纹理的uv坐标上了(将纹理采样到uv坐标),
这样就能得到Texture的Color了。
四、屏幕空间与纹理过小、过大关系
当我们的屏幕大于我们纹理时候,纹理就要把自身拉大,我们的采样点所对应的uv坐标就不是一个整数值了,默认会被四舍五入的映射成附近的值,结果就会导致部分像素映射到了同一块颜色值上了,导致模糊,这不是我们要的结果,所以要引入插值,而这里的插值也被称为双线性插值(Bilinear)
假设一个点刚刚好落在下列这张图的红点处,如果按照四舍五入,它就得映射为u11的纹素了,那么引入Bilinear之后,就进行这样的操作,在水平方向取2次插值,一个上方的插值,一个下方的插值,最后在做一次高度的插值,这样得出的颜色就会比较平滑,没那么多硬过渡(锯齿)

那么纹理过大呢,那我们屏幕空间在远处所采样的那个点就会对应到可能是一整张纹理了,离我们摄像机越远,我们看的东西就会越来越小,但是纹理像素要是没规定的化,他是保持像素不变的缩小,这就是问题,那么我们屏幕空间所采样的点,是不是就是一张纹理图,这也太大了,对一张图做平均,那得到的肯定就是Bad的了。
所以引入Mid Map(多级渐远),不先采样,先让我们的纹理自己产生对应层数的纹理
总层数D=log2纹理分辨率,它是一个快、近似、正方形的范围查询
开销是增加1/3存储

通过映射到的uv坐标的点与点之间的距离,可以得到我们所采样的是在第几层

那么我们如何再平滑一点的层与层过渡呢,其实也是引入插值
在我们的两个目标层与层中,每层的像素自己先做一次插值,然后再对应的像素之间插值

多级渐远的更进一步平滑过渡,完全连续的各向异性过滤(Anisotropic Filtering)
原本我们只能用正方形去取平均,现在可以用矩形去取了,开销是原来的3倍,但是只要显存足够,基本没有多少消耗

四、如何利用纹理信息
texture=memory(内存)+range query(范围查询)
纹理去表述环境光
有两种表述形式
Spherical Environment Map,将周围环境蒙在一个材质球上的纹理,但展开会发现头部与底部会有明显的收缩重叠的结果,对于映射顶部与底部不友好。
Cup Map,将周围环境按一定规则贴到正方形的六个面上
以上都可以通过空间内的方向向外延伸取交点来映射,而不论球,还是正方形都存储了我们用来模拟环境光照的信息
凹凸贴图(Bump/Normal mapping)
纹理定义它在法线上往上往下各走了多少(相对高度)
物体表面产生凹凸感,其实就是我们人为的对物体的法线进行了修改,扰动(Perturb)了像素的法线。

每个像素不同位置的高度,邻近的法线贴图产生的高度差,从而重写计算法线(改变相对高度,改变法线,从而改变法线法线)
一般在Unity种,我们会引入切线空间来进行法线贴图的映射,先规定我们的切线空间下的纹理法线方向总是正方向,且为(0,0,1),而最后切线空间的法线还得对纹理进行映射取的
还有一种方法可以表现凹凸的是位移贴图,上面的法线贴图,是不会改变物体的顶点信息的,但是位移贴图,是通过移动顶点,从而改变面来表示凹凸的,一般只能用于三角形比较细致的,才可以用位移贴图
在DX中,采用动态曲面细分来区分是否要使用位移贴图,从而动态改变面的松细
Noise函数贴图:
三维空间中利用噪声函数,解析这个函数,了解值为多少,通过二值化等生成一张贴图
ambient occlusion(环境光遮蔽),将我们的纹理图拿出来,往里面添加信息,最后采样后于光照模型想乘,得到物体被自身所遮挡的阴影信息,由此可见,纹理可以储存很多信息,Dota2中的人物模型就是典型例子

浙公网安备 33010602011771号