第十二章:Mesh细分、光线追踪
网格操作:细分、简化、规则化
Mesh 细分(引入更多的三角形,让三角形的位置发生变化,使得原来的模型变得更光滑)
Loop Subdivision(Loop 不是循环的意思,是发明者的 familyname 是 Loop)
1.把三角形分成更多的三角形:连接边的中点
2.调整三角形的位置(把三角形的顶点区分成新的顶点和老的顶点,分别应用不同的规则改变顶点的位置)
度:一个点相邻的边数。
新的顶点用四周的老顶点做加权平均
老的点用原本的点位置和相连三角形的顶点位置再加上度做加权平均。
Catmull-Clark Subdivision(General Mesh)
Loop Subdivision 只能处理三角形的情况,Catmull-Clark 可以处理任何面
两个概念:
1.非四边形面
2.奇艺点(度不为 4 的点)
细分:
每一条边都选它的中点,每一个面都选中间的一个点。把边上的中点和面的中点连起来。
只要是非四边形面,就一定会引入新的奇艺点。经过一次细分后,非四边形都会消失,也即不会再增加新的奇艺点。
新的点考虑在面中心的点和边中心的点两种情况。
老的点用它原本的位置和新的面中心点、边中心点做加权平均。
Mesh 简化
不同情况下选用不同复杂度的模型,比如离得远的时候用简化模型
但是几何的层级结构不好处理,从 300 个网格到 3000 个网格时平滑过渡怎么处理
简化怎么计算?
一种方法:边坍缩
坍缩即找到一条边的两个顶点,捏成一个顶点,重点是找到要坍缩哪些点。
用到一种叫做二次(平方)误差度量(Quadric Error Metrics)的方法
找到一个最优位置,使得它到原本相关联的各个面的平方和达到最小。
选坍缩的边的时候,给每个边一个分数表示坍缩后最优位置计算出来的平方和,选择平方和最小的边。但是坍缩一条边后,会影响其他相邻的边。所以需要一边求最小,一边动态更新任一点的值,需要用到优先队列(堆)的数据结构。
局部取最小,更新受影响的边的二次度量误差,再取最小,再更新…
用局部最优解找全局最优解(贪心算法)
越简单越接近平面的面坍缩得越多(计算出来的二次度量误差越小),比如下图中的小奶牛的面部坍缩的多,但是颈部坍缩的少
光线追踪
光栅化怎么绘制阴影?
着色是一种局部行为,仅考虑自己、光源和摄像机,不考虑其他物体,因此无法解决阴影的问题
于是发明了阴影映射(shadow mapping)。
图像空间算法
- 在生成阴影的时候不需要知道场景的几何信息
- 会产生走样现象
主要思想
- 如果一个点不在阴影里面,说明可以从照相机看到这个点,也可以从光源看到这个点
- 如果一个点在阴影里,说明相机可以看到这个点,但是光看不到这个点
经典的 shadow mappding 只能处理点光源,这种阴影是非 0 即 1 的阴影,叫做硬阴影
从光源看向物体,生成一幅图,把不同位置看到的点的深度记录下来
再从摄像机出发看向场景。把看到的点投影回光源,就知道之前记录到深度图上的深度。把记录的深度图深度和眼睛看到的点到光源的实际深度比较,如果二者一致,说明这个点一定即可以被光源看到,又可以被摄像机看到。
如果深度不一致,说明这个点被挡住了。
shadowMapping 会有各种问题:
判断深度是否相等,需要判断两个浮点数相等,实际一定会有误差,有精度问题。
另外 shadowMap 自己有分辨率,如果这个分辨率很低,但是渲染场景的分辨率很高,那么阴影信息是走样的
另外要做两遍渲染,从光源看过去做一遍,从相机看过去做一遍,性能开销大
硬阴影 VS 软阴影
硬阴影要么可见要么不可见,边缘很锐利
软光源边缘是慢慢过渡的,越靠近物体根部阴影越硬
软硬指的是物理上的半影。如果一个地方完全看不到光源,则这个地方叫做本影区域,如果看得到部分光源就叫做半影,如果完全能看到则没有阴影。
阴影程度取决于可以看到多大的光源。