10 Geometry 01#
纹理 可以理解成是一块数据, 不限制在图像
Environment Map 周围环境记录下来, 可以用纹理去描述环境光长什么样, 用这个环境光去渲染其他物体. 环境光贴图假设的环境光距离无限远且强度一样(只记录方向信息, 无限远, 没有深度信息, 一般最好是方向和位置信息都要有)
Spherical Environment Map#
把环境光记录在球面上再展开, 这样会有扭曲问题
Cube Map#
解决了Spherical Environment Map的扭曲问题, 把环境信息存在立方体上
缺点是想判断某个方向的光照时, 在球形上容易判断, 在cube上需要先判断这个光照被记录在那个平面上. 代表着需要额外的计算(非常快)
凹凸贴图#
纹理可以定义任何不同位置的任何不同属性
这里距离是定义任何一个点的相对高度, 从而影响到法线, 影响到shading结果. 不改变几何形状的情况下制造假的视觉效果
凹凸贴图和法线贴图本质是改变某个点的法线
如何计算法线如何变化#
案例考虑的是一维的情况in flatland
假设一个平面, 受凹凸度贴图产生变化
定义一个点P(0,1)
凹凸变化后, 定义P的切线, 用相邻两个点的高度差除以间隔1,再乘以常数c, 常数c定义高度贴图影响强度
通过切线求法线, 法线垂直于切线
向量导数定义是水平方向和竖直方向的移动距离xy. 由此得到法线定义为(-dp,1)归一化, dp是切线的y坐标
在三维情况下, 假设有个二维的贴图, 求点p被凹凸贴图的影响
假设点原本为n(p) = (0,0,1), 在纹理坐标移动1u, 1v(纹理单位), 切线会有什么变化, 由此写出切线方向, 再求出法线(-dp/du,-dp/dv,1).normalized
这里讨论的是局部坐标的情况, 一般计算法线, 是把指定的点(这个点法线会是任意方向)归为(0,0,1), 再计算切线方向, 再把结果转换到世界坐标
Displacement mapping#
实际上移动了顶点位置, 效果比凹凸贴图好, 但要求模型面数高
动态曲面细分, 根据需要做细分来满足置换贴图需要的面数
3D Procedural Noise#
定义的是空间中任意点的值
预计算#
提前计算好shading需要的信息, 加快渲染速度
体积渲染#
磁共振 记录任意点的密度信息
几何归类#
隐式几何
不会表示点的具体位置, 而是表示这些点的关系
x^2+y^2+z^2 = 1 球的隐式表达
可以通过函数f(x,y,z)=0去找出所有复合这个函数定义的点, 这些点连接起来就是一个圆
缺点是无法通过式子判断形状, 优点是可以快速判断某个点是否在物体内部
显示几何
用三角形表示某个几何形状是一种显示几何
参数映射: 马鞍面 定义函数, 输入是Uv, 输出是xyz, 每个uv代表空间中的某个点, 这样可以通过输入uv值来构建几何图形
由于公式定义了点的具体位置, 所以被定义为显示
显示几何容易判断图形, 但不方便判断某个点是否在物体内部
Csg(隐式)#
通过合并隐式几何来实现布林操作Boolean
距离函数(隐式)#
描述任何一个点到几何表面的最近距离
空间中任意一个点, 到想要表述的几何形体上任意一个点, 算出它们之间的最小距离, 正的表示点在几何外部, 负的表示在内部.
最后将两个不同物体, 两者距离函数计算出来再做个blend, 再恢复出物体, 可以看出有融合现象
如果你用两张灰度图来代表两个边界, blend结果中间会是一个灰色区域, 无法表达边界融合
但SDF的blend结果转换成图形, 就可以准确表达边界融合
SDF = (1-t)·SDFa+t·SDFb
假设SDFa边界在0.3, SDFb边界在0.7, t=0.5, 求融合后的边界
取x=0.5, SDFa=0.2, 因为这个位置在右侧, 距离SDFa边界距离为0.2, 同理, SDFb = -0.2
SDF = 0.5·2+0.5·(-2) = 0, 所以边界在0.5的位置
融合两个物体距离函数再恢复, 就是求SDF=0时点的位置
水平集#
有一些格子, 在格子上写不同的值, 连接结果为0的地方. 这就是用水平集表达SDF, 因为SDF不方便用式子表示, 所以用这个方法表示.
水平集也可以应用到三维空间, 给不同物体赋予不同密度来区分物体, 用水平集表示, 这就是CT
水滴融合也是运用水平集和SDF
Fractals(Implicit)分形#
某个物体或图形, 其中一个部分和整体相似. 这种情况在渲染容易出现走样, 因为变化频率太高
11 Geometry 02#
显示几何#
PointCloud点云#
只要点够多, 视觉上就足够像面
3D扫面得到的输出就是点云 点云一般后面会用于转换成polygon mesh
Polygon Mesh 多边形面#
ojb 文件
一个text file, 包含vertices, normals, texture(vt, uv坐标) 和连接关系(f)的信息
曲面Curves#
Bezier Curves 贝塞尔曲线
由起点, 终点, 控制点来绘制的曲线
设起点, 终点, 控制点为 b0, b1, b2, 假设b0到b1视为0到1, 设置参数t, t的位置增加点b01, 同理在b1b2上设置t点b11,连接两个点, 增加t点b02, b0, b02, b2构筑曲线
每两个点找时间t, 相当于两个点做线性插值, 产生新的点, 一直循环下去直到得到最后一个点
b01(t) = (1-t)b0+tb1, t=0时,是b0, t=1是, 是b1
这是一个多项式, 设定n 个控制点, 可以得到n阶的贝塞尔曲线, 给任意时间点t, 它都是之前给定的控制点的线性组合, 组合系数就是个多项式, 这个多项式就叫伯恩斯坦多项式
(n,i)是组合数, 表示从n个像素中获取i个元素, 如果n =2, i= 0,1,2.
如果做3次贝塞尔曲线, 也就是控制点有4个, b’(0) = 3(b1-b0), 这里想到于t=0, 代入3次贝塞尔曲线的公式里, 得到的最后结果
仿射变换: 在向量空间进行一个线性变换+平移
特性: 对这些控制点做仿射变换,得到的曲线会和之前的一样. 只对仿射变换成立, 比如投影就不成立
凸包性质: 任何一个贝塞尔曲线, 上面的任何一个点在任何时间体t, 一定在所形成的凸包内
piecewise bezider curves 逐段贝塞尔曲线#
多个控制点无法表达复杂的曲线
每次用很少的控制点制作曲线, 再把曲线合并. 每个曲线用4个控制点控制
photoshop的钢笔工具就是例子
如何保证曲线连接处是顺滑的, 要保证两个控制杆等距且共线
连续性 continuity#
给定两个贝塞尔曲线, 这两个曲线相连的那个点叫做C0 continuity, 即第一段的终点等于第二段的起点
切线连续 第一段终点等于第二段起点, 且周边两点距离这个点的距离相等且共线, 方向相反, 这就叫C1 continuity.
还有曲率连续
Splines 样条#
由一系列控制点控制的曲线, 满足一定连续性. 即可控的曲线
B splines Basis splines#
比贝塞尔曲线能力更强, 具有局部性, 修改一个控制点不会影响到曲线其他地方
更衍生的还有NURBS
surfaces 曲面#
在两个方向上应用贝塞尔曲线
案例中, 设置4x4个控制点, 连接每行的控制点,得到4个曲线, 这些曲线在不同时间t, 会在不同位置, 把在同一时间t的4个点作为控制点构造贝塞尔曲线. 由多个t的结果构成平面
Evaluating surface position#
找到贝塞尔曲面的任意点
设定(u,v)两个值, u 代表 t, 通过u构成的纵向贝塞尔曲线, v代表在这个纵向的位置
Mesh Operations#
Mesh subdivision网格细分
Mesh simplification网格简化
Mesh regularization网格正规化
得到的三角形不会特别尖, 会接近正三角形
12 Geometry 03#
loop subdivision#
引入更多三角形, 再对这些三角形进行位移
连接三角形的中点来增加三角形
区分新旧顶点
对新点的位置, 是根据旧点的位置进行加权平均
对旧的顶点,
n: 顶点连接的边的数量
u: 考虑到顶底的度, 和这个度有关的数
权重说明: 如果一个顶点连了多个三角形,则可以通过其他三角形来更新自己, 如果只连了少量三角形, 则它自身更重要
Catmull-Clark Subdivision (General Mesh)#
定义 四边形和非四边形面
定义 奇异点, 度不为4的点
引入更多的点: 每一条边取中点, 每个面取中点, 连接这些中点
细分后, 非四边形面消失, 这些非四边形面会变成奇异点
细分后点的位移
新的点(面的中点) f=(v1+v2+v3+v4)/4
新的点(边的中点) e=(v1+v2+f1+f2)/4
老的点 v=(f1+f2+f3+f4+2(m1+m2+m3+m4)+4p)/16
loop 只能用作三角形面, Catmull-Clark可以用作不同面
网格简化#
现在还没有做出LOD过渡的技术(类似于之前光栅化提到的mipmap双线性插值)#
其中一种简化方法, 边坍缩Edge Collapsing
坍缩哪些点 Quadirc Error Metrics
最小化二次误差, 二次误差 求这个点到原本几个面的距离平方和, 新的位置使得这个点和相关联的面的距离的平方和达到最小
如何选择坍缩的边: 从二次误差最小的边开始坍缩, 取完最小进行坍缩后, 对受到影响的边进行更新
优先队列是这个方法 允许取最小且动态更新各个点的数据
这不是全局最优性质的算法, 这是个局部最优解
Shadow#
光栅化做阴影不好做, 一般用Shadow Mapping, 因为光栅化是计算局部像素的, 如果光栅化时考虑阴影, 有遮挡关系的情况下像素会判定为接受不到光, 直接渲染成黑色
shadowmapping会有走样现象
shadowmapping key idea
如果一个点不在阴影, 代表这个点相机和光都能看到. 利用这点来制作shadowmapping
经典shadowmapping只能处理点光源, 案例讲解的是点光源的情况
硬阴影, 非0即1
操作:
- 从光源看场景, 虚拟一个摄像机在光源的位置和方向, 进行光栅化, 就可以判断光源看到了什么. 不做着色, 但记录点的深度信息
- 从摄像机看场景, 看到的点投影回光源的相机, 查看这个点记录的深度, 投影深度和记录深度一致, 就代表这个点是可见的
- 如果投影的深度和光源相机记录的深度不同, 代表这个点被遮挡, 在阴影内
走样: 浮点数判断相等很困难(数值精度) 办法: 不判相等判大小(仍然解决不掉问题) 引入Bias, 判断大小的同时加入一个偏差值来进行判定(仍然不能解决问题)
分辨率问题: Shadowmap本身有分辨率, 如果阴影分辨率低于场景, 会有锯齿
shadowmaps问题
- hard shadows(point lights only) 2.Quality depends on shadow map resolution
- involves equality comparison of floating point depth values means issues of scale, bias, tolerance
Hard shadows vs soft shadows
软阴影来源 半影 可以部分看到光源的区域 本影 完全看不到光源
日食的半影和本影区域 太阳可以视作多个点光源的集合
有软阴影代表光源有一定的大小