UE4官方文档毛发部分整合笔记

UE Groom

Unreal engine Groom hair

1、毛发渲染与模拟

groom毛发并不存在标准格式,在UE4.26中使用Alembic作为从DCC到UE的中转文件格式

Alembic是一个开源的计算机图形交换框架。Alembic将复杂的动画场景提炼成一套非程序化的、独立于应用程序的烘焙的几何结果。这种将场景提炼成烘焙的几何图形的做法,完全类似于将照明和渲染场景提炼成渲染的图像数据的做法。
Alembic专注于有效地存储复杂程序性几何结构的计算结果。他的重点不在于存储用于创建计算结果的程序性工具的复杂依赖图。例如,Alembic将有效地存储由任意复杂的动画和模拟过程产生的动画顶点位置和动画变换,这些过程可能涉及包络、修正形状、体积保留模拟、布和肉体模拟等等。
来源http://www.alembic.io/index.html

2、在项目中启用毛发

项目设置

启用支持皮肤计算缓存 (Support Compute Skin Cache)
《UE4官方文档毛发部分整合笔记》

插件浏览器

在插件浏览器中启用

  • Alembic Groom Importer
  • Groom
    《UE4官方文档毛发部分整合笔记》

3、基本流程

《UE4官方文档毛发部分整合笔记》

3.5、Alembic for Grooms规范

目标

1、定义梳理专有的非正式Alembic元数据模式,以便将毛发导入虚幻引擎。
2、检查UE4支持的毛发相关属性,并将这些属性映射到Alembic。

曲线

从标准Alembic曲线模式中读取毛发的常规形状:

Alembic::AbcGeom::ICurves

宽度

根据此规范导出的Groom属性让导入程序在构建Groom时能够检索和使用这些属性。但是,宽度属性没有特殊行为。例如,在Maya等DCC应用程序中,宽度数值直接导出到曲线行,因此不需要导出自定义的 groom_width 属性;导入程序将会把Maya的宽度数值转换成 groom_width 属性。值得注意的是,如果你的Groom中存在 groom_width 属性,那么在导入期间不会被覆盖。如果未指定 groom_width 属性,或者无法从宽度数值转换为该属性,虚幻引擎中的构建器将会后退,使用1厘米来作为宽度值。

使用以下命令可为每个ICurve存储曲线宽度:

(GeometryScope::kConstantScope)

使用以下命令可为每个曲线存储曲线宽度:

(GeometryScope::kUniformScope)

使用以下命令可为每个cv存储曲线宽度:

(GeometryScope::kVertexScope)

命名规则

属性名必须小写,不含空格或特殊字符。

所有属性必须使用以下前缀:

groom_<attr>

举例而言,groom_id、groom_color或groom_width都符合命名规则。

范围和优先权

本文档中的属性都有指定范围,该范围控制可在哪个Groom的 级别 上对属性进行定义。
可用范围包括:

范围说明
Constant针对带 AbcGeom::ICurves 对象的所有曲线,这些参数都拥有单一值。
Uniform针对 AbcGeom::ICurves 对象中的每个曲线,这些参数都拥有一个值。
Vertex针对每个cv每条曲线,这些参数都拥有一个值。

常规属性

本节介绍整体应用于梳理的属性。这些属性应添加到最顶部的节点:IXForm或ICurves。

名称类型可选说明
groom_version_majorint16用于识别此文件符合梳理方案的哪个 主要 版本1
groom_version_minorint16用于识别此文件符合方案的哪个 次要 版本4
groom_tool字符串生成此文件的工具的名称和版本。用于调试和跟踪问题
groom_properties字符串该字符串描述用于生成此梳理的参数。这些是工具专属的选项,用于调试

几何体参数

所有几何体参数都是可选的,但如果导出的Groom中没有这些参数,则会使用内置参数。

名称类型范围(Scope)可选说明范围(Range)备注
groom_ guideint8/16/32常量/统一根据导入的发束和抽取设置生成导线。0 = 无导线 / 1 = 导线
groom_group_idfloat32/64[2]统一所有发束将组合到一起。[0, INT_MAX]
groom_root_uvint8/16/32常量/统一通过将发束的根投射到球体上来计算根UV。[-FLOAT_MAX, FLOAT_MAX]此属性是可选的。如果未指定,将使用球体映射在引擎中自动生成根UV。
groom_idint32统一发束不会具有ID。此属性应在调试中使用,与 groom_closest_guides 属性搭配。[0, INT_MAX]
groom_colorfloat32/64[3]顶点缺省是黑色[0, INT_MAX]
groom_closest_guidesint32[3]统一计划专门用于在虚幻引擎外计算的插值数据。[0, INT_MAX]
groom_guide_weightsfloat32[3]统一计划专门用于在虚幻引擎外计算的插值数据。[0, FLOAT_MAX]

4、毛发材质

首先需要将将着色模型设置为毛发,然后在用途中启用使用发束(Use with Hair Strands)
《UE4官方文档毛发部分整合笔记》

4.25、生成Groom纹理

利用 Groom 资产,你可以根据导入的groom中的发束数据创建纹理。你可以为骨架网格体生成毛囊遮罩,以将毛发与其网格体表面更好地混合起来。你还可以创建多种发束纹理,以使用这些纹理创建毛发网格体或毛发方块。

流程

1、在内容浏览器中右键单击Groom资产

《UE4官方文档毛发部分整合笔记》

2、选择要创建的纹理类型:创建毛囊纹理(Create Follicle Texture) 和 创建发束纹理(Create Strands Texture)

毛囊纹理

毛囊(Follicle) 纹理包含根部的小型距离场,利用此距离场,可以从骨架网格体中捕获底层表面材质的着色器中的某些效果。生成的纹理中包含用于存储纹理信息的多个通道。你可以同时选择多个groom来填充生成的纹理中的这些通道。

选择 创建毛囊纹理(Create Follicle Texture) 时,将会打开 Groom毛囊遮罩选项(Groom Follicle Mask Options) 窗口。选择你的选项,然后单击 创建(Create) 来生成你的毛囊纹理遮罩。这些纹理将保存在与Groom资产相同的位置。
《UE4官方文档毛发部分整合笔记》

属性说明
分辨率(Resolution)毛囊遮罩的纹理分辨率。分辨率四舍五入到最接近的2的n次方大小,例如256、512和1024
根半径(Root Radius)生成的毛囊遮罩中的发束根大小,用像素来衡量

Groom

属性说明
Groom用于生成毛囊纹理遮罩的Groom资产
通道(Channel)用于将此groom的毛囊纹理遮罩存储在其中的纹理遮罩的色彩通道

发束纹理

发束(Strands) 纹理包括根据你的groom生成的多个纹理,将应用到指定的毛发网格体。

选择 创建发束纹理(Create Strands Texture) 时,将会打开 Groom发束纹理选项(Groom Strands Textures Options) 窗口。选择你的选项,然后单击 创建(Create) 来生成你的发束纹理。这些纹理将保存在与Groom资产相同的位置。
《UE4官方文档毛发部分整合笔记》

属性说明
分辨率(Resolution)所生成的发束纹理(切线、不透明度、深度和属性)的纹理分辨率。分辨率四舍五入到最接近的2的n次方大小,例如256、512和1024。
追踪类型(Trace Type)选择在生成发束纹理时要为投影执行的追踪方向。
  • 向外追踪(Trace Outside) 从网格体的表面向外部执行追踪。这对于面部毛发非常有效。
  • 向内追踪(Trace Inside) 从网格体的表面向内部执行追踪。这对于毛发groom非常有效。
  • 双向追踪(Trace Bidirectional) 在两个方向上(内部和外部)执行追踪。
追踪距离(Trace Distance)与网格体表面之间的距离,超过此距离后,会将发束投影到网格体上。
网格体类型(Mesh Type)选择用于追踪的输入网格体类型:静态网格体(Static Mesh) 或 骨架网格体(Skeletal Mesh)。
静态网格体(Static Mesh)groom发束将投影至该静态网格体资产,以生成纹理。这要求你将 网格体类型(Mesh Type) 设置为 静态网格体(Static Mesh)
骨架网格体(Skeletal Mesh)groom发束将投影至该静态网格体资产,以生成纹理。这要求你将 网格体类型(Mesh Type) 设置为 骨架网格体(Skeletal Mesh)。
LOD索引(LOD Index)将在其上执行纹理投影的细节层次网格体索引。
分段索引(Section Index )将在其上执行纹理投影的网格体分段。
UV通道索引(UV Channel Index)用于纹理投影的UV通道索引。
组索引(Group Index)应烘焙到纹理中的groom索引。数组变空之后,默认包括所有组。

结果可以产生多种纹理资产,包括深度、特性、不透明度和切线,这些资产可以应用至毛发网格体。以下是从groom贴到毛发网格体的两个示例纹理输出。
《UE4官方文档毛发部分整合笔记》

4.5、毛发资产编辑器

Groom毛发主要用于处理Alembic文件中的毛发发束,但同时也支持发片网格体等形式
毛发资产编辑器管理毛发的内容,修改毛发的不同部分,确定渲染和物理模拟方式,管理创建LOD

显示(Show)

在毛发资产编辑器的视口中,与其他资产编辑器不同的主要是Show选项
《UE4官方文档毛发部分整合笔记》

属性说明
导线(Guide)显示用于模拟的导线。
导线影响(Guide Influence)以彩色显示模拟中的毛发聚丛(所有受某根导线影响的发束)。
UV显示每个发束的UV。
根UV(Root UV)显示每个发束根部的UV。
根UDIM(Root UDIM)在每个发束的根部显示UDIM。
尺寸(Dimension)显示用于模拟的导线。
种子(Seed)(用彩色)显示每个发束使用的随机种子。
半径差异(Radius Variation)(用彩色)显示发束的大小。蓝色表示较细的发束。黄色表示较粗的发束。
底色(Base Color)显示每个顶点存储的底色。如果建模应用导出的毛发不包含底色,发束将显示为黑色。
粗糙度(Roughness)显示每个顶点存储的粗糙度。如果建模应用导出的毛发不包含粗糙度,发束将显示为黑色。
Vis群集(Vis Cluster)显示用于剔除和细节层次用途的毛发群集。
发片导线(Cards Guide)

细节面板

1、细节层次

控制毛发在各个细节层级上的删减,控制LOD在何种屏幕尺寸更改,以及使用哪种类型的几何体结构来表示
《UE4官方文档毛发部分整合笔记》

属性说明
曲线删减(Curve Decimation)通过减少发束数量来删减毛发。移除的发束是从导入的毛发发束中随机选择的。
顶点删减(Vertex Decimation)通过移除发束上的顶点来删减毛发。
角阈值(Angular Threshold)定义了删除顶点时,两个连续发束片段之间的最大角度值。数值越大,删减就越多。
屏幕尺寸(Screen Size)LOD在低于该屏幕尺寸后将会被启用。
厚度缩放(Thickness Scale)你可以增加发束的厚度,以弥补被删除的发束曲线。厚度缩放值负责控制计算补偿时所用的自动缩放值。
可视性(Visible)切换此LOD的可视性。
几何体类型(Geometry Type)设置将使用哪种类型的几何体来呈现此细节层次。在以下选项中进行选择:发束(Strands)发片(Cards)网格体(Meshes)
发簇世界尺寸(Cluster World Size)定义发簇的平均大小(在世界空间中)。毛发会被划分成多个发簇,以便LOD的选择和剔除更加精细。
发簇屏幕尺寸缩放(Cluster Screen Size Scale)缩放发簇的投影屏幕(projected screen),以便微调其细节层次选择。

LOD选择类型(LOD Selection Type):CPU较为粗糙GPU较为精细
最低LOD(Minimum LOD):指定烘焙的最低LOD,或者用增加设置各平台的最低LOD
禁用低于最低LOD时删除(Disable Below Min LOD Stripping):设置一个标记,覆盖在LOD低于 最低 LOD(Minimum LOD) 时删除LOD的操作,影响范围是全平台。或用 增加(Plus) 按钮来指定平台设置。

2、插值

修改毛发导入时的属性设置
《UE4官方文档毛发部分整合笔记》
毛发组(Hair Group)

属性说明
曲线删减(Curve Decimation)通过减少发束数量来删减毛发。移除的发束是从导入的毛发发束中随机选择的。
顶点删减(Vertex Decimation)通过移除发束上的顶点来删减毛发。
覆盖导线(Override Guides)启用后会覆盖导入的导线,并选择发束的一个子集作为导线。
毛发导线密度(Hair to Guide Density)定义用作导线的发束的比率。
插值质量(Interpolation Quality)定义将导线动作插值到发束上时,插值的质量。
插值距离(Interpolation Distance)定义用于将导线和发束配对在一起时的距离。
随机化导线(Randomize Guide)启用后,用于插值的导线将会轻度随机化,以避免可能发生的毛发聚丛。
顶点删减(Vertex Decimation)通过移除发束上的顶点来删减毛发。
用户唯一导线(User Unique Guide)启用后,可以使用单一导线来执行动作插值。

差值
启用全局插值(Enable Global Interpolation)
启用后,使用径向基函数进行插值,而不是使用本地蒙皮刚体变换( local skin rigid transform)。
毛发插值类型(Hair Interpolation Type)
选择将毛发绑定到骨架网格体时,要使用的插值类型:

  • 刚体变换(Rigid Transform):插值过程中,仅会平移最接近根部的皮肤三角形。

  • 偏移变换(Offset Transform):插值过程中,仅会平移最接近根部的皮肤三角形。

  • 平滑变换(Smooth Transform):插值过程中,会平移最接近根部的皮肤三角形,同时会基于导线计算出平滑旋转。

3、发束面板

《UE4官方文档毛发部分整合笔记》

属性说明
材质(Material)用于展现发片使用不同LOD时的材质。
毛发宽度(Hair Width)更改发束大小。此数值对应发束的最大宽度。默认数值来自于导入的毛发。
毛发根部缩放(Hair Root Scale)控制毛发根部的缩放从底端到顶端
毛发顶部缩放(Hair Tip Scale)控制毛发顶部的缩放从顶端到底端
毛发剪断缩放(Hair Clip Scale)在距发束根部一定距离处剪断毛发。
毛发阴影密度(Hair Shadow Density)缩放毛发密度,使毛发上的阴影和透射效果均匀地变弱或变强。
毛发光线追踪半径缩放(Hair Raytracing Radius Scale)在使用光线追踪阴影时缩放发束的宽度。
体素化(Voxelize)启用后,对毛发束进行体素化处理,从而提供更加准确的光照计算。
使用稳定光栅化(Use Stable Rasterization)启用后,发束的噪点更少,但可能显得有点厚。
散射场景光照(Scatter Scene Lighting)启用后,发束会使用下方的场景光照作为光源。此属性适用于非常短的毛发,例如人体毫毛。

4、发片面板

设置发片使用的几何体和纹理,并选择使用引擎生成的的发片或是使用导入的发片
《UE4官方文档毛发部分整合笔记》

属性说明
材质(Material)用于发片呈现LOD的指定材质
源类型(Source Type)选择要使用的发片类型 基于程序化生成(实验性)(Procedural (Experimental))基于导入(Imported)
程序性网格体(Procedural Mesh)程序化发片几何体引用的网格
导入的网格(Imported Mesh)导入的发片几何体引用的网格

Textures

深度纹理(Depth Texture)用于发片资产的深度纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点。
覆盖纹理(Coverage Texture)用于发片资产的覆盖纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点。
切线纹理(Tangent Texture)用于发片资产的切线纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Attributes node节点。
属性纹理(Attribute Texture)用于发片资产的特性纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点。
辅助数据纹理(Auxiliary Data Texture)此辅助纹理允许为发片资产传输用户数据。这是可选的纹理,一旦设置,其值会转发到材质编辑器中的 Hair Attributes 节点。
组索引(Group Index)将此发片的几何体映射到的组索引
LOD索引(LOD Index)应使用此发片资产的LOD索引

5、程序化生成设置(实验性)

《UE4官方文档毛发部分整合笔记》
几何体设置(Geometry Settings)

属性说明
生成类型(Generation Type)选择是使用导线还是发束来生成发片,选择发束时,将使用随机选择方式来生成发片
发片计数(Cards Count)在生成类型(Generation Type)中设置为发片计数(Cards Count)时,生成发片的数量
发簇类型(Cluster Type)定义如何组合块来生成发片,“高”将创建更加完善的块,但速度更慢
最小片段长度(Min Segment Length)控制毛发顶部的缩放从顶端到底端
角阈值(Angular Threshold)定义两个连续发片片段之间的最大角度值。较高的数值可以减少发片删减的几何复杂程度。
最小发片长度(Min Cards Length)将移除长度小于此阈值的发片
最大发片长度(Max Cards Length)将移除长度大于此阈值的发片

纹理设置

属性说明
图集最大分辨率(Atlas Max Resolution)生成的发片图集的最大分辨率,此数值仅是发片生成器的建议值,并非强制要求
每厘米像素(Pixel Per Centimeters)设置用于生成发片图谱的像素密度(或精度)
长度纹理计数(Length Texture Count)要生成的聚丛变体数量

6、网格体面板

网格体面板负责管理毛发资产中各个LOD使用的网格体几何体。此面板会列出所有网格体几何体,但并非所有列出的几何体都是必须使用的。
《UE4官方文档毛发部分整合笔记》

属性说明
材质(Material)用于发片呈现LOD的指定材质
导入网格体(Imported Mesh)要引用的指定网格体几何体

纹理

属性说明
深度纹理(Depth Texture)用于发片资产的深度纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点
覆盖纹理(Coverage Texture)用于发片资产的覆盖纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点
切线纹理(Tangent Texture)用于发片资产的切线纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点
特性纹理(Attribute Texture)用于发片资产的特性纹理。此纹理是可选的,但一旦设置,其值会转发到材质编辑器中的Hair Attributes节点
辅助数据纹理(Auxiliary Data Texture)此辅助纹理允许为发片资产传输用户数据。这是可选的纹理,一旦设置,其值会转发到材质编辑器中的 Hair Attributes 节点
组索引(Group Index)要引用的指定网格体几何体
导入网格体(Imported Mesh)将此发片的几何体映射到的组索引
LOD索引(LOD Index)应使用此发片资产的LOD索引

LOD

属性说明
最低LOD(Minimum LOD)
指定要为所有平台调配的最低细节LOD,或通过使用 增加(Plus) 按钮来增加LOD,为各个平台指定具体最小值

7、材质

材质(Materials) 面板定义了毛发资产可以使用的材质。

使用 添加(Add) (+)按钮添加新材质引用。在”插槽名称(Slot Name)”中输入材质的名称,否则将使用指定的默认材质名称。
《UE4官方文档毛发部分整合笔记》
发束(Strands)、网格体(Meshes)和发片(Cards) 面板中的 材质(Material) 插槽允许你从引用的材质中进行选择。
《UE4官方文档毛发部分整合笔记》

8、物理

物理(Physics) 面板提供了多种设置,可用于启用物理模拟以及修改毛发的运动行为。
《UE4官方文档毛发部分整合笔记》
解算器设置

属性说明
启用模拟(Enable Simulation)为毛发资产启用物理模拟
Niagara解算器(Niagara Solver)选择要用于模拟的Niagara解算器。从 Cosserate Rods、角弹簧(Angular Springs) 和 自定义解算器(Custom Solver) 中选择
自定义系统(Custom System)若Niagara解算器设置为自定义解算器,则添加要使用的自定义Niagara系统
子步骤(Sub Steps)每帧要完成的子步骤数。实际的解算器调用以每秒24帧的速度完成
迭代计数(Iteration Count)用xpbd解算器解算约束的迭代数。
组索引(Group Index)要引用的指定网格体几何体

外力

属性说明
重力矢量(Gravity Vector)用于重力的加速度矢量,测量单位为cm/s2
空气阻力(Air Drag)0到1之间的系数,用于空气阻力
空气速度(Air Velocity)周围空气的速度,单位为cm/s

材质约束:弯曲约束

属性说明
解算弯曲(Solve Bend)在xpbd循环期间启用弯曲约束的解算
投影弯曲(Solve Bend)在xpbd循环后启用弯曲约束的投影
弯曲阻尼(Bend Damping)对弯曲约束施加的介于0到1之间的阻尼
弯曲刚度(Bend Stiffness)弯曲约束的刚度,单位为GPa
刚度范围(Stiffness Scale)该曲线可确定每个束的弯曲刚度。X轴范围是0,1。0映射到根部,1映射到梢部

材质约束:拉伸约束

属性说明
解算拉伸(Solve Stretch)在xpbd循环期间启用拉伸约束的解算
投影拉伸(Project Stretch)在xpbd循环后启用拉伸约束的投影
拉伸阻尼(Stretch Damping)约束介于0到1之间的阻尼
拉伸刚度(Stretch Stiffness)拉伸约束的刚度,单位为GPa
刚度范围(Stiffness Scale)该曲线可确定每个发束的拉伸刚度。X轴范围是0,1。0映射到根部,1映射到梢部

材质约束:碰撞约束

属性说明
解算碰撞(Solve Collision)在xpbd循环期间启用碰撞约束的解算
投影碰撞(Project Collision)在xpbd循环后启用碰撞约束的投影
静态摩擦(Static Friction)用于物理资产碰撞的静态摩擦
动态摩擦(Kinectic Friction)用于物理资产碰撞的动态摩擦
束粘度(Strands Viscosity)用于自碰撞的介于0和1之间的粘度
网格有效维度(Grid Dimensions)用于计算粘度力的网格有效维度
碰撞半径(Collision Radius)用于物理资产碰撞检测的半径
半径范围(Radius Scale)该曲线可确定每个发束的碰撞半径。X轴范围是0,1。0映射到根部,1映射到梢部

发束参数

属性说明
发束大小(Strands Size)用于模拟的每根导线上的粒子数
发束密度(Strands Density)束密度,测量单位为g/cm3
发束平滑(Strands Smoothing)传入导线曲线介于0至1之间的平滑度,旨在提升稳定性
发束厚度(Strands Thickness)束厚度(单位为厘米),用于计算质量和惯性
厚度范围(Thickness Scale)该曲线可确定每个束的束厚度。X轴范围是0,1。0映射到根部,1映射到梢部

4.75、毛发创建Xgen指南

转换旧有XGen说明

将导线转换为Numbs曲线

请参考下列步骤将Groom的导线转化为曲线,以便保存一组曲线并匹配你要转换的导线。
1、从主菜单中,点击 生成(Generate) 下拉列表并选择 XGen编辑器(XGen Editor)。
2、在 XGen 窗口中,使用 工具(Utilities) 选项卡选择 曲线的导线(Guides to Curves)。
《UE4官方文档毛发部分整合笔记》
3、点击创建曲线。
完成后,groom的输出将类似下图:
《UE4官方文档毛发部分整合笔记》

将Groom转换为XGen交互式Groom

若使用旧版XGen说明,需将groom转换为 XGen交互式Groom(XGen Interactive Groom)。步骤如下:
1、选择XGen Description节点。
《UE4官方文档毛发部分整合笔记》
2、在 建模(Modeling) 菜单集中使用主菜单点击 生成(Generate) 下拉列表,然后选择 转换为交互式Groom(Convert to Interactive Groom)

将样条说明导出到NURBS曲线

1、选中你的XGen Spline Description节点。在 建模(Modeling) 菜单集中使用主菜单点击 生成(Generate) 下拉列表。然后在列表中选择 缓存(Cache)> 导出缓存(Export Cache)
请遵循以下步骤,将你选中的样条说明导出成Alembic文件,该文件可以与插入的头发一起导入为NURBS曲线。
2、在 导出缓存(Export Cache) 窗口中进行以下设置:

  • 缓存时间帧(Cache Time Frame): 设置成 当前帧(Current Frame)
  • 多个变换(Multiple Transforms): 禁用
  • 写入最终宽度(Write Final Width): 启用
    《UE4官方文档毛发部分整合笔记》

创建属性

创建组ID属性

可在一个或多个组中导出内插毛发。虚幻引擎中可识别此类组,用于唯一材质指定。

创建组ID属性时使用以下脚本:

from maya import cmds

attr_name = 'groom_group_id'

# 注意:更改以下命名以反映节点场景。
groups = ['hair_brows_splineDescription1|SplineGrp0', 'hair_lashes_splineDescription1|SplineGrp0', 'hair_head_splineDescription1|SplineGrp0']

for groom_group_id, group_name in enumerate(groups):

    # 获取xgGroom下的曲线
    curves = cmds.listRelatives(group_name, ad=True, type='nurbsCurve')

    # 用组id标记组
    cmds.addAttr(group_name, longName=attr_name, attributeType='short', defaultValue=groom_group_id, keyable=True)

    # 添加属性范围
    # 强制Maya的alembic将数据导出为GeometryScope::kConstantScope
    cmds.addAttr(group_name, longName='{}_AbcGeomScope'.format(attr_name), dataType='string', keyable=True)
    cmds.setAttr('{}.{}_AbcGeomScope'.format(group_name, attr_name), 'con', type='string')

创建导线属性

当你为groom创建导线属性时,只有标记为 导线(guide) 的曲线才会被用于虚幻引擎中的模拟。若未在Alembic文件中指定导线,在导入UE4的过程中,一定比例的内插毛发将被内部标记为导线。

创建导线属性时使用以下脚本:

from maya import cmds

attr_name = 'groom_guide'

# 获取xgGroom下的曲线
curves = cmds.listRelatives('xgGroom', ad=True, type='nurbsCurve')

# 新建组
guides_group = cmds.createNode('transform', name='guides')

# 将组标记为groom_guide
cmds.addAttr(guides_group, longName=attr_name, attributeType='short', defaultValue=1, keyable=True)

# 强制Maya的alembic将曲线导出为一个组。
cmds.addAttr(guides_group, longName='riCurves', attributeType='bool', defaultValue=1, keyable=True)

# 添加属性范围
# 强制Maya的alembic将数据导出为GeometryScope::kConstantScope
cmds.addAttr(guides_group, longName='{}_AbcGeomScope'.format(attr_name), dataType='string', keyable=True)
cmds.setAttr('{}.{}_AbcGeomScope'.format(guides_group, attr_name), 'con', type='string')

# 导线组下方的父曲线
对于曲线中的曲线:
    cmds.parent(curve, guides_group, shape=True, relative=True)

Groom_Width属性
在Maya中,宽度值有一个特殊的行为,与其他DCC应用不同的是,它可以遵循Alembic以及Grooms规格中的内容,来获取它们并使用它们来构建groom。

Maya可以直接在曲线上导出宽度值,因此不需要导出自定义的 groom_width 属性;导入器会自动将这些值转换为该属性。如果 groom_wdith 属性在导入虚幻引擎时与groom一起存在,则它不会被覆盖。如果 groom_wdith 没有被指定,或者不能从宽度值转换,那么生成器将默认使用1厘米。

将纹理应用于毛发UV

以下步骤和包含脚本可以帮助你设置自己的XGen毛发,该毛发可以导出到虚幻引擎,并且各个发束上呈现已应用的纹理。
1、在Maya的建模菜单中,选择 生成(Generate) > 创建交互式Groom样条(Create Interactive Groom Splines)。
《UE4官方文档毛发部分整合笔记》
2、你可以根据自己的偏好为项目创建导线并涂刷毛发。准备就绪后,选择 生成(Generate)> 缓存(Cache)> 创建新缓存(Create New Cache) 将曲线导出为 Alembic缓存(Alembic Cache)。
3、通过隐藏或删除XGen头发以将其移除。然后,在Maya场景中,使用源网格体重新导入之前导出的毛发曲线。
《UE4官方文档毛发部分整合笔记》
4、根据你的场景,顶部曲线下将有数千条样条曲线,本例中为 SplineGrp0。编辑以下Python脚本,并将以下值替换为项目中的值:

  • export_directory
  • hair_file
  • curve_top_group
  • uv_mesh
from maya import cmds
from maya import OpenMaya
import os

def create_root_uv_attribute(curves_group, mesh_node, uv_set='map1'):
    ''' Create "groom_root_uv" attribute on group of curves. '''

    # check curves group
    if not cmds.objExists(curves_group):
        raise RuntimeError('Group not found: "{}"'.format(curves_group))

    # get curves in group
    curve_shapes = cmds.listRelatives(curves_group, shapes=True, noIntermediate=True)
    curve_shapes = cmds.ls(curve_shapes, type='nurbsCurve')
    if not curve_shapes:
        raise RuntimeError('Invalid curves group. No nurbs-curves found in group.')
    else:
        print "found curves"
        print curve_shapes

    # get curve roots
    points = list()
    for curve_shape in curve_shapes:
        point = cmds.pointPosition('{}.cv[0]'.format(curve_shape), world=True)
        points.append(point)

    # get uvs
    values = list()
    uvs = find_closest_uv_point(points, mesh_node, uv_set=uv_set)
    for u, v in uvs:
        values.append([u, v, 0])
        #print (str(u) + " , " + str(v) )

    # create attribute
    name = 'groom_root_uv'
    cmds.addAttr(curves_group, ln=name, dt='vectorArray')
    cmds.addAttr(curves_group, ln='{}_AbcGeomScope'.format(name), dt='string')
    cmds.addAttr(curves_group, ln='{}_AbcType'.format(name), dt='string')

    cmds.setAttr('{}.{}'.format(curves_group, name), len(values), *values, type='vectorArray')
    cmds.setAttr('{}.{}_AbcGeomScope'.format(curves_group, name), 'uni', type='string')
    cmds.setAttr('{}.{}_AbcType'.format(curves_group, name), 'vector2', type='string')

    return uvs

def find_closest_uv_point(points, mesh_node, uv_set='map1'):
    ''' Find mesh UV-coordinates at given points. '''

    # check mesh
    if not cmds.objExists(mesh_node):
        raise RuntimeError('Node not found: "{}"'.format(mesh_node))

    # check uv_set
    uv_sets = cmds.polyUVSet(mesh_node, q=True, allUVSets=True)
    if uv_set not in uv_sets:
        raise RuntimeError('Invalid uv_set provided: "{}"'.format(uv_set))

    # get mesh as dag-path
    selection_list = OpenMaya.MSelectionList()
    selection_list.add(mesh_node)

    mesh_dagpath = OpenMaya.MDagPath()
    selection_list.getDagPath(0, mesh_dagpath)
    mesh_dagpath.extendToShape()

    # get mesh function set
    fn_mesh = OpenMaya.MFnMesh(mesh_dagpath)

    uvs = list()
    for i in range(len(points)):

        script_util = OpenMaya.MScriptUtil()
        script_util.createFromDouble(0.0, 0.0)
        uv_point = script_util.asFloat2Ptr()

        point = OpenMaya.MPoint(*points[i])
        fn_mesh.getUVAtPoint(point, uv_point, OpenMaya.MSpace.kWorld, uv_set)

        u = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_point, 0, 0)
        v = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_point, 0, 1)

        uvs.append((u, v))

    return uvs

def abc_export(filepath, node=None, start_frame=1, end_frame=1, data_format='otawa', uv_write=True):

    job_command = '-frameRange {} {} '.format(start_frame, end_frame)
    job_command += '-dataFormat {} '.format(data_format)

    job_command += '-attr groom_root_uv '

    if uv_write:
        job_command += '-uvWrite '

    job_command += '-root {} '.format(node)   

    job_command += '-file {} '.format(filepath) 

    cmds.AbcExport(verbose=True, j=job_command)

def main():

    export_directory = 'D:/Dev/Ref'
    hair_file = os.path.join(export_directory, 'hair_export.abc')
    curve_top_group= 'description1|SplineGrp0'
    uv_mesh='pPlane1'

    create_root_uv_attribute( curve_top_group , uv_mesh)
    abc_export(hair_file, curve_top_group)

main()

5、在Maya中,使用更改后的数值运行脚本。这 将 生成一个新的Alembic(’.abc’)文件,该文件可以导入到虚幻引擎中。
6、在虚幻引擎中,使用 毛发 着色模型创建新材质。在材质图表中,添加 毛发属性(Hair Attributes) 表达式,然后将 根UV(Root UV) 插入纹理样本的 UV 输入中。

groom_root_uv 属性为每个毛发指定了它所连接的底层网格UV。这个属性是可选项,如果没有指定,引擎会使用球面贴图自动生成一个根UV。

7、将导入的毛发Alembic文件从内容浏览器拖到关卡中,然后向其指定毛发材质。你应该以如下形式结束:

确保关卡中的毛发Alembic文件的宽度大于0。

《UE4官方文档毛发部分整合笔记》

5、绑定毛发

绑定资产用于将Groom组件添加并蒙皮到骨骼网格体上。通过这种方法,Groom可以指定给需要用到它的骨骼网格体,还能指定给享有相同拓扑的骨骼网格体,也可以不预先绑定到网格体上,但会在使用时实时投射造成较高的GPU消耗。

要创建绑定需要在内容浏览器中右键点击 Groom资产(Groom Asset) 并在快捷菜单中选择 创建绑定(Create Binding)。在创建绑定时,请使用 Groom绑定选项(Groom Binding Options) 窗口指定 目标骨骼网格体(Target Skeletal Mesh) 和 源骨骼网格体(Source Skeletal Mesh)。

6、毛发物理与nigara

要对角色毛发应用物理效果,可打开Groom资产,并在 毛发物理效果(Hair Physics) 分类下的解算器设置(Solver Settings)中勾选 启用模拟(Enable Simulation)。
《UE4官方文档毛发部分整合笔记》

7、毛发控制台命令

r.HairStrands.DebugMode

号码效果
0关闭
1群集信息
2所有DOM光源边界
3屏幕投影群集
4深度不透明贴图
5亚像素样本计数
6TAA解析类型(常规/响应)
7毛发覆盖类型
8毛发密度体积
9毛发切线体积
10毛发底色体积
11毛发粗糙度体积
12毛发网格体投影
13毛发覆盖

r.HairStrands.StrandMode

号码效果
0关闭
1模拟发束
2渲染发束影响
3根UV
4根UV UDIM纹理索引
5毛发UV
6毛发种子
7毛发尺寸
8毛发半径变体
9毛发顶点颜色
10毛发顶点粗糙度

8、已知限制

  1. 帧率取决于groom大小、分辨率,以及采用的底层硬件。例如,对于1080p的人类groom,底层硬件应为2080Ti,帧率30Hz或更高。
  2. 视图模式尚不支持毛发。
  3. 多视图(毛发在多个开放窗口上可见)尚不受支持,或会导致出现瑕疵。
    原文作者:康米主义~
    原文地址: https://blog.csdn.net/qq_31175907/article/details/119031903
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞