← ALL ARTICLES

描边方向烘焙

全库目录221
本文目录6

几何壳需要一份跨硬边连续的外扩方向,着色法线仍保留原有棱角。输入是网格拓扑、面法线与权重,输出是每级LOD可复现的顶点方向和存储契约。壳的像素宽度、深度与屏幕方案见描边。

硬边裂缝与独立方向

硬边处会出现裂缝,因为同一个位置通常存在多个法线不同的顶点。沿各自法线外扩后,这些顶点会向不同方向移动,于是原本相连的轮廓被拉开。

既然裂缝来自方向不一致,让接缝上的顶点沿同一个方向移动就能把它们重新接起来。但着色法线之所以分开,正是为了保留硬边的光照。直接平滑这份法线,轮廓可能连续了,原来的棱角明暗却也会改变。

因此我们给描边单独准备一份外扩方向,原着色法线继续负责光照。烘焙这份方向时,在对象空间找到属于同一轮廓接缝的顶点,再让它们共享结果。位置比较带上容差,是为了处理浮点误差;同时检查拓扑所属,是因为两块独立表面可能恰好相交。它们位置相同,却不一定应该连成同一条轮廓。

权重累加完成后再归一化

顶点分好组以后,还要决定这个组沿哪个方向外扩。做法是把参与面的方向加起来,再归一化;如果某些面贡献更大,就给它们更大的权重:

noutline=normalize⁡(∑iaini)\mathbf n_{outline}=\operatorname{normalize}\left(\sum_i a_i\mathbf n_i\right)

这里的ni是参与面的方向,ai是它的权重。如果直接按三角形数量平均,网格切得更密的一侧可能占据更大贡献。面积权重能减少这种小三角形重复贡献;角度权重则能减少局部重划分对结果的影响。

所以烘焙输入最好从选定面片的法线和权重出发。直接累加拆分后的顶点法线也能得到一个方向,但UV接缝或硬边产生的副本越多,那一侧的贡献就可能越大。这里的权重已经受拆分规则影响,确认副本怎样产生,才能解释算出的方向。

下面的Python参考函数接收同组方向和非负权重。它先完成累加,最后只归一化一次,这样在精确算术下与遍历顺序无关,浮点求和仍可能有舍入差异。

python
def smooth_group(normals, weights):
    total = tuple(sum(n[axis] * w for n, w in zip(normals, weights))
                  for axis in range(3))
    length = sum(value * value for value in total) ** 0.5
    if length < 1e-12:
        raise ValueError("无法确定外扩方向")
    return tuple(value / length for value in total)

用三个互相垂直的单位方向试一下,结果就是归一化后的(1,1,1)。如果每次加一项就归一化,前面累计量的长度会被反复改为一,后加入的方向相对它的权重也随之改变,最终结果就会依赖顺序。reference.py保留了这个检查,也补上输入长度和权重的检查。

数据通道与蒙皮

方向算出来以后,着色器还得读到它。选择存储通道时,先看哪些属性已经被材质和资产管线占用,再决定愿意用多少带宽和精度换这份数据。

存储方式前提要检查的代价
顶点色选择8位或浮点格式,确认原有遮罩用途方向量化、顶点带宽、通道占用
UV属性Unity SetUVs支持索引0–7与2/3/4分量布局与精度;两分量可用八面体编码
切线资产不使用该通道的法线贴图契约与切线、手性和导入处理冲突
独立缓冲着色器能按顶点或实例索引读取绑定、索引一致性和生命周期

比如把方向写入8位顶点色,量化会改变三个分量的比例,解码后的长度也未必仍是一。因此读取后再归一化,让外扩距离继续由宽度参数决定。至于8位精度够不够,近景斜边和高曲率网格会比平滑球体更容易暴露误差,用它们检查线宽和方向更有意义。

静态模型的处理比较直接:对象空间中的描边方向跟着对象变换就够了。角色做了蒙皮以后,表面会随骨骼弯曲,外扩方向也得跟着变化。单纯把方向存进UV做不到这一点,因为UV里的数值不会自动参与蒙皮。

一种做法是把方向存成切线空间数据,蒙皮完成后再用变形后的基底恢复它;另一种是明确对这份方向执行蒙皮。

另外,模型存在非均匀缩放时,方向的变换也不能直接按普通向量处理。这里遵循法线的变换规则,使用逆转置矩阵,再重新归一化,才能保持方向与变换后的表面关系。

LOD切换时,网格拓扑和顶点属性布局都可能变化,同一份顶点方向也就不能直接套到每一级。因此每级LOD分别烘焙,再观察切换时的轮廓是否连续。把算法、容差、权重和版本记在自动导入步骤里,资产重导入时才有依据复现相同结果。

实现与验证

运行python -B 知识库/examples/outline/reference.py,对应检查覆盖累加顺序、三轴方向和权重。本页Python片段省略的输入长度与权重验证由参考函数完成;完整烘焙器、蒙皮和各LOD资产仍需目标工程运行。

相关主题

参考资料

完整来源与本机实验入口见描边。