网格细分
网格简化
网格正则化:改进三角形质量的同时不能丢失模型的质量
Subdivision/细分
Loop Subdivision
不只是引入三角形,细分除了分出更多的三角形,还会让三角形的位置发生变化,使原来的模型更光滑
数量增多,连接三角形三条边的中点
调整三角形位置,即调整顶点位置。区分新顶点与旧顶点
更新新顶点:新顶点一定在一条边上,如上图白点,只要其不在物体的边界,那么一定被两个三角形所共享。找到上图四个点的位置ABCD,进行加权平均
调整旧顶点,一部分相信周围旧顶点的平均值,另外一部分也相信自己
定义n:顶点的度,即顶点连接的边的数量,上图为6.
定义u:跟顶点的度有关系的数
Catmull-Clark Subdivision
如果不是三角形网格,无法用loop细分。
定义四边形面和非四边形面。
定义奇异点:度不为4的点
每一条边取中点,每一个面也取中点,并且把这些点连起来。
只要在一个非四边形内引入的新点,就是奇异点。
每一个非四边形面都会引入一个奇异点,在引入奇异点后非四边形就消失了
因此经过第一次细分后,会增加非四边形面数的奇异点,之后再也不会增加
- 点在面中间的点f
- 点在边的中心的点e
- 旧的点v
Mesh Simplification
对于远处的物体,不需要建模特别细的物体。不同的情况下,要选用不同复杂程度的模型。类似mipmap
边坍缩,找到一条边连接的两个点,捏在一起
左图是五个点平均,可以看出求平均不是合适的方法
二次误差度量:新的顶点和原本的面都有关系,求这个点到原本的几个面的距离的平方和,并希望这个点求得得平方和最小。
希望坍缩的任一条边之后形成的点可以放在一个最优的位置,求得一个最小得二次误差度量。
对于整个模型,都假设坍缩每一条边会有多大的误差
先把每一条边打上一个分数,分数即为二次度量误差。
从小的开始一个个做坍缩。
注意每坍缩一条边可能会引起其他边的变化,造成二次度量误差的变化。
因此做完一个坍缩后,要更新所影响的边的二次度量误差。
使用优先级队列或堆
贪心算法:在任意一个局部找最优解,试图找到全局最优解
Shadow Mapping
之前的着色是只考虑局部的,解决不了阴影物体
解决阴影映射的方法就是shadow mapping,对应的结构是shadow map
shadow mapping本质是一种图像空间的做法。只要用了shadow mapping,在生成阴影的这一步,是不需要知道场景的几何信息的。
shadow mapping会产生走样现象。
最重要的思想:如果一个点不在阴影内部,说明可以从摄像机看到这个点,并且光源也可以看到这个点。如果在阴影内部的点,说明摄像机可以看到这个点,但是光源无法看到这个点
经典的shadow mapping只能处理点光源,或者说方向光源,这种阴影会有非常明显的边界,要么看到要么看不到,是非0即1的过程,称为硬阴影
第一步:先从光源看向场景。放一个摄像机在光源的位置,对准整个场景,做一遍光栅化。就可以得到光源会看到什么的一张图。这张图不做着色,而把不同位置所看到的点对应的深度记下来。
第二步:从真正摄像机的位置再次看向场景,看到场景的某个点,可以把点投影回刚才光源位置虚拟摄像机的成像平面上,即从光源看这个点应该出现在深度图的哪个像素上。然后计算这个点实际到这个光源的深度。对比光源的深度图,如果是一样的,说明光源可以看到,如果不一样,说明光源无法看到
光源在左上角
从光源位置看向场景
不着色,只记录深度zBuffer
通过真正的摄像机看向场景,将实际点投影回刚才生成的shadow map,对比shadow map记录的深度和实际点与光源的深度。
问题:
实际的场景中各种距离都是浮点数,浮点数由于精度问题判断相等有误差。
并且一个像素里可能覆盖很多点,每个点间可能有微小的差异,与光源计算距离时会有一点点不一样
所以引入了一个偏差bias/eps,一个很小的数,不仅要大于shadow map记录的深度值,还要大于深度值+偏差的值才表示在阴影内。
但无法解决本质问题
生成shadow map时,如果分辨率不够,会形成一个有锯齿的阴影,但分辨率变大又会带来更大开销。
shadow map虽然有很多问题,但仍然是现在3d游戏的主流技术
硬阴影:(软阴影光源有一定大小,处理从光源的哪一部分看上场景)
阴影图的分辨率
浮点精度问题
硬阴影与软阴影对比
硬阴影:对点光源来说,地面上的点要么可见要么不可见,所以阴影一定是非常锐利的边缘
软阴影:在物理上称为半影,如果在一个地方完全看不到光源,就是本影区域,如果可以部分看见光源,则是半影区域,完全能看到光源,则没有阴影。如上图日食
阴影程度取决于能看到多大的光源,因此点光源是不可能有软阴影的,如果有软阴影说明光源有一定的大小