此为个人学习笔记,总结内容来源于网络各个平台,如有错误欢迎指摘
几何表示
基本表示方法
本节附加资料:
- (2) Coding Adventure: Ray Marching - YouTube
- (57条消息) FBX格式和obj格式的区别_井冈山市监人的博客-CSDN博客_fbx是什么文件格式
- (57条消息) fbx格式 - CSDN
- (57条消息) obj文件格式详解及示例_秦伟H的博客-CSDN博客_obj格式
几何形体是计算机图形学当中十分重要的一部分内容,无论是人物,风景,建筑,都离不开几何,如何表示好各种各样的模型是几何部分的主要研究内容之一
从微观结构到高楼大厦,都算作几何的范畴,如此广泛的定义显然不利于我们研究它
于是有了隐式曲面与显式曲面的大分类
隐式 Implicit与显式 Explicit关于表示几何上的区别
所谓隐式表示指的是并不会告诉你任何点的信息,只会告诉你该曲面上所有点满足的关系
而显式表示是与隐式表示相对应的,即给出所有的点,或者可以通过映射关系直接得到这些点
隐式曲面 Implicit Surface的特点
隐式的表示方法是给出点的满足关系,将空间中所有的点根据这个关系筛选出来就可以得到需要的几何形状,例如图中黑色表示 f = 0 f=0 f=0,满足这个关系的点就是需要连起来的点
例如 x 2 + y 2 + z 2 = 1 x^2+y^2+z^2=1 x2+y2+z2=1表示一个半径为 1 1 1的球体,但一般会让等式的右侧变为 0 0 0,即写作 f ( x , y , z ) = x 2 + y 2 + z 2 − 1 f(x,y,z)=x^2+y^2+z^2-1 f(x,y,z)=x2+y2+z2−1的形式
对于隐式方程来说因为没有给出任何点的信息,因此如何采样到曲面上具体的点是一个很难的问题,如下图这样一个例子
如果不是给出了图示,很难想到这是一个圆环的形状
但隐式的表示方法带来的好处是可以轻易判断一个点与曲面的关系,只需要带入方程计算一下就可以得到它们之间的关系
显式曲面 Explicit Surface的特点
显式表示的曲面上的点是可以直接获取到的,直接给出或者通过一种映射关系获取
例如图中的 ( u , v ) → ( x , y , z ) (u,v)\rightarrow(x,y,z) (u,v)→(x,y,z)这样的一种映射关系
相对于隐式曲面来说,显式曲面更容易被塑造出它的实际形状
更重要可以很轻易地采样到所有的点,只需要根据映射关系遍历所有的 ( u , v ) (u,v) (u,v)就能得到所有的 ( x , y , z ) (x,y,z) (x,y,z)
你或许还是很疑惑这样到底容易在了哪里,把它想象成”刻舟求剑“而隐式想象成”大海捞针“或许有些帮助,前者通过把船开回原地点就能找到位置,但后者只能不断尝试所有的地方,这段描述有些不妥,请看最后的举例说明
但用显式的方式描述几何,会让点与曲面的关系变得不易判断
小结
如果你还是很迷惑的话请听这样一个例子:
假如你的队伍中出了叛徒,那么
告诉你叛徒都是浓眉大眼的,这是隐式表达
- 如果张三不是浓眉大眼的,那么他就不是叛徒,而李四是那么李四就是叛徒,鉴别一个人是不是叛徒是很容易的
- 但你要找出所有的叛徒,尤其是叛徒人数不确定的情况下,你就需要仔细的对所有人都筛查一遍,如果你的队伍人数多到爆炸,那么你也会爆炸
提供给你叛徒名单,这是显式表达
- 你很容易就找到了确定的叛徒,这是一一对应的
- 但这份叛徒名单只是你队伍里的,其他队伍里的叛徒需要其他的名单,你说不请他们之间有什么联系,所以对任意一个人是不是叛徒就很难判断
隐式曲面具体实例
代数曲面 Algebraic Surfaces
使用代数表达式定义的曲面是十分符合隐式表达特点的,球体的定义式比较容易看出,但圆环、心形甚至是复杂的奶牛,他们的表达式不易联想出形状,也不容易求出
体素构造表示 Constructive Solid Geometry (CSG)
中文的翻译是如此的奇怪…
这是一种通过布尔运算将简单的基本体素拼合成复杂实体的描述方法,应用如布尔运算
通过CSG的方法可以一定程度上缓解隐式曲面难以表现复杂形体的困境,许多建模软件中都包含这类操作
符号距离函数 Signed Distance Functions
和布尔函数不同的是,距离函数会混合这两个物体的边界,体现出一种交融的效果
符号距离函数来说本质上就是一种定义距离的函数,算出空间中任意一点距离所有几何物体的距离,对这些距离做出一系列的操作(图中是取最小值,也可取最大值等等)
如果这个点在物体内,那么这个距离是负数;如果在物体外,那么是正数
在这个图中给出了一个示例:
第一列的A与B中的阴影部分为一个图形,而blend是他们的一个混合态,简单的叠加会得三分的效果
而第二列分别对应第一列中A于B的SDF函数,以他们的边界为0线,或者说只有SDF为0,也就是在边界的情况才绘制这一点,且内部为负外部为正
那么它们的混合态要去绘制时需要SDF为0的点。而SDF的叠加导致了正负抵消,0线出在了中间位置
混合两个SDF可以得到许多的性质,而对于这样的效果只需要合理定义空间中任意一点的SDF即可得到
这一步是如何做到的将在本节最后介绍
水平集 Level Set
水平集的方法其实与SDF很像(像是SDF的一种特殊形式),也是找出函数值为0的地方作为曲线,但不像SDF会空间中的每一个点有一种严格的数学定义,而是对空间用一个个格子去近似一个函数
对该面内的每一个点利用已经定义好的格子值进行双线性插值,找出值为0的点作为目标曲线
该方法的好处是对于SDF,我们可以更加显示的区空间曲线的形状
该方法广泛的运用在医学成像和物理模拟之中
分形 Fractals
分形就是研究无限复杂具备自相似结构的几何学,是大自然复杂表面下的内在数学秩序
一个数学意义上分形的生成是基于一个不断迭代的方程式,即一种基于递归的反馈系统
显式曲面具体实例
点云 Point Cloud
由大量的点直接表示出几何体的形状
可以表示出任意的形状,常作为物体扫描后得到的原始数据,之后将会被转化为多边形网格
多边形网格 Polygon Mesh
如果你接触过建模软件,你一定操纵过多边形网格,这是一种在图形学中被大量使用的东西
通过定义各个多边形面的顶点以及顶点之间的连接关系就可以得到许许多多的三角形面或是四边形面,再通过这些面来近似表现出我们想要的模型效果
拓展内容
SDF的基础使用
符号距离 Signed Distance
首先我们需要知道一些基础概念:
计算两点间的距离公式想必大家都不陌生,即图中的
float length(float2 v)
{
return sqrt(v.x * v.x + v.y * v.y);
}
这里的 v = C − P v = C-P v=C−P是一个向量,你可以将它的 v . x v.x v.x和 v . y v.y v.y理解为以 C P CP CP为斜边的直角三角形的长和高
而若计算的是点到一个圆的距离的话
float signedDstToCirlce(float2 p, float2 centre, float radius)
{
return length(centre - p) - radius;
}
只需要求出点到圆心的直线距离后再减去圆的半径就好
不过若你想计算的是点到一个矩形的距离的话,有些许复杂
float signedDstToBox(float2 p, float2 centre, float2 size)
{
float2 offset = abs(centre - p) - size;
float unsignedDST = length(max(offset, 0));
float dstInsideBox = max(min(offset, 0));
return unsignedDst + dstInsideBox;
}
我不太能理解它的意义,尤其是其中的max函数只有一个参数,在这里给出我一种个人的见解:
float signedDstToBox(float2 p, float2 centre, float2 size)
{
// 仿照计算点到圆边界的方法计算
float2 offset = abs(centre - p) - size;
// 参照图中注释转写为if-else结构
if(offset >= 0)
{
signedDst = length(offset)
}
else
{
signedDst = -length(offset)
}
return signedDst;
}
布尔运算
交集
现在我们已经知道了什么是符号距离:空间中任意一点到任意一物体的最短距离
在这样的一个场景中,显示有一个立方体与一个球体,图中的代码求出所有点的符号距离后,返回出一个最小值,若这个最小值为0则表明该点位于其中一个物体的表面,则进行顶点着色渲染出它
代码逻辑为:
for(every points in scene)
{
if(signedDstToScene(p) == 0)
{
paint(p)
}
}
这一部分并没有演示出两者重叠的情况,但可简单举例想出这一点:这两个部分重叠的内部不存在被渲染的点,原因是min会给出一个负数值
并集
如果我们将这一函数改写为返回其中的最大值,那么我们就创造出了两个图形的并集
仍然是返回值为0时才进行渲染,而max意味着只有当其中一个值为负数,另一个值为0的时候才会让这个函数返回0,这就对应着重叠的部分
差集
在max的情况下反转其中一个参数就得到了差集
选取两个物体重叠的一点距离即可分析得出原因
课程中类似水滴融合的SDF
布尔运算是对SDF的一种简单运用,因为它对于每个符号距离只有基本的线性运算
图中函数适用于替换我们之前使用的min的,在使用原本的min函数情况下,计算出红色与蓝色两个函数图形的最小值为图中的白色部分
而它可以将min平滑为这般效果
现在就得到了课程中令人惊艳的水滴融合效果
虽然我们并不清楚改进后的min的原理,但它在原本min的基础上减去了一个数,这就让原本一些不该被渲染的点的符号距离变为了0,从而发生了形变
FBX与OBJ格式对比
这两种格式都是目前主流的模型格式,课程中对OBJ文件进行了讲解,此处拓展为两种格式的对比
FBX
FBX文件分为两种方式从建模软件中导出,一种是二进制文件另一种是ASCII码保存
以一个正方体模型为例:
- Vertices 的24个值是三维数据集的8个顶点(3个值代表一个顶点三维坐标)
- PolygonVertexIndex 下的36个值是顶点索引(mesh中点的索引)
- Edges 指的是所有三角形的边,以索引的方式给出(36条边中只表示出不重复的18个)
- Normals 的108是12个三角形的每个三角形角的36个法线(3个值代表一个法向量)
- UV 下的24是12个纹理坐标(2个值代表一个纹理坐标对)
- UVIndex 的36是三维数据集的36个三角形角的纹理坐标索引(引用 UV 的值)
Vertices中数据不难理解,就是这些数据三个一组对应X、Y、Z构成一个三维坐标,所以可以得到正方体的8个顶点坐标。
PolygonVertexIndex 看到这个数据中的大家都会有疑问:为什么顶点索引数据会有负数?
因为模型为了区分模型网格是三角面还是四边面,如果数据每隔三个为负数则为三角面,每隔四个为四边面。
如何将负数的索引值转成有效索引数据呢?
假如n为负数索引值,m = |n|-1 。m为计算后的正确索引值。
因为normal和uv所计算的值都是对应的点的值:点法线是对应的点的法线,uv是点映射在平面上的坐标值,他们根本都是点的属性。
而 PolygonVertexIndex、Normals和UVIndex的数量都是36,可以猜测Normals 和 UV 是在每个PolygonVertexIndex所映射的点所相应 normal 或者 UV 的值的集合。
OBJ
以文本形式存储的包括顶点、法线、纹理坐标和它们的组合关系
以另一个正方体为例:
- v 代表了每一个顶点,后面的数字为它的坐标,共8个
- vt 代表了这些顶点的纹理坐标,共12个,12个三角形共36个顶点,每个顶点被用到3次
- vn 代表了顶点法线,至多8个,顶点法线不是一个模型必须有的内容,如果你对面法线和顶点法线的概念模糊,请查阅着色一节中的附加资料切线空间(Tangent Space)完全解析 - 知乎 (zhihu.com)中关于这一点的解释,由此关于课上提到的6个不同朝向于是有6个法线的解释有待商榷
- f 为它们的组合关系,代表一个面,三个组分别表示一个完整的顶点,构成一个三角形,其中的数字为索引,以1开始
- 第一位表示顶点索引
- 第二位表示顶点纹理坐标索引
- 第三位表示法线索引
你可能注意到了这些数量似乎对不上,图中的数据貌似会多出几个,这是由于建模软件的精度所导致的问题
区别
相同点
- FBX格式和OBJ格式都是三维通用模型格式,可以用在目前几乎所有主流的三维软件中
- FBX文件和OBJ都支持三个点以上的面,这一点很有用。很多其它的模型文件格式只支持三个点的面,所以导入Maya的模型经常被三角化了,这对于我们对模型进行再加工甚为不利
不同点
FBX:
- FBX格式是一种3D通用模型文件。包含动画、材质特性、贴图、骨骼动画、灯光、摄像机等信息
- FBX格式支持多边形(Polygons)、曲线(Curves)、表面(Surfaces)、点组材质(Point Group Materials)
- FBX格式支持法线和贴图坐标。贴图以及坐标信息都可以存入FBX文件中,文件导入后不需要手动指认贴图以及调整贴图坐标
OBJ:
- OBJ文件是一种3D模型文件,不包含动画、材质特性、贴图路径、动力学、粒子等信息
- OBJ文件主要支持多边形(Polygons)模型。虽然也支持曲线(Curves)、表面(Surfaces)、点组材质(Point Group Materials),但Maya导出的OBJ文件并不包括这些信息
再加工甚为不利
不同点
FBX:
- FBX格式是一种3D通用模型文件。包含动画、材质特性、贴图、骨骼动画、灯光、摄像机等信息
- FBX格式支持多边形(Polygons)、曲线(Curves)、表面(Surfaces)、点组材质(Point Group Materials)
- FBX格式支持法线和贴图坐标。贴图以及坐标信息都可以存入FBX文件中,文件导入后不需要手动指认贴图以及调整贴图坐标
OBJ:
- OBJ文件是一种3D模型文件,不包含动画、材质特性、贴图路径、动力学、粒子等信息
- OBJ文件主要支持多边形(Polygons)模型。虽然也支持曲线(Curves)、表面(Surfaces)、点组材质(Point Group Materials),但Maya导出的OBJ文件并不包括这些信息
- OBJ文件支持法线和贴图坐标。OBJ只能保存贴图坐标信息,贴图需要手动重新指认,但不需要再调整贴图坐标