mcpField
S
scenario-blender-hair

scenario-blender-hair

github.com/scenario-labs创意与媒体1.2k353 次安装1 天前更新
代码仓库

关于 scenario-blender-hair

面向使用 Blender 5.2 制作毛发和皮毛的艺术家与 Agent,涵盖曲线梳理、渲染毛发及游戏用发片。通过引导曲线、遮罩程序化层和质量检查组织工作流程。

主要功能

  1. 01规划并放置毛发引导曲线
  2. 02构建遮罩程序化梳理层
  3. 03检查 UV、根部、间距和密度
  4. 04审核全密度渲染与姿势
  5. 05将梳理曲线转换为游戏发片

适用场景

  1. 01制作带有毛簇和杂毛的动物皮毛
  2. 02围绕分线塑造人类发型
  3. 03检查变形时的毛发效果
  4. 04准备游戏导出的毛发片

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scenario-labs/skills --skill scenario-blender-hair

安装后在 Claude Code 中输入/scenario-blender-hair确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
critique.md
expert-notes.md
procedures.md
sources.md
scripts/
bx_hair.py

详细介绍

毛发梳理(毛发曲线,Blender 5.2)

专业的梳理只需少量间距均匀的引导曲线来确定方向和轮廓。叠加使用经过遮罩的程序化图层,增加密度、成束效果、毛躁感、长度变化和散毛,并在完整密度和摆好姿势的光照渲染中进行评估。在 5.2.1 中,将引导曲线编写为数据(无法通过脚本绘制曲线笔刷笔触),并通过 Essentials 毛发节点组资产做出所有外观决策。如果这里提到的同级技能不在可用技能中,请要求用户安装它 (npx skills add scenario-labs/skills --skill <name>);无人值守时,根据工具架构继续操作,并标明缺失的技能。

必备背景: scenario-blender-expert(执行渠道、审查循环、5.2 API 变更)。

原则(专家要点)

  • 方向正确之前,每条引导曲线只设 2 个点(Schmidbauer)。更多点会导致梳理缠乱和穿插。短毛用 3 个点,长毛才用 8 个点。Bystedt 会在塑形前将长的人类头发重新采样为 15 个点。
  • 引导曲线均匀分布,并始终为 Interpolate 添加遮罩(Schmidbauer)。子毛会生成在整个表面上,而远离任何引导曲线的子毛会“自行其是”。间隙会形成秃斑,并在变形时变得明显。
  • 密度按平方米计数,因此数值必须很大(Thommes)。长毛使用 1,000,000/m²,半径约为 0.2 mm。工作时将 Viewport Amount 设为 4%。
  • 按曲线随机化,而不是按点随机化(Thommes)。让 80% 的毛束没有毛躁感。散毛占曲线的 10%,并使用强噪波。
  • 关闭 Replace Length,并使用 Random Offset 进行修剪(Schmidbauer、Thommes)。这是成本最低的真实感提升方法。为其添加遮罩,否则短毛区域会失去引导曲线,变得光秃。
  • 在人类发型中,沿分缝将头发种植在独立的发帽上(Bystedt):这样就不必在意身体网格拓扑,也能避免插值跨越分缝。分缝处仍需要更高密度并向上提起。
  • 所有资产的塑形方式都相同:1 只影响末端,0 影响整根毛发,负值影响根部。使用负值 Frizz Shape,保留卷曲和成束的末端(Thommes、Bystedt)。
  • 在完整密度和摆好姿势的情况下评估渲染(Thommes、Schmidbauer)。网格的剧烈变形会让毛发“看起来糟十倍”。

首先确认

输入影响未说明时的默认值
目标Cycles 毛束与 EEVEE 或游戏卡片之间的选择Cycles 毛束(Principled Hair BSDF)
对象人类发型(发帽、分缝)与动物毛发(身体网格、标志点)遵循参考资料
长度类别每条引导曲线的点数、成束和卷曲图层短毛:3 个点,长毛:8 个点,长的人类头发:15 个点
变形动画场景意味着 Hair Dynamics (Animation) 保持在最后,并需检查摆姿效果动画
预算渲染曲线、卡片三角形说明数量:完整密度下的求值曲线数
参考资料同一亚种、同一季节,最好是同一个体(Schmidbauer)主动索取;先绘制标志点并确定毛发走向

梳理前先完成拓扑和无重叠 UV(毛发会绑定到 UV 空间),并应用缩放: 密度按网格的局部面积计算(已验证)。

工作流

任务无头模式实时会话
曲线对象、表面绑定、作为数据的引导线、吸附、细分或重采样、资产修改器、输入、遮罩、计数、渲染、卡片是(scripts/bx_hair.py)是,在对象模式下使用相同代码
进入雕刻曲线模式、激活 11 种曲线笔刷、设置笔刷参数、sculpt_curves.select_random不适用是(bx_gui.activate_brush("SCULPT_CURVES", "Comb"))
梳理、添加、密度、增长/收缩、拉动尖端笔触否否。sculpt_curves.brush_stroke 没有 exec,因此 bx_gui.stroke("SCULPT_CURVES", ...) 会返回 PASS_THROUGH,且不做任何更改。设置好笔刷后,请用户进行笔触操作,或使用以下替代方案。
  1. 准备表面。 H.uv_report(surface):UV 重叠会导致曲线忽略绑定;UDIM 没问题;未合并的镜像接缝需要使用 UV Merge by Distance(Schmidbauer)。人体模型:沿分缝将发帽拆分为多个岛。动物模型:将口腔内部单独分离。蒙版:使用顶点组(速度快)或纹理(适用于低多边形网格的细节)。关卡: overlap_faces == 0,已应用缩放,每个区域使用一个蒙版。
  2. 规划流向和对象。 将绘制稿转成区域(顶点组),每个区域指定一个流向。Schmidbauer:每个特征部位(脸部、脸颊、耳朵、脖子、身体、尾巴、脚)使用一个曲线对象,以提升性能。Thommes:使用一个带蒙版的对象。Bystedt:将前后部分拆开,避免梳理一侧时扰动另一侧。关卡: 写下区域、流向和对象的清单。
  3. 引导曲线。 hair = H.new_groom(surface),P, N = H.sample_roots(surface, spacing, mask=...),H.add_guides(hair, P, N, length, points=2, flow=..., flow_blend=...)(吸附并写入 surface_uv_coordinate)。之后可使用 H.subdivide_guides 或 H.resample_guides(hair, 15)。画笔的替代方式:使用方向场实现梳理,用 droop 实现重力效果,通过删除并重新添加引导曲线实现密度和添加效果;Bystedt 的“先长长地生长,梳理,再缩短”可通过长引导曲线加 Trim 实现。关卡: 在 H.groom_report 中,roots_off_surface 和 spacing_gaps_2x 均为 0,且 length_outliers 为 0。仅显示引导曲线的渲染应能清楚呈现每个方向。
  4. 密度。 先添加 Set Hair Curve Profile,再添加带 Density Mask 的 Interpolate Hair Curves。Bystedt 在分缝处绘制 50% 灰色和 100%,然后重新映射。5.2 版的 Interpolate 也支持 Mask Texture 图像。关卡: H.count(hair)(完整密度)在预算范围内,root_area_fraction 远低于 0.5,且渲染中没有秃斑。
  5. 程序化图层,每层都带蒙版,并通过切换 show_viewport 和渲染进行 A/B 测试。
    • 长毛(Thommes,预设 H.FUR_STACK_LONG,通过 H.build_stack 应用):Noise、Curl、strays、使用负形状的 Frizz、Clump、Clump 2、最后的 Frizz(关闭 Cumulative)、Trim、Rotate。
    • 动物(Schmidbauer):Trim、Clump(脸颊、Tip Spread、Clump Offset)、低强度 Frizz,每项都使用自己的顶点组。
    • 人体(Bystedt):在引导曲线上使用 Noise(关闭 Cumulative,开启 Offset per Curve),仅在尖端使用 Roll,然后对梳理后的引导曲线按群体应用 Interpolate、Profile、Clump;宽、细图层需要使用不同种子。
    • 每条曲线的随机性:H.random_curve_mask(hair, "frizz_mask", 0.8),然后输入 "attr:frizz_mask";从根部到尖端的渐变:H.along_curve_attr。关卡: 每个图层都必须在 A/B 渲染中证明其价值。
  6. 分缝和发际线(人体)。 保持开启 Part by Mesh Islands(默认):测试中,关闭岛屿时,分缝附近有 21% 的子曲线越过分缝;开启时为 0%。对于隆起效果,H.distance_weights(cap, "part_lift", "part", radius, "bump") 输入 Displace Hair Curves(开启 Surface Normal,距离设小,Shape 接近 0,Factor 为 attr:part_lift)。关卡: 顶视图中分缝处没有头皮空隙,头顶也不扁平。
  7. 着色和渲染。 使用 H.hair_material(name, "CYCLES", melanin=(root, tip)),或使用 "EEVEE" 并指定颜色,然后使用 H.setup_render(scene, engine, close_up)。关卡: H.review([surface, hair], out, engine) 通过 references/critique.md 中的标准。
  8. 形变。 设置 2 或 3 个极限姿势的关键帧,并使用同一摄像机渲染每一帧。关卡: 所有姿势下都没有秃斑或穿插。
  9. 游戏:卡片。 运行 H.add_cards(hair, width, material=H.card_material(...)),然后转换副本 object.convert(target='MESH') 并导出 glTF。在卡片下方放置带纹理的发帽。关卡: 三角形数量在预算范围内,卡片 UV 位于半个图块内,发根位于头皮上。

数值

项目数值对应来源
引导点放置时为 2 个,短毛为 3 个,长发为 8 个Schmidbauer [00:20:24],[00:21:34]
长人发重采样为 15 个点Bystedt [00:08:38]
添加笔刷长度毛发约为 0.01 m(默认值为 0.3 m)Schmidbauer [00:17:59]
密度,人类图层每束群组每 m² 5,000 根Bystedt [00:17:28]
密度,长毛1,000,000/m²,半径 0.2 mm,视口显示 4%Thommes [00:09:02],[00:16:44]
密度贴图分缝处 1.0,底部 0.5,秃斑处 0;渐变黑色标记略高于 0.5Bystedt [00:22:04],[00:23:46]
宽发束形状约为 0.3,减小 Factor,梳理引导线Bystedt [00:19:47]
卷曲半径 2 cm,Curl Start 1,Random Offset 0.5,Guide Distance 1 cm,Guide Mask 0.2Thommes [00:12:04],[00:14:18]
子发束Guide Distance 1 mm,Mask 0.1;第 2 层:4 mm、0.25、Clump Offset 5 mmThommes [00:16:12],[00:31:01]
毛躁2 mm,负向 Shape;最终值:-0.2,关闭 Cumulative,应用于 20% 的曲线Thommes [00:15:04],[00:32:08],[00:26:03]
杂乱发丝占曲线的 10%,Noise distance 5 mmThommes [00:30:28]
修剪、旋转关闭 Replace Length,Random Offset 5 mm;Rotate 随机旋转 5°Thommes [00:22:20]
发片细分每 20 cm 发片长度细分 1 次Bystedt g_ZIOafq4QU [00:05:08]
发片和管状剖面弧形:平面 1 段,推荐 3 段;管状:平面螺旋,分辨率 6,1 圈,高度 0Matsumoto [00:19:54],[00:22:40]
发片 UV 宽度发片使用管状物 UV 瓦片宽度的一半Matsumoto [00:31:27]
覆盖率合理性检查密度 × π × 半径²:Thommes 的毛发为 0.13[added] check

质量门槛

代码中:

import sys; sys.path.append("<skills>/scenario-blender-hair/scripts"); import bx_hair as H
print(H.uv_report(surface))                 # overlap_faces == 0
rep = H.groom_report(hair); print(H.verdict(rep))   # [] or a list of fixes
print(H.count(hair))                        # full-density curves and points vs budget
print(H.card_stats(hair))                   # cards: tris, UV range

groom_report 会检查附着 UV、根部是否位于表面上、间距空隙、长度凹陷(与相邻发丝相差超过 50%)、Hair Dynamics 是否位于最后、Trim Replace Length、未遮罩的 Frizz 或 Noise、缺失的 Density Mask、半径与密度、Strand 显示,以及 EEVEE 下的 Cycles 毛发着色器。

视觉检查:H.review(objs, out, engine, views=("front", "threequarter", "top")) 使用 Thommes 的布光方案(暖色顶部补光、侧面主光、冷色轮廓光、深蓝灰色世界背景),渲染一张全密度受光效果图。根据 references/critique.md 评分:秃斑、分缝覆盖、发束、杂乱发丝、长度变化、发梢、从根部到发梢的颜色、高光。

常见错误

错误表现修复方案
阻挡时画笔默认大小为 8 点缠结、穿插、梳理时相互干扰设为 2 点,之后再调大(Schmidbauer)
未使用密度遮罩进行插值毛发长进嘴巴或眼睛,子发束远离引导发束使用顶点组遮罩;分离嘴部内部区域
引导发束间距不均出现秃斑,摆姿势后更严重检查 sample_roots 间距;检查 spacing_gaps_2x
默认半径下密度过高毛发变成实心团块或“一团糟”先调整轮廓;密度为 1M/m² 时约为 0.2 mm(Thommes)
使用默认设置修剪每根发束都变成 1 m 长关闭 Replace Length(Thommes)
在卷发或发束上使用正向毛躁卷发末端被破坏,发束末端变得毛糙使用负向 Shape;对最后一个 Frizz 关闭 Cumulative Offset
使用相同种子复制图层宽发束和细发束以相同方式堆叠更改种子和频率(Bystedt)
发梢笔直“糟糕的 CG 头发”仅在发梢使用 Roll Hair Curves(Bystedt)
梳理后编辑了表面发根悬浮或陷入表面使用 snap_to_surface(hair, "DEFORM");拓扑更改后则使用 NEAREST
仅以 4% 视口密度进行评估未发现发束均匀、长度一致的问题使用完整密度渲染
在 EEVEE 中使用 Principled Hair BSDF颜色暗淡扁平(测得中心亮度为 0.09,而非 0.26)使用带有显式颜色的 Principled BSDF
通过脚本执行梳理笔触没有任何效果,返回 PASS_THROUGH写入位置,或将笔触交给用户

Blender 5.2 说明

  • Empty Hair 和 Quick Fur 会添加一个固定的 Hair Dynamics 修改器(模式为 Animation 或 Physics (Experimental))。它取代了旧的 Surface Deform,并使根部随变形表面移动(已验证形态键和骨架)。请将其保留为最后一个修改器。
  • Interpolate 没有 Surface 或 UV Map 输入;它会读取曲线对象的表面。新增输入包括 Part by Mesh Islands、Follow Surface Normal、Mask Texture 和 Resting Surface(开启)。开启 Resting Surface 后,Thommes 的“Mask modifier on the surface”补丁预览不会生效。请改用补丁顶点组作为 Density Mask,或在预览时关闭 Resting Surface。
  • 使用 md.properties.inputs.<id>.value 或 .type = 'ATTRIBUTE' 设置修改器输入。在无头模式下,求值结果会保持过期状态,直到调用 obj.update_tag()。H.set_inputs 会为你解析 UI 名称并添加标签。后台求值会应用 Viewport Amount,因此请使用 H.count(full=True)。
  • 笔刷是资产:Snake Hook 对应 Pull Tips,Selection Paint 对应 Select;Add 默认添加 8 个点,间距为 0.3 m;设置位于 brush.curves_sculpt_settings。
  • 出厂设置中的 render.hair_type 为 STRAND:请使用 STRIP,并将 hair_subdiv >= 1。Cycles 的形状包括: RIBBONS、THICK、THICK_LINEAR。“Curves Info”是 ShaderNodeHairInfo;Principled Hair 提供 Chiang 和 Huang。Hair Curves Noise 会写入 resolution 12,自 5.0 起曲线渲染时会采用该值。
  • 发片:Curve to Mesh 有一个 Scale 输入(4.5),Arc Resolution 用于统计点数。EEVEE 的 Alpha 使用 surface_render_method = 'DITHERED'。读取 obj.evaluated_geometry().mesh 时,请确保 GeometrySet 仍然有效。
  • Quick Fur 的密度会随对象大小缩放(直径 10 cm 的球体使用 MEDIUM 时:80,220/m²,每条引导曲线 12 个点)。

参考资料

  • references/expert-notes.md:用于辅助判断,按专家分类并附有时间戳(人类发型、动物皮毛、程序化皮毛、发片、网格毛发)。
  • references/procedures.md:编写代码前请先阅读。该文件包含完整且经过测试的 P1 至 P8 流程,以及 bx_hair 调用对应的原始 bpy 写法。
  • references/critique.md:审查渲染结果或报告时请加载,作为评分标准。
  • references/sources.md:用于引用或重看来源,并附有最佳时间戳。
  • scripts/bx_hair.py:工具包(已在 5.2.1 上测试)。测试位于 tests/code/blender-hair/。

评论

支持 Markdown