纹理展开(UV Unwrapping)是3D资产制作流程中连接几何与材质的关键步骤。它把三维表面映射到二维平面,使得后续绘制的纹理能够准确贴回模型。从算法角度看,UV展开本质上是一个带约束的几何参数化问题:对于给定的三角网格,需要为每个顶点找到二维坐标,使得由三维三角形到二维三角形的映射尽可能保持形状、角度或面积特性。如果展开不当,就会出现纹理拉伸、棋盘格变形、像素密度不一致等问题,即使手绘纹理再精细,也抵不过UV本身的缺陷。

三维网格的拓扑复杂度直接决定展开难度。封闭网格必须切开才能铺平,而切口位置和数量又影响接缝数量与纹理连续性。目前主流的展开算法大多把问题转化为能量函数的优化:定义一个衡量映射扭曲程度的能量项,通过数值求解器寻找最优二维布局。接下来分别讨论几种有代表性的算法,并重点分析在3D生成场景下如何针对自动生成的网格做额外优化。
共形映射与LSCM:最小化角度扭曲
LSCM(Least Squares Conformal Maps,最小二乘共形映射)最初由Lévy等人提出,核心思想是保持局部角度不变,从而避免纹理在曲率大的区域出现明显拉伸。对于一个三角形,三维顶点到二维平面的映射可以分解为旋转、缩放和平移。如果要求该映射是共形的,即每一处局部都保持角度不变,那么对于单个三角形就存在一个相似变换关系。LSCM将每个三角形的共形条件写成复数形式,然后把所有三角形的偏差平方和作为能量函数。
具体来说,对于每个三角形,设其三维顶点为\( (x_i,y_i,z_i) \),二维展开坐标为\( (u_i,v_i) \)。共形条件可以表示为:存在一个复数\( \lambda \)使得每个三角形的边向量满足\( (u_i - u_j) + i(v_i - v_j) = \lambda [(x_i - x_j) + i(y_i - y_j)] \)。但实际上三维三角形无法完全保持该关系,所以通过最小二乘拟合每个三角形的最佳相似变换,再最小化残差。求解时先固定两个顶点(例如指定UV空间中的两个锚点),然后求解线性方程组。该方法的优点是速度较快,结果角度扭曲小,适合大多数有机模型。
不过LSCM也有明显局限。它不直接控制面积扭曲,所以对于细长三角形或极端曲率区域,可能出现三角形面积为零甚至翻转的情况。在3D生成流程中,网格往往由隐式曲面或Marching Cubes提取而来,包含大量狭长三角形,单纯使用LSCM经常导致局部折叠,需要额外做翻转修正或与面积项结合。
角度空间优化与ABF系列
ABF(Angle Based Flattening,基于角度的展开)换了一种思路:不直接优化顶点坐标,而是先优化三角形内角。对于平面三角形,三个内角之和必须等于180度,而且围绕每个内部顶点的所有相邻三角形内角之和必须为360度。ABF在角度空间中设定目标:让展开后的三角形内角尽可能接近原始三维三角形内角,从而保持角度不变。然后通过求解一个非线性优化问题得到满足约束的角度集合,最后从角度重构二维顶点位置。
ABF的优点是能非常精确地控制角度扭曲,对局部形状保持得比LSCM更好。代价是计算量较大:需要求解带约束的非线性系统,迭代次数多,而且从角度重建二维坐标是另一个需要仔细处理的过程。后续的ABF++和ABF+++改进了求解效率,通过拉格朗日乘子将约束转化为无约束优化,并引入了层次化加速。对于需要高质量UV的影视级资产,ABF系列经常被嵌入到专业展开工具中作为备选算法。
实践中,如果网格三角形质量本身较差(比如大量非常小的三角形),角度空间优化会放大浮点误差,导致重构出的UV坐标不稳定。3D生成中的网格通常需要先做重网格化或简化,去除退化三角形后再使用ABF,否则容易得到扭曲的岛状布局。
局部刚性约束与ARAP方法
ARAP(As-Rigid-As-Possible,尽可能刚性)参数化在近十年成为UV展开领域的热门选择。它假设每个三角形在映射后应该经过一个刚性变换(旋转+平移),但允许缩放。能量函数基于每个三角形的仿射变换与最近刚性变换之间的差异,迭代优化:先固定旋转矩阵,求解顶点位置;再固定顶点位置,更新每个三角形的最佳旋转。这种交替最小化过程能够较好地平衡角度与面积扭曲,比LSCM鲁棒,比ABF高效。
ARAP的一个显著优势是初始猜测不敏感,即使从糟糕的展开状态开始也能收敛到质量较好的结果。此外,通过给不同三角形赋予权重,可以控制特定区域的保持程度。例如对于机械模型的平面区域,可以增大权重保持刚性;对于有机曲面的转折处,适当减小权重允许更多拉伸。在3D生成中,ARAP常和分割算法配合使用:先自动将模型切割成多个可展开的块,再对每个块运行ARAP,最后做全局优化统一尺度。
值得注意的是,ARAP并不保证全局无翻转。当初始展开包含翻转三角形时,交替优化可能陷入局部极小值。实际使用中需要先做一次简单的展开(比如Tutte嵌入)作为初始化,并加入翻转检测和惩罚项。例如可以在能量中增加对数障碍项,当三角形面积接近零时能量急剧增大,从而避免退化。
面向3D生成的专项优化策略
3D生成模型输出的网格常常具备以下特征:顶点密度不均匀、存在非流形边或孔洞、需要自动切割成UV岛。针对这些场景,仅靠通用展开算法往往不够,还需要在流程上做额外处理。首先推荐使用测地距离驱动的切割线检测。传统方法依赖用户手动标记切割边,而自动方法可以根据曲率极值和对称性检测生成候选切割路径。例如检测模型表面的特征线(如褶皱、硬边),优先沿这些线切割,能把接缝隐藏在不显眼的位置。
第二个策略是岛间距控制和填满率优化。展开算法输出初始UV布局后,通常需要将多个UV岛排布到统一的[0,1]²纹理空间中。若直接等比例缩放所有岛,可能浪费30%以上的纹理面积。更好的做法是使用装箱算法(如Skyline或Guillotine)加上旋转、镜像候选,在保持岛间距不少于2个像素的前提下最大化填满率。间距过小会导致不同岛边缘的纹理渗色;间距过大则浪费分辨率。
第三是针对自动生成网格的对称性处理。很多生成模型具有对称结构,如果左右两侧UV布局不一致,会导致纹理在对称部位出现密度差异,破坏后续纹理合成。可以在展开前检测对称平面,约束对称顶点共享同一组UV坐标(或镜像坐标),这样既能减少接缝,又能提升纹理利用率。示例如下:
import numpy as np
from scipy.sparse import lil_matrix
def symmetric_uv_constraint(vertices, uv, sym_pairs):
"""
vertices: (n,3) 原始顶点
uv: (n,2) 当前UV坐标
sym_pairs: 对称顶点对列表,每项为 (i,j)
返回拉格朗日乘子矩阵A和右端向量b,用于线性求解对称约束
"""
A = lil_matrix((len(sym_pairs)*2, len(uv)*2))
b = np.zeros(len(sym_pairs)*2)
for k, (i, j) in enumerate(sym_pairs):
# 约束 u_i - u_j = 0, v_i - v_j = 0
A[2*k, 2*i] = 1.0
A[2*k, 2*j] = -1.0
A[2*k+1, 2*i+1] = 1.0
A[2*k+1, 2*j+1] = -1.0
# b置零即可,表示u_i = u_j且v_i = v_j
return A.tocsr(), b
最后,纹理分辨率选择也与展开质量紧密相关。对于3D生成模型,常使用4K甚至8K纹理来弥补UV密度不均的问题。但更高效的做法是采用多UV集(UDIM)技术,将不同材质区域分配到独立贴图空间。这要求展开算法能够输出多个UV图块并正确记录UDIM索引,目前主流DCC软件和运行时引擎均支持该流程。
实际应用中的调试与验证方法
展开完成后,不能只看UV布局美观与否,必须用定量指标验证质量。常用的三个指标是:角度扭曲(Angle Distortion)、面积扭曲(Area Distortion)和重叠面积(Overlap Area)。角度扭曲通过比较三维三角形内角和展开后三角形内角之差来衡量,面积扭曲则用面积比值的对数或相对误差表示。重叠面积指UV空间中不同三角形互相覆盖的总面积,该值应严格为零,否则纹理会出现错误映射。
在3D生成工作流中,建议使用棋盘格纹理做快速目视检查。将生成模型赋予一张黑白相间的棋盘格贴图,如果棋盘格在某些区域被拉伸成长方形,说明该处存在面积扭曲;如果格子边缘不垂直,说明有角度扭曲。同时配合UV检查器图,观察颜色渐变是否连续,可以直观定位接缝和翻转。这些检查应在展开算法每次迭代后自动执行,当指标超过阈值时触发重新切割或局部松弛。
另外,展开算法的性能也不容忽视。对于包含几十万三角形的生成网格,LSCM和ARAP的线性求解可能需要数秒到数十秒。若需要实时预览,可以采用分层策略:先在简化网格(例如1万三角形)上展开,得到粗略UV后通过重心坐标映射回原始网格,再利用局部优化修正边界区域。这种方案能在交互式建模工具中保持流畅体验。