← ALL ARTICLES
动画系统3 MIN READ

毛发表示与模拟

全库目录221
本文目录6

近景需要发丝轮廓,远景却主要看到发束体积。毛发表示因此分成发片、发丝与引导线代理,模拟密度、渲染密度和阴影预算分别变化。切换不能只减发丝数,还要保持运动与覆盖连续。

发片、发丝与引导线

发片用少量带 Alpha 的面片表示发束。主要成本在重复绘制、排序、阴影和各向异性材质。二级运动可用少量关节或弹簧链。

Strand/Groom 直接表示大量发丝,通常先模拟少量引导线 Hair,再插值 Follower。还需要分 Cluster 做剔除、LOD 和渲染。

毛发模拟要处理长度、弯曲、碰撞和阻尼约束。近景可保留更多引导线与发丝,远景逐步降低密度,最终切到发片或体积近似。几何 LOD、阴影 LOD 和材质 LOD 需要一起变化。

引导线到渲染发丝

机制伪代码中,跟随发丝绑定到相邻引导线的相同归一化弧长位置,离线权重非负且和为一。每根跟随发丝还绑定一条主引导线,transportedFrame 使用该线的局部标架,bindOffset 存在这个标架中;相邻引导线只参与中心位置插值。这样每次旋转偏移时都有唯一且正交的基底。若改用多标架混合,需要处理旋转符号和归一化,直接平均矩阵会引入缩放。

text
for sample in follower:
    position = sum(weight[g] * guide[g].SampleArcLength(sample.s))
    position += transportedFrame * bindOffset

弧长采样与偏移传递

设一条引导发丝的累计弧长为 a0=0,a1,…,ana_0=0,a_1,\ldots,a_n。跟随发丝保存归一化位置 ss,目标长度为 u=sanu=s a_n。找到 aj≤u≤aj+1a_j\le u\le a_{j+1} 后,用 α=(u−aj)/(aj+1−aj)\alpha=(u-a_j)/(a_{j+1}-a_j) 插值两个引导点。重合点造成分母为零,应在绑定时合并,或跳到下一段非零长度。用同一顶点编号对应不同采样密度的引导发丝,会把发梢绑定到错误高度。

例如引导点位于y=0、0.2、1米,s=0.5应落在y=0.5。按顶点序号取一半却落在y=0.2,采样密度改变就会使跟随发丝沿束上下滑动。累计弧长查找找到第二段,段内权重为(0.5-0.2)/(1-0.2)=0.375,才得到正确位置。

偏移还要随发束旋转。沿曲线把上一段切线旋转到当前切线,并用同一最小旋转传递法线和副法线,得到局部标架;初始标架来自头皮绑定。切线接近反向时最小旋转轴不唯一,应使用绑定方向或上一有效标架回退。把静止偏移直接加到世界位置会使发束转动时散开。模拟根部跟随头皮、长度约束和碰撞的求解顺序见 XPBD。

验证方法

在甩头、瞬移、风和碰撞下检查长度及包围体。引导线减少后观察形态,发片切换后核对覆盖、阴影和材质;高光主机制见风格化头发高光。

实现状态:正文片段用于解释本页数据流与边界条件;完整宿主的编译、运行及性能测量尚未执行。可运行的独立模型以本页列出的具体测试为准。

相关主题

参考资料