关于 scenario-maya-groom
面向使用 XGen Interactive Groom 的 Agent 的 Maya 2027 毛发梳理技能。它指导发丝走向、簇层级、遮罩、渲染和动态,并结合数值检查与渲染审阅。
主要功能
- 01基于引导曲线规划发丝走向
- 02设置分层毛簇与噪声
- 03检查发际线遮罩和密度
- 04Arnold 毛发着色器与渲染审阅
- 05基于导线的动态和缓存检查
适用场景
- 01梳理写实或风格化毛发
- 02依据参考走向建立毛发描述
- 03检查毛发覆盖和发丝预算
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-maya-groom安装后在 Claude Code 中输入/scenario-maya-groom确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/mx_groom.py详细介绍
毛发梳理(XGen Interactive Groom,Maya 2027)
专家会先用几根引导毛发设定走向,再建立根部松散、轮廓各异的毛丛层级,最后只在参考图显示的位置(发梢、散毛)添加破碎效果,并通过使用真实毛发着色器、侧向照明的近景渲染来评判。Interactive Groom 笔刷没有笔触 API,因此 Agent 会通过数据梳理毛发(将流向表中的引导毛发接入堆栈、将遮罩写入图像、按值设置修改器),再结合导出毛束的数据和渲染结果进行数值评判。代码:scripts/mx_groom.py(import mx_groom as G)。如果这里提到的同级技能不在你可用的技能中,请让用户安装它(npx skills add scenario-labs/skills --skill <name>);如果无人值守,则根据工具架构继续操作并标明缺失项。
必备背景: scenario-maya-expert(执行通道、审查循环、2027 版陷阱)。
状态(2026-09-24): 此处的所有 Maya 调用尚未在 Maya 中运行(尚未安装 2027 版)。mx_groom 的纯逻辑层已通过离线测试(tests/code/maya-groom/test_mx_groom_offline.py)。未从 2027 帮助文档中引用的名称会在运行时通过 G.NAME_CANDIDATES 解析。
要点(专家经验差异)
- 先梳理流向,在引导毛发上操作,并根据参考图上绘制的箭头来复制(Fernandez)。流向就是压力:相邻毛发共享压缩曲线,相对的流向则在更平直的带状区域交汇。短毛转向急,长发转向缓。决定每个大形状由流向还是毛丛来控制。
- 根部要松散,每个毛丛各不相同,分两层(Fernandez)。长度前约 14% 的部分不要产生吸引力,否则发根会挤成光秃的线条。每个大毛丛包含 3 到 5 个小毛丛;只有长发或鬃毛才需要第三层。改变尺寸和轮廓(
G.CLUMP_PROFILES:spike、onion)。 - 遮罩和紧致度是两个不同的调节项(Fernandez 05、06)。遮罩决定是三角形还是方形:方形毛丛是在较松散的大毛丛中包含紧密的小毛丛,两者的遮罩都要调低。紧致度(IG Clump strength [added])为 0 时,毛丛保留形状而不收拢;遮罩为 0 时则会移除毛丛。直线引导毛发会让两者看起来相似,因此应在带噪声的引导毛发上测试(
G.clump_follow)。 - 噪声所在的层级决定了破碎效果(Fernandez 07)。毛丛层级的噪声(二级 Clump 的 Noise,位于发梢一半处)会打散大毛丛,同时保留小毛丛和发根;Noise 修改器也会打散小毛丛,因此只应用于少量毛发(Giovannini:身体部位设为 0,5% 的毛发设为 3)。改变频率;只让少量毛发产生毛躁。散毛毛丛来自主毛丛遮罩中的孔洞,而不是一个新系统。
- 真实的发际线要靠较稀疏的边缘毛发以及过渡和桃绒毛描述来呈现,而不只是增加密度(Hadi Karimi)。所有描述共用一张密度贴图;每种毛发类型各自使用一个描述。
- 短毛填充层可以遮住头皮(Giovannini):将身体引导毛发剪至 2/3 长度,这样长发就不必“密得离谱”。
- 运动只驱动少量线缆,绝不驱动毛发(Flood)。从 Linear Wire 的 inGuide 导出线缆。在第 1 帧的静止姿势下更新 Reference State。Curve to Spline 关闭 Align to Normals。
- Standard Hair 的真实感来自黑色素、粗糙度和 IOR(Arnold 毛发文档)。Diffuse 保持为 0,色调保持白色,间接光缩放保持为 1,并使用 ribbon 模式(Min Pixel Width 仅在此模式下有效)。金发使用 Extra Depth。成本有四个调节项(MPW、透明度深度、高光采样数、AA);不透明度低于 1 会显著增加成本。
先确定
在创建任何节点之前,先将答案写入 brief.json。
| 输入 | 变化 | 未明确说明时的默认值 |
|---|---|---|
| 目标 | Arnold 发丝、Unreal 发丝或卡片(MtoA 不会渲染 XGen 卡片图元) | Arnold 发丝 |
| 毛发类型 | 每种类型各写一段描述:身体毛发、填充毛发、刘海、杂毛、眉毛、上下睫毛、过渡毛发、绒毛。近景面部:确定是否加入桃毛(Hadi) | 身体毛发 + 眉毛 |
| 风格 | 写实:随机簇点、Randomness > 0、黑色素。风格化:导向毛发上的毛簇(FlippedNormals),Base Color 使用纯色,Melanin 为 0 [新增]。两者都要:在明确到柔和的范围中选取一个点,保持相同的轮廓(Fernandez 07) | 写实 |
| 动态,以及由谁负责 | 静态跟随;关键帧或模拟线束;绑定或 CFX 部门(Flood),或梳理文件(2027 帮助) | 跟随头皮 |
| 静帧还是动画 | 静态相似度:在头部上生长(Hadi)。动画或实时:使用 UV 整洁的头皮帽 | 头皮帽 |
| 摄影机距离 | Scattering Mode:近景使用 Accurate(速度慢 10 到 30 %),混合镜头使用 Adaptive | Adaptive |
| 预算 | 样条数量和 GPU 内存(xgmSplineQuery)、Unreal 模拟导向毛发 | 写明具体数值 |
| 参考 | 毛流箭头和毛簇数量均以此为依据 | 询问;否则写下假定的外观 |
| 新建还是继承 | 新建项目使用 Interactive Groom;仅对继承的资产或非样条图元使用旧版 XGen | Interactive Groom |
工作流
无头模式下的 mayapy(mx_run --plugins mtoa,xgen,abc,顺序不可更改)可处理导向曲线、蒙版、Alembic、Unreal 标签、lint、分析和 Arnold 审核;GUI 桥接则处理菜单查询,以及探测结果表明无法在无头模式下计算的内容(IG 在 GPU 上计算)。
references/procedures.md 中的 P16 用一个脚本完成整个任务,并断言每个关卡(G.gate 会引发异常)。
- 探测和配方(每次安装一次)。 在无头模式和 GUI 中运行
G.probe()。对于没有文档记录命令的菜单操作,只读取,不点击:通过桥接调用G.menu_recipe(name)查询菜单项的命令字符串(cmds.menuItem(item, q=True, command=True))并保存;属性编辑器按钮(Make Wires Dynamic、Reference State Update、Rebuild)通过G.button_recipe(name, node)操作。Export Cache 会打开对话框:用G.recipe_source写入其@path@模板。**关卡:**已保存探测 JSON;recipe_status()显示计划所需的配方均已记录。 - 头皮。
G.scalp_check(scalp, for_unreal=...)。**关卡:**没有error:行,存在边界边(发际线),UV 不重叠。 - 流向表和计数。 根据参考图编写流向表(
base、whorl、part、direction、长度区域),并统计大块发束数量及每块大束中的小束数量。关卡:G.check_flow_sheet(flow) == []。 - 导向曲线。
g = G.make_guides(scalp, flow, spacing=..., cvs=8, collide=head),先少量创建(FlippedNormals);仅在拓扑对称时设置symmetric=True(Hadi)。关卡:G.gate(G.measure_curves(...)["verdict"]),穿透数为 0,间断仅出现在分缝和旋涡处。 - 描述和连接。 每种发型调用一次
G.create_description(scalp, "hair_body")(应用配方并重命名)。G.wire_guides(desc, g["curves"]):在堆栈较低处放置 Guide 修改器,用 Curve to Spline 节点连接其 inGuide,为导向曲线插值;它保存分缝所需的区域映射。直接放在描述上的 Curve to Spline 会将每条曲线转为一根发丝,并禁用其下方的所有内容:仅用于精确发丝或缓存。关卡:G.wiring_verdict:连接后,该头发的流向表误差下降,且 InGuide_base 缓存包含每条导向曲线。 - 堆栈、密度和蒙版。 从下到上:base(按 Numbers 设置 CV 数量)、Scale、Guide、主次 Clump(
G.build_clumps)、作用于共享部分的 Strand Noise、长度变化、Collision。对发际线调用G.write_hairline_mask(band=True表示过渡带),在各描述间共享同一张贴图(G.connect_texture),用G.patches在主 Clump 的蒙版中打孔以去除杂散发束。关卡:G.gate(G.lint()["lines"]);coverage检查(露出头皮的百分比)和样条数量均在预算范围内。 - 发束和变化,逐层处理(Giovannini)。每次安装一次,P5b 的两项测试可确定 Clump Scale 的约定、哪个参数控制紧致度,以及每个噪声级别会产生何种变化。导出堆栈中间阶段的缓存,然后运行
G.hierarchy_from_states(3 到 5)、G.breakup_report和G.measure_abc。各渲染一次 Noise 前后的 Clump(2027 帮助文档)。关卡:breakup_verdict和strand_verdict均无问题;侧光特写通过references/critique.md的审核,三角形和方形的比例符合参考图。 - 着色器和渲染。
G.hair_shader(desc, preset=...)(替换默认的hairPhysicalShader),G.curve_render(desc, "ribbon", min_pixel_width=...),并在四个参数上运行G.cost_sweep,同时检查闪烁。渲染 XGen 前先保存。**关卡:**根据审核标准评判G.review(...)评审表,且着色器没有warn:。 - 运动。 静态跟随、设有关键帧的 wires(Flood),或动力学(Linear Wire、Make Wires Dynamic)。缓存需标记版本。**关卡:**静止帧、中间帧和最后一帧的渲染均无穿透。
- 交付(交接)。
数值
| 数值 | 相对于 | 来源 |
|---|---|---|
| 前约 14 % 的发丝长度内没有明显的簇拉扯 | 发丝长度、簇剖面 | Fernandez 02 [00:17:56] |
| 尖峰型:中段为 0.01;洋葱型:中段凸起约为 0.9 | 旧版 Clump Scale 渐变(半径读数) | Fernandez 02 [00:05:38],帧 00:06:00、00:10:51 |
| 每个大簇配 3 到 5 个小簇;2 层,长发用 3 层 | 簇层级 | Fernandez 03 [00:01:31]、[00:09:11] |
| 第二层簇密度 7.5,簇噪波 2,Cut 随机值最高为 10 | 他的实时头皮资产 | Giovannini [00:09:43] 至 [00:11:25] |
| 散发占 5 %(最高 20 %),散发噪波为 3,主体为 0 | 发丝占比 | Giovannini [00:09:28]、[00:11:59] |
| 噪波遮罩为 0.1 到 0.5(1 会消除簇效果) | 旧版 Noise 修改器 | FlippedNormals [00:32:05] |
| 使用噪波时为 20 个 CV;卷发为 24 到 36 个 | 修改器或基础 CV 数量 | FlippedNormals [00:28:52];2027 帮助文档 |
| 随机长度为 0.8 到 1.2;簇切割为 0.2 | 以 1 为中心平衡;小簇层级 | Fernandez 08 [00:09:33]、[00:15:34] |
| 黑色素:金发为 0.2,红发或棕发为 0.5,黑发为 1.0 | Standard Hair | Arnold 毛发文档 |
| IOR 为 1.55(仅湿发时超出 1.4 到 1.6);Shift 为 0 到 10 度,测量值为 2.3 到 3.7,合成值为 0 | Standard Hair | Arnold 毛发文档 |
| Unreal:Sub Steps 为 40,Iterations 为 10,Collision Radius 为 3.5,发梢 Bend Scale 为 0.1 | UE 5.3 时期 [估算] | Giovannini [00:51:04] 至 [00:54:27] |
| Nucleus Space Scale 为 0.01 | 以 cm 为单位的场景 | maya-version-deltas 2.8 |
质量门槛
代码检查。 G.lint()(插件顺序、堆栈、簇连接与剖面、噪波位置、预算、着色器)、G.measure_abc(cache)["verdict"](根部收窄、剖面多样性、大簇中的小簇数量、散发、发梢噪波、频率与毛躁度、长度平衡、流向、穿透)、G.wiring_verdict、G.breakup_verdict、G.unreal_verdict(G.inspect_abc(abc))。G.gate 会将其中任何一项转为断言。标记为 [added] 的阈值是此技能的默认值;每行都注明了对应规则。
视觉检查。 G.review(hair, out, head=head, scalp=scalp, closeups=[...]) 使用实际着色器进行渲染:美术图(穹顶灯光加沿着发型布置的主光,Schneider)、逆光(散发、光晕)、剪影、覆盖范围。只有在调用 G.viewport_aa(True)(FlippedNormals、Fernandez)后才进行视口截图。根据 references/critique.md 进行评判:先看流向,再看簇,最后看发丝(Fernandez)。
常见错误
| 错误 | 表现 | 修正 |
|---|---|---|
| 指引曲线未连接,或描述中通过 Curve to Spline 连接 | 头发忽略流向图,或每条曲线只生成一根头发 | G.wire_guides(Guide 修改器),然后运行 wiring_verdict |
| 发根成簇 | 头皮上发簇之间出现秃线 | 使用发根疏松的 Clump Scale 渐变(Fernandez) |
| 所有三角形的发簇形状都一样 | 规律得像「CG」 | 调整 Radius Variance、轮廓和方形发簇(Fernandez 02、05) |
| 在笔直的指引曲线上判断 Mask 和 Tightness | 两个旋钮看起来作用相同 | 在 Clump 下方添加噪波,使用 G.clump_follow(Fernandez 06) |
| 用发丝噪波打散大簇;在发束上添加噪波 | 小发簇散成毛躁的碎发 | 添加发簇级噪波;仅对部分头发使用发丝噪波(Fernandez 07、Giovannini) |
| 只有一种噪波频率,所有地方都毛躁 | 碎发虚假且均匀 | 改变频率;仅让少量头发毛躁(Fernandez 05) |
| 只用新系统添加散发 | 散发与发簇毫无关联 | 在主要系统的 Mask 中挖孔(Fernandez 03) |
| 延长发丝 | 发簇内部相互交叉 | 在小发簇级别缩放或裁切(Fernandez 08) |
| 发簇边缘锯齿状,位置不佳 | 发簇边缘呈阶梯状 | 提高每个级别的 Map Subdivision Level;使用新的 Seed(2027 帮助文档) |
| 次级密度小于或等于主级 | 次级发簇溢出单元 | 复制主级,提高密度,并启用 Use Control Map(2027 帮助文档) |
| 发簇跨越分缝 | 发簇横跨分缝 | 将指引区域图用作发簇控制图,或拆分描述 |
| 缓存时未启用 Multiple Transforms 和 Write Final Width | 曲线在其他应用中显示错误 | 同时启用两者(2027 帮助文档、Flood);注意 Epic 的相反建议 |
保留默认的 hairPhysicalShader | 头发没有间接漫反射(Ai Kd Ind 默认为 0) | 使用 aiStandardHair,或提高 Ai Kd Ind(2027 帮助文档) |
| 在有锯齿的视口中进行判断 | 密度和发簇判断失准 | 先运行 G.viewport_aa(True) |
交接
- **接收自 scenario-maya-retopology-uv:**仅含头皮的发帽(发际线处为开放边界),
UV 唯一且位于 0 到 1 范围内,供 Unreal 使用的 UV 集
map1,已冻结且无历史记录;通过G.scalp_check。 - **接收自 scenario-maya-animation:**引用的绑定,从第 1 帧的静止姿势开始的镜头,动画身体的
Alembic(
-uvWrite、-stripNamespaces),以及绑定负责线束时的线束缓存。 - **交付给 scenario-maya-lighting-rendering:**新版毛发,已分配并通过 lint 检查的 aiStandardHair、 发片设置、按镜头版本化的缓存、审阅表,以及尚未验证的内容。 如果毛发必须与皮肤匹配,请联系 scenario-maya-lookdev。
- 交付给 scenario-maya-pipeline-scripting(Unreal):
<asset>_ue5.abc,包含groom_group_id、groom_guide(真实导向毛发,不含填充毛发)和groom_root_uv(UV 集map1), 重新导入后通过检查的unreal_verdict,以及 Unreal 起始值(Numbers)。
Maya 2027 说明
- 旧版描述不适用于 Interactive Groom 工具;请逐个转换,然后分别执行 Rebuild (Giovannini)。
- 默认 IG 着色器为
hairPhysicalShader(Ai Kd Ind 0)。Standard Hair 在 MtoA 5.6.0 中新增了scattering_mode。请先加载 MtoA,再加载 XGen。 - IG 在 GPU 上计算;尚未验证 Apple Silicon 上的无界面求值(需探测)。并行 Maya 的已知限制:批量渲染 XGen 场景“可能会产生错误结果”。
- Alembic 仅支持 Ogawa。Epic 的脚本使用 Python 2 和 API 1.0:请使用
mx_groom移植版本。macOS 不支持 Arnold GPU;Arnold RenderView 已取代 Maya IPR。Ctrl 指 Control,不是 Command。
参考资料
references/procedures.md:每个阶段的代码、P5b 毛束测试、完整工作流程 P16。编写毛发代码前请加载。references/critique.md:根据渲染结果和数值评判毛发的标准。每个关卡都要加载。references/expert-notes.md:专家原则、分歧及用于决策的条件。选择方案时加载。references/gui-paths.md:菜单、编辑器、画笔、快捷键 (计算机操作 Agent)。references/sources.md:所有来源、凭据、URL 和最佳时间戳。