计算机图形学-06:几何表示
纹理作为数据
纹理的点查询与范围查询依赖不同过滤方式。纹理最初常被理解为一张颜色图片,但在现代 GPU 中,它更接近一块支持快速寻址和过滤的数据。给定一个点,可以进行点查询;给定一个区域,可以进行近似的范围查询。片元着色器如何解释这块数据,决定了它最终表示颜色、法线、粗糙度、可见性,还是空间中的密度。
这个观点解释了纹理应用为何能超出漫反射颜色。若纹理保存的是环境在各个方向上的光照,查询结果就是环境贴图;若保存的是高度变化,就可以扰动法线或移动顶点;若保存的是三维空间中每一点的密度,就可以参与体渲染。纹理仍然是同一类快速查询结构,改变的是数据的含义。
环境贴图
站在房间中向四周看,每一个方向都有光进入眼睛。这些光可能直接来自灯具,也可能是墙面、地面和物体反射来的光。把每个方向上的光照记录下来,就得到一张环境贴图 Environment Map。它可以用来近似环境对光滑物体的镜面反射,也可以在预滤波后近似环境漫反射照明。
环境贴图的一个常见获取方法,是在场景中放置一个高度光滑的金属球。球面反射出了周围完整环境,再像展开地球仪一样把球面记录展开,就能建立方向到光照的对应关系。也可以用鱼眼镜头拍摄大范围视野,或把多张照片拼成全景图。无论采用哪种方式,最终索引的都是方向,而不是一个有真实深度的物体。

球状贴图先将方向映射到球面,再用二维参数存储。常见经纬展开在两极附近会拉伸,同样面积的纹理块对应不同立体角,方向采样密度因而不均匀。立方体贴图 Cube Map 把环境投影到包围原点的六个正方形面上。给定方向向量,先找绝对值最大的分量确定落在哪个面,再用另外两个分量除以该最大分量求面内坐标。以右面为例,它记录满足 且 的方向;六个面各自是一张二维纹理。
立方体贴图避免了球面贴图的极点压缩,但查询时需要判断方向属于哪个面,并处理相邻面之间的接缝。选择最大绝对分量作为面法线时,方向与所选面法线的夹角不超过
因此采样密度变化是有界的。两种贴图本质相同,都是在方向域中查一张预先记录的光照表。
环境贴图默认环境位于无限远处。物体在场景中平移时,同一方向上的光照被视为不变,反射内容不会因观察点移动产生视差。房间很小、墙面很近或光源距离有限时,这个假设会失效;此时只记录方向不足以描述环境,必须恢复位置或深度信息。

四个反射球记录了室内结构、灯光和室外天空。球面点对应一个反射方向,获取后还需按反射几何转换成方向索引,不能直接把球面像素当作均匀的方向采样。
法线与高度
纹理不必只存颜色。把纹理解释成表面相对于基准面的高度,就能在不增加三角形的情况下制造细小的明暗起伏。真正发生变化的是着色所使用的法线,几何顶点仍在原来的位置,因此这种方法必须与位移贴图区分。
一维推导。
先考虑平面上的一条起伏曲线。设高度函数为 ,沿参数 前进一个单位时,高度变化近似为 。曲线的切向量可以写成
法线应当与切线垂直。把切线旋转 ,得到未归一化的法线
着色前还必须归一化。实际纹理中通常使用相邻样本差分近似导数,并乘一个缩放因子控制凹凸强度。高度变化越快,法线偏转越大;高度为常数的区域法线仍接近基准法线。
二维推导。
对高度场 ,两个参数方向的局部切向量可写成
它们的叉积为
因此切线空间中的扰动法线为
这个公式假设局部基准表面是 ,参数单位与两个切线方向一致。一般曲面还要考虑原表面的参数偏导和尺度,不能把纹理坐标的单位变化直接当成世界空间距离。
切线空间。
在表面点建立由切线 、副切线 和几何法线 构成的局部坐标系,通常写成 TBN 矩阵。先在该坐标系中计算高度变化带来的扰动,再将法线变回世界空间:
凹凸贴图 Bump Mapping 在片元着色器中保存高度,用相邻纹素差分求导,再扰动着色法线。它能改变明暗,却不会改变物体外轮廓,也不会产生与真实起伏相符的自遮挡阴影。
法线贴图 Normal Mapping 直接把切线空间单位法线编码进 RGB 通道,通常把 线性映射到 。它省去了运行时从高度差分求法线的步骤。两者都只改变着色法线,区别在于纹理保存的是高度还是已经算好的法线。

图中左侧只改变法线,球面的明暗出现凹凸,但外轮廓仍是平滑圆形,地面投影的阴影边缘也没有真实起伏。右侧位移贴图改变了几何位置,轮廓和阴影边缘随之起伏。这个对比是判断两类贴图的最快方法:只改法线,轮廓不变;真的移动几何,轮廓与遮挡关系才会变。
位移贴图
位移贴图 Displacement Mapping 使用与凹凸贴图相同的高度数据,但在顶点处理或曲面细分阶段真实移动顶点。沿几何法线移动时可写作
其中 是高度尺度。由于位移施加在顶点上,网格必须能采样高度场的变化。如果两个相邻顶点间距大于高度纹理的特征尺度,三角形内部没有足够自由度表达起伏,结果会丢失细节或产生轮廓锯齿。这与采样极限中讨论的欠采样是同一个问题。
最直接的解决办法是预先使用很密的网格,但存储和处理成本会很高。更灵活的办法是动态曲面细分:先提交较粗的网格,在位移过程中判断哪些三角形需要更细,再把这些三角形拆开后继续处理。DirectX 中的 dynamic tessellation 就属于这种按需增加几何采样的思路。
纹理应用
三维纹理与程序纹理。 三维纹理在空间中处处有定义。物体被剖开后,内部仍能查询到材质值,因此它与只贴在表面的二维纹理不同。三维纹理适合表示大理石、木材内部结构和体数据。
程序化纹理不预先存储整张图片,而是用定义在空间中的函数计算任意点的值。Perlin noise 是常见的噪声函数,可以在空间中生成连续变化的随机样式。对噪声进行阈值、缩放、叠加和频率调整,就能得到大理石裂缝、木纹、地形起伏等效果。这样做的优点是参数少、可按任意分辨率生成;代价是每次查询都要执行函数计算,并且高频噪声同样需要按像素 footprint 过滤。

球面和花瓶的形状不同,却可以查询同一个三维函数得到连续深浅纹理。查询变量是空间位置,因此模型被切开时内部也有定义,不需要为每个新表面制作二维 UV 图。

中间图把环境遮蔽保存成灰度纹理,凹陷、褶皱和口部附近更暗;与左侧基础着色组合后,右侧增加了这些局部明暗差异。它近似环境的可见程度,不能代替随光源变化的完整阴影。

左侧小立方体表示对体内空间分块采样,右侧头部数据把不同密度转换成颜色和透明程度。查询不再只发生在外表面,沿视线还要经过多个体积位置并累积它们的作用。
预计算着色。
纹理还可以保存预先计算的着色结果。环境光遮蔽 Ambient Occlusion 用一个可见性或遮蔽因子描述局部凹陷处有多少环境光能够到达。可见处可记为1,被完全遮挡处可记为0,中间情况用连续值表示。若把它预先写入纹理,运行时只需把着色结果与该因子相乘,就能用离线计算换取实时性能。
这种做法的本质是把纹理当成快速查询的缓存,而不是把纹理限制为颜色。它不能自动适应所有光源、材质和几何变化:预计算假设发生变化后,旧纹理就不再严格正确。
体数据。
医学 CT、MRI 等扫描可以为三维空间中的每一点提供密度或组织信息。把这些值存成三维纹理,就能在空间中查询密度并进行体渲染。体渲染处理的是体内部的参与介质或密度场,不再只是表面上的一次着色;之后若要提取几何边界,可以从密度场中选择等值面。
几何难在哪
几何表示必须服务于要执行的查询。实时渲染关心表面采样与光线求交,物理模拟关心内外判定、距离和碰撞,建模系统关心局部连续性与可编辑性,流体动画还要处理拓扑断裂、合并和自由表面。
真实几何在不同尺度上都可能复杂。车身近看仍然光滑,齿轮与叶片包含大量部件;布料是纤维、纱、线和织物组成的层级结构;水滴会因表面张力形成薄膜并断裂;城市包含建筑、窗户、树叶和草;毛发需要大量细曲线,细胞和病毒在更小尺度仍然有复杂结构。这带来两个相互独立的问题:数据占多少存储,以及渲染/模拟要处理多少图元。
一个常用的工程策略是细节层次 Level of Detail, LOD。远处物体在屏幕上只占很少像素,没有必要保留室内结构和微小部件,可以换成更粗的模型;物体靠近时再使用更高分辨率的模型。直接切换会产生跳变,因此常用几何渐变(geomorph)让相邻层次在一段距离内平滑过渡。表示方式应随任务和观察尺度变化,不能期待一种格式同时让所有查询都便宜。
固定的经典模型可以把表示方式和算法差异分开。Utah teapot、Stanford bunny/dragon 和 Cornell Box 都是图形学中反复使用的基准:茶壶适合观察曲面和反射,兔子与龙适合测试扫描网格和复杂拓扑,Cornell Box 适合比较全局光照。换算法时复用同一模型,才能把差异归因于渲染或表示方法,而不是输入几何改变。
隐式与显式
拓扑 Topology 描述顶点、边、面之间的连接关系以及孔洞和连通分支。移动顶点可以保持拓扑不变,切开、合并或打通表面则可能改变拓扑。
几何表示通常分为隐式和显式两类。隐式表示通过关系或标量场定义哪些点属于表面;显式表示直接列出表面元素,或给出从参数域到空间的映射。两种表示可以产生相同外观,但程序能高效回答的问题不同。

隐式表示通常便于回答“一个点在内部还是外部”,显式表示通常便于回答“表面点在哪里”。参数曲面虽然写成函数,也属于显式表示:遍历参数域就能枚举表面点。只有额外认出它等价于某个简单隐式方程时,内外测试才会变得容易。
图的左侧列出隐式与显式的常见定义方式,右侧的点集、面片和体素展示不同数据组织。类型取决于程序怎样定义和查询形体,单看渲染外观无法判断它是函数、网格还是离散标量场。
代数曲面
代数曲面用三维多项式的零集定义表面:
例如,中心在原点、半径为 的球面为
可以约定 表示内部、 表示表面、 表示外部。一次函数求值就能完成内外判定。球、平面、椭球、圆柱、圆锥、双曲面和抛物面等低次曲面都有紧凑的闭式表达。
复杂形状的公式会迅速失去可读性。例如圆环面的隐式方程为
其中 是主半径、 是管半径。扫描得到的奶牛或自然物体通常很难写成闭式多项式,这时网格、参数片或离散场更实用。
代数曲面与射线求交也有直接联系。把射线 代入 ,就得到关于 的一元方程;其实根就是交点。二次曲面可直接使用求根公式,次数越高,求根与数值稳定性越困难。
参数曲面
参数曲面 Parametric Surface 用二维参数域到三维空间的映射定义显式表面:
给定 就能直接得到表面点,均匀采样参数域也能直接生成规则网格,参数本身还可以作为纹理坐标。标准例子是马鞍面
它沿两个参数方向的曲率符号相反;同一个圆环面既可以写成四次隐式方程,也可以写成
圆环面这一写法中两个角参数均取 ;使用归一化参数时,要把角度写成 。
对参数求偏导可以得到切线
并由
求单位法线。若两个偏导共线或其中一个为零,参数化发生退化,例如球面极点;此时需要另取极限法线或用多块参数片覆盖。
实体构造
构造实体几何 Constructive Solid Geometry, CSG 用基本实体通过布尔集合运算构造复杂模型。对两个实体 ,并集保留至少属于一个实体的体元,交集保留同时属于两个实体的体元,差集 保留在 内但在 外的体元:

CSG 通常组织为表达式树:叶节点是球、圆柱、立方体等基元,内部节点是并、交、差。修改叶节点的位置和尺寸,就能重新求值整个模型,因此很适合 CAD 和机械零件。布尔结果仍通过“一个点属于哪个集合”来描述,没有列举表面点,所以属于隐式表示。
图中上半部分依次展示圆柱与球的并集、交集和差集;下半部分把一个块体与三个圆柱组织成表达式树,再从块体中挖出交叉孔。树的结构保留了建模步骤,任意叶节点参数改变后,根节点可以重新计算。
相切、共面或仅在一点接触的组合可能产生退化或非流形边界。流形表面在一般点附近应像一小块二维面片;一条边通常至多属于两个面,一个顶点周围的面应形成单一闭环。布尔运算并不自动保证这些条件。
有符号距离场
有符号距离函数 Signed Distance Function, SDF 为每个空间点记录到表面 的最短欧氏距离,并用符号区分内外:
表面就是零等值面 。球的场为 ;过点 、单位法线为 的平面场为 。这些场可以作为程序化建模的基本零件。
在约定内部为负、外部为正时,布尔运算的符号可以用极值表达:
这些公式能正确给出布尔结果的符号与零表面,但极值在交界处通常产生折痕,而且组合场的绝对值不一定仍是真实新表面的最短距离。因此,复合场可以用于内外判断或保守步进,不能无条件当作严格欧氏 SDF。
梯度 Gradient 把三个坐标方向上的变化率组成向量,指向函数增长最快的方向,也垂直于等值面。在可微区域,真实欧氏距离场沿法线方向每前进一个单位,距离也变化一个单位,因此满足 Eikonal 方程
内部为负时,梯度指向外部,法线可由
得到。尖角、多个最近表面点的中轴处可能不可微,不能把梯度长度为1写成无条件的全局结论。数值实现通常用中心差分:
太小会放大浮点误差和高频噪声,太大则会跨过高曲率区域,法线变得迟钝。
距离融合
两个标量场可以逐点线性融合:
恢复几何时取 。先把两张黑白边界图逐像素平均,只会得到灰色叠加,边界位置不动;先转成有符号距离场再混合,零等值面才会在两条边界之间移动。

一维情形最清楚。若两条边界位于 和 ,其场为 、,则
图的上排直接平均黑白边界,只得到中间灰色带,原轮廓没有移动;下排先把边界转成带有负、零、正等值线的距离场,再混合两个场,零等值线才沿两条原边界之间移动。
因此零等值面在
处。这个一维例子说明线性场融合如何表示两条边界之间的连续移动。对相互分离的完整三维实体,简单的 并不保证得到直观的“两个形体之间长出细颈”:在端点参数处它只包含对应的一侧形体,中间还可能出现收缩或消失。更一般的 distance blending/soft union 需要额外选择标量场和组合算子。

这张圆形与方形的图展示的是更一般的距离场融合/soft union 效果:两个实体从分离、接触到形成细颈并合并,零等值面随所选的标量场组合发生拓扑变化。它不应被解释成上面一维线性边界公式在两个完整实体上的直接结论。
平滑最小值 Smooth-Min。 smooth-min 是在硬 附近用连续修正制造圆角的专门算子,可能填平窄缝;它也不等同于线性场插值。
一种常用的多项式平滑最小值写法是
其中 控制过渡宽度。 时修正项为0,算法退化为普通 ;在交界带内,修正项把场压低,使零等值面形成圆角。它属于平滑布尔/软融合算子,不应和上面的线性场插值当作同一方法。
球体追踪
有了距离场以后,可以不先生成三角网格,而是直接沿射线步进求交。设射线为
先假设起点位于物体外部,当前位置的距离 。严格 SDF 以该点为球心、以 为半径的球内部没有表面,因此可以安全地沿射线前进这么远:
若射线从物体内部出发,可用 沿正方向追踪穿出位置,不能把负场值直接作为前进步长。距离绝对值小于容差时可认为命中,超过射线范围时认为无交;最大步数只能表示“没有在预算内收敛”,不能单独证明无交。掠射角附近距离下降很慢,步长会连续缩小,需要同时设置最大步数和命中容差。
若场只是混合场或保守距离下界,已知函数 Lipschitz 上界为 时应使用 作为保守步长,不能无条件把任意场值当作真实距离。球体追踪直接对程序化场求值,可以处理布尔组合和融合形体;代价是每一步都要重新计算场。
等值面
当隐式函数不能方便地写成闭式表达,可以把它采样到规则网格中。满足
的点集叫等值面(二维时是等值线), 时就是零等值面。医学 CT/MRI 可以把组织密度存成三维网格,再按不同阈值抽取不同组织表面;流体模拟也常用水平集表示液体与空气的边界。

Marching Cubes 把隐式场转换为显式三角网格。对每个体素立方体,先检查8个顶点相对阈值的符号,共有 种编码;再用边两端的标量值线性插值估计等值面穿过边的位置;最后按拓扑查找表连接成三角形。部分构型存在连接歧义,需要统一的面判定规则或四面体分解,否则相邻体素之间可能出现裂缝。顶点值恰好等于阈值时也必须规定一致的归类方法。
图中规则网格左侧示例值约为 ,右侧示例值约为 ;黑色零等值线从异号顶点之间穿过。它不是直接把网格顶点连起来,而是先在交叉边上按两端数值做线性插值。把阈值改成其他常数,就会从同一份标量数据中抽取另一层等值面。
网格分辨率限制了可表达的最小结构。薄壁和细管若小于体素尺度,抽取后可能断裂或消失;三线性插值重建的场通常也不再是严格距离场。
表示转换
实际管线很少只使用一种表示。雕刻和布尔建模可以在 CSG/SDF 中完成,进入渲染前再用 Marching Cubes 或自适应剖分转换成三角网格;需要避免网格化时,也可以在求交阶段直接做球体追踪。显式网格转隐式场则需要在窄带内计算到表面的距离并判定符号,封闭网格的符号通常可由射线奇偶计数或绕数判定,常要配合空间加速结构。扫描点云通常先重建成流形网格,之后才能进行参数化、平滑着色和薄壳模拟。
分形
分形 Fractal 通过递归规则或噪声函数,在多个观察尺度上生成相似的细节。雪花的每条边上继续长出更小的分叉,Romanesco 的小花枝像整体的缩小版本,这些都是自相似的直观例子。自然界的分形会在有限尺度终止,不会无限重复到任意小的物理尺度。
分形可以用确定性递归,也可以用多个频率的噪声叠加来生成。高频细节带来采样困难:一个像素覆盖大量细小结构时,点采样会随视线和像素位置剧烈变化,表现为闪烁和噪声。应按像素 footprint 预过滤高频层,或在远处切换到低频版本。

