跳转到内容
CRUSHFORMV1.1.0
在 Fab 上获取

集成材质与着色器

材质与着色器

每个发生形变的车身、车轮、玻璃板和轮胎都由材质绘制。插件提供移动顶点、绘制磨损和绘制污垢的函数,并为每个网格提供它在图集中找到位置所需的数据。本页是这些部分的参考。关于接线的逐步讲解(其中包括一个涂漆车身的十处连接),请见快速入门。其背后的思路请见核心概念中的材质部分。

所有函数都位于插件内容的 Materials 文件夹 /Crushform/Materials 中。它们的输入和输出即材质或外观所连接的引脚。引脚名称必须完全一致,包括空格。

函数输入输出构建器
MF_CF_DeformNormal、Crumple Tiling、Fold Amplitude、Fold Wavelength、Fine Fold Wavelength、Fine Fold StrengthWorld Position Offset、Normal、Wear Depth、ScratchUCFContentLibrary::BuildDeformFunction
MF_CF_PaintBase Color、Roughness、Metallic、Wear Depth、Primer Color、Metal Color、Scratch Tiling、Dust Color、Mud Color、Dirt Strength、Snow Color、Built-in Look、Scratch、Scratch Line TilingBase Color、Roughness、MetallicBuildPaintFunction
MF_CF_DirtAmount无Dust、Mud、Snow、Wet、Dirt Fresh、Dirt Ranks、Pattern Position、Pattern NormalBuildDirtAmountFunction
MF_CF_WheelDirtBase Color、Roughness、Metallic、Dust Color、Mud Color、Dirt Strength、Snow Color、Built-in LookBase Color、Roughness、MetallicBuildWheelDirtFunction
MF_CF_WheelDirtAmount无Dust、Mud、Snow、Wet、Dirt Ranks、Pattern Position、Pattern NormalBuildWheelDirtAmountFunction
MF_CF_GlassCrackBase Color、Opacity、Roughness、Normal、Built-in LookBase Color、Opacity、Roughness、NormalBuildGlassCrackFunction
MF_CF_GlassCrackData无Crack Mask、Crack Frost、Crack Tilt、Crack 0 至 Crack 3、Crack Radii、Pane U、Pane VBuildGlassCrackDataFunction
MF_CF_TireDeformAxleAxis、HalfWidth、BulgeAmount、RimRadius、RimFalloff、FlattenScale、MaxVertDispResultBuildTireDeformFunction
MF_CF_TrunkBend插件代码不设置世界空间的 World Position Offset在编辑器中制作,不由代码生成

MF_CF_Deform 在切线空间中工作,因此已接线材质的法线也必须是切线空间的。MF_CF_Paint 和 MF_CF_WheelDirt 带有 Built-in Look 开关,它是一个默认为 true 的静态布尔值。外观设置会使用该开关,如下文“外观”一节所述。

轮胎材质有一个标量参数 RimRadius,即轮辋半径,单位为网格单位。MF_CF_TireDeform 把它作为输入,UCFTireComponent 读取同一个参数,以知道可以把车轮从障碍物推开多远。轮胎网格体上第一个自身设置了 RimRadius 的材质槽优先,因此只继承母材质默认值的轮辋材质不会盖过轮胎自己的值。如果没有槽设置它,则由第一个带有该参数的槽提供其默认值。UCFTireProfile::RimRadiusOverride(单位厘米)会取代它。

MF_CF_TrunkBend 使树干弯曲。其自身描述写道:“Parabolic trunk bow driven by CPD 0..2; outputs world-space WPO”。它的两个母材质会将其加在风力偏移之后。

构建器会在编辑器中从头重建函数。它们按名称保留引脚 ID,且不会保存函数。重建后请保存该函数。

MF_CF_Deform 作为一个函数节点,带有六个输入和四个输出。
资产作用
/Crushform/Materials/M_CF_VehiclePaint漆面母材质:Clear Coat,在设置了 Paint Mask 的区域,Paint Color 覆盖 Base Texture
/Crushform/Materials/M_CF_Wheel车轮母材质:Default Lit,经由 MF_CF_WheelDirt,并受开关 Tire Deform 控制
/Crushform/Materials/M_CF_GlassShard玻璃碎片所用的半透明清透玻璃
/Crushform/Materials/MPC_CF_Dirt污垢外观,由每个车身和车轮共享。其参数由污垢函数读取
/Crushform/Atlas/RT_CF_LatticeAtlas晶格图集。每个发生形变的网格都在其中找到自己的槽位
/Crushform/Atlas/RT_CF_DirtAtlas 和 RT_CF_DirtFreshAtlas污垢图集,尺寸与晶格图集相同
/Crushform/Atlas/RT_CF_ScratchAtlas划痕图集:大小与晶格图集相同的 RG8 渲染目标,保存每个点的划痕线覆盖度和方向

母材质的贴图来自插件的 T_CF_Default* 贴图,每张贴图都有一个普通参数和一个虚拟参数。参数名称是固定的。材质实例通过名称设置它们,因此重命名任何一个参数都会使设置该参数的每个实例失效。

每个网格都在自定义基元数据中携带自己的数据,数据分块存放,由材质函数读取。各数据块的偏移量是 Project Settings > Plugins > Crushform > Atlas 中的项目设置。在 Unreal Engine 5.6 至 5.8 中,一个基元有 36 个浮点数(FCustomPrimitiveData::NumCustomPrimitiveDataFloats)。

数据块偏移设置浮点数默认偏移内容
形变网格UCFSettings::CustomDataOffset180图集槽位、网格到根的变换各列、平移、单元格尺寸的倒数、量化值和分辨率
车轮UCFSettings::WheelCustomDataOffset234两个整数:灰尘和泥浆的数量,以及雪和湿润的数量,连同各层的等级
玻璃板UCFSettings::GlassCustomDataOffset1618四条裂纹记录,每条四个浮点数
轮胎UCFSettings::TireCustomDataOffset320四条接触记录,每条八个浮点数

形变数据块依次包含:索引 0 处的图集槽位;索引 1 至 9 处网格到根的旋转与缩放的三列;索引 10 至 12 处晶格空间中的网格原点;索引 13 至 15 处单元格尺寸的倒数;索引 16 处的量化值;以及索引 17 处打包后的分辨率。MF_CF_Deform 读取的索引相同,因此布局由代码决定,而不由资产决定。

Atlas
AtlasRT_CF_LatticeAtlas
Slot Width256
Slot Height8
Custom Data Offset0
Wheel Custom Data Offset34
Tire Custom Data Offset0
Glass Custom Data Offset18
Scratch AtlasNone
项目设置中 Plugins > Crushform 下的 Atlas 分组。

使用默认值时,形变网格的数据块位于 0 至 17,玻璃板位于 18 至 33,车轮位于 34 至 35。轮胎有自己的 0 至 31,它从不与车身共用网格。

插件会拒绝放不下或与其他数据块重叠的数据块。玻璃数据块必须能放入基元,并与形变数据块保持不重叠。轮胎数据块必须能放下,并与车轮数据块保持不重叠。被拒绝的玻璃偏移会以错误形式记录,玻璃板也不会产生裂纹:

%s: Glass Custom Data Offset %d does not fit beside the deformed block at Custom Data Offset %d; the panes get no cracks

数据块移动时,烘焙了其索引的材质函数必须重建。当你在项目设置中更改四个偏移量之一时,编辑器会自动执行此操作。它会重建烘焙这些索引的八个函数:MF_CF_Deform、MF_CF_Paint、MF_CF_DirtAmount、MF_CF_WheelDirt、MF_CF_WheelDirtAmount、MF_CF_TireDeform、MF_CF_GlassCrack 和 MF_CF_GlassCrackData。编辑器中的提示内容如下:

Crushform: the Custom Data Offsets are in the material functions. Save the Crushform material functions to keep them.

重建结果不会自动保存。请保存这些函数,否则编辑器重新加载时旧索引会恢复。当八个函数中的任何一个在 Material Editor 中打开时,编辑器不会重建其中任何一个。控制台命令 Crushform.RebakeOffsets 可手动执行相同的重建,且仅存在于编辑器中。

接线用于将材质连接到插件。由以下三个步骤完成:

  1. 顶点偏移和法线经过 MF_CF_Deform。
  2. 基础颜色、粗糙度和金属度经过 MF_CF_Paint。对于与车身共享网格的玻璃和内饰,不要传入任何漆面函数。它们会随车身一同凹陷,并保留各自的外观。
  3. 材质的 Max World Position Offset Displacement 会被提高到你传入的值。

涂漆材质还会获得标量 CF_PaintWear,默认值为 1。与车身母材质共享、但不应磨损的材质实例将其设为 0。对于 /Crushform/ 和 /Engine/ 之外的材质,接线还会为其应用项目的外观。

在 Python 中,编辑器提供了相同的调用:

import unreal
material = unreal.load_asset(MATERIAL_PATH) # the material to wire, in your project
deform = unreal.load_asset("/Crushform/Materials/MF_CF_Deform")
paint = unreal.load_asset("/Crushform/Materials/MF_CF_Paint")
bound = 60.0 + unreal.CFContentLibrary.get_default_fold_amplitude()
unreal.CFContentLibrary.wire_material(material, deform, paint, bound)

将 60.0 替换为你的配置文件的 Max Displacement。褶皱幅度来自函数,而不是配置文件。

同一调用也是编辑器模块的一个蓝图函数,因此编辑器工具蓝图可以调用它。下方的图表为材质接线,其中默认褶皱幅度被加到 Max Displacement 上。其 A 引脚保存 60 厘米,即 UCFProfile::MaxDisplacement 的类默认值。请将其设为你的配置文件的值。材质本身放入 Material 引脚,该图表将其留给你自行设置。

该图表为材质接线,其中默认褶皱幅度被加到 Max Displacement 上。

当材质使用世界空间法线,或使用材质属性却没有任何来源为其提供数据时,接线会被拒绝,材质保持原样。日志会在每种情况下写明该材质的名称。

Nanite 与 Max World Position Offset Displacement

Section titled “Nanite 与 Max World Position Offset Displacement”

材质的 Max World Position Offset Displacement 是一个边界。渲染器用它判断网格的顶点最多可能移动多远。该边界必须至少等于配置文件的 Max Displacement 加上材质的褶皱幅度。褶皱会使顶点移动到凹陷之外。默认褶皱幅度为 3 厘米(CFContent::DefaultFoldAmplitude),get_default_fold_amplitude() 返回的就是它。

在 Nanite 中,这一边界更加重要。簇剔除会以此扩大其包围盒,因此过短的边界会导致渲染器剔除屏幕边缘处的凹陷面板。接线时若边界过小,会将其提高。已有自身偏移和边界的材质,会把位移量加到其边界上。只有在不接线时才需要手动设置。

轮胎母材质保持 Always Evaluate WPO 关闭。UCFTireComponent 会为每个带有形变器的车轮开启偏移,而始终计算该偏移的材质会使该开关失去作用。车轮母材质的边界为 16 厘米。

骨骼网格体的材质必须在 Usage 下标记 Used with Skeletal Mesh,否则其着色器不会被编译,网格也不会弯曲。

外观用你自己的材质函数替换函数内置的污垢或裂纹绘制。三个设置用于选择外观,位于 Project Settings > Plugins > Crushform > Look:

设置替换必需输出
UCFSettings::BodyDirtLookMF_CF_PaintBase Color
UCFSettings::WheelDirtLookMF_CF_WheelDirtBase Color
UCFSettings::GlassCrackLookMF_CF_GlassCrackOpacity
Look
Body Dirt LookNone
Wheel Dirt LookNone
Glass Crack LookNone
项目设置中 Plugins > Crushform 下的 Look 分组。

外观的输入和输出按名称与函数的引脚相匹配,不区分大小写,但区分空格。若某个外观输入无法由任何引脚提供数据,接线就会失败,除非你在该输入上勾选了 Use Preview Value As Default。缺少必需输出的外观会被拒绝。日志会写明缺少的输出:

WireLook: %s lacks the output "%s" that the look of %s cannot do without

外观的 Normal 输入总会被提供数据。它取内置调用的法线输出、为法线引脚提供数据的来源,或一个平坦的切线空间法线。外观的 Normal 输出同样会被使用。带有 Normal 输出的内置调用会将其作为自己的法线。否则,在车身中它会放在 MF_CF_Deform 的 Normal 输入之前,或放在材质法线之前。车身漆面没有 Normal 输出,因此车身外观的法线会放在 MF_CF_Deform 之前。

外观替换数据函数可能具有的输入可能替换的输出
Body Dirt LookMF_CF_PaintMF_CF_DirtAmountBase Color、Roughness、Metallic、Normal;Dust、Mud、Snow、Wet、Dirt Fresh、Dirt Ranks、Pattern Position、Pattern NormalBase Color(必需)、Roughness、Metallic、Normal
Wheel Dirt LookMF_CF_WheelDirtMF_CF_WheelDirtAmountBase Color、Roughness、Metallic、Normal;Dust、Mud、Snow、Wet、Dirt Ranks、Pattern Position、Pattern NormalBase Color(必需)、Roughness、Metallic、Normal
Glass Crack LookMF_CF_GlassCrackMF_CF_GlassCrackDataBase Color、Opacity、Roughness、Normal;Crack Mask、Crack Frost、Crack Tilt、Crack 0 至 Crack 3、Crack Radii、Pane U、Pane VOpacity(必需)、Base Color、Roughness、Normal

外观的输入由同名的内置调用输出,或由同名数据函数的输出提供数据。两者都无法提供数据的输入会使外观失败,除非该输入勾选了 Use Preview Value As Default:

WireLook: %s has the input "%s", which nothing can feed; name it after a pin of %s or %s, or tick Use Preview Value As Default

包含多个内置函数调用的材质,只会对第一个调用应用该外观。日志会对其他调用发出警告。

更改外观设置时,会将其应用于项目中调用该函数的每个已保存材质。被修改的材质会重新编译并标记为脏(需要保存),但不会自动保存,因此请保存它们以保留新外观。在 Material Editor 中打开的材质会被跳过并给出警告。请关闭它,然后运行控制台命令 Crushform.RewireLooks,它会手动执行同样的操作。该命令仅存在于编辑器中。

污垢层被烘焙进污垢函数。更改 Dirt Layer Order,或某个污垢通道的混合方式或 Z 顺序,会立即在编辑器中重建 MF_CF_Paint 和 MF_CF_DirtAmount。Crushform.RebakeDirtOrder 可手动执行相同的操作。

烘焙器只能从 ini 文件的文本中看到设置对象中的软引用。在设置构造函数中设定的默认值无法被它看到。因此插件会手动添加 Crushform 设置对象所软引用的每个包。这包括图集、默认配置文件、路面资产、污垢集合和外观函数。它对插件运行时模块的每个设置类都这样处理,并读取类默认值(构造函数在其中放置默认值)。仅由编辑器专用属性引用的包不会被添加。

其效果是:即使没有任何地图使用,设置所指向的外观或图集也会进入游戏。

UCFContentLibrary 是上述构建器和接线的底层库。它位于 CrushformEditor 模块中,因此仅存在于编辑器中。其函数均为静态函数,位于 Crushform|Content 分类下:Python 和编辑器工具蓝图会调用它们。该库有 24 个可供蓝图调用的函数。以下为上文未涵盖的函数:

函数作用
WireGlassMaterial将半透明玻璃材质的 Base Color、Opacity、Roughness 和 Normal 经由 MF_CF_GlassCrack 连接,并保留原有的数据来源。World Position Offset 保持不变。玻璃使用此调用而非 WireMaterial,且玻璃材质不会获得漆面函数。若材质使用材质属性、世界空间法线,或使用缺少引脚的函数,则会被拒绝。在 /Crushform/ 和 /Engine/ 之外,它随后会获得项目的玻璃外观。
ApplyLooks通过外观接线,将项目的三种外观分别应用到材质中各自目标的内置调用上。设置为空时会将该外观移除。WireMaterial 和 WireGlassMaterial 在结尾调用它,Crushform.RewireLooks 为每个已保存材质调用它。/Crushform/ 和 /Engine/ 中的材质保持不变。
RepointFunctionCalls将材质中某个函数的每次调用指向另一个函数,并按引脚名称保留连接。返回被更改的调用次数。用于将材质从其自己的轮胎函数迁移到 MF_CF_TireDeform。
BuildVehiclePaintMaterial重建车身的清漆母材质 M_CF_VehiclePaint。它不会接入 Crushform:请接着调用 WireMaterial。
BuildWheelMaterial重建 M_CF_Wheel,World Position Offset 中为 MF_CF_TireDeform,颜色、粗糙度和金属度上为 MF_CF_WheelDirt。
BuildGlassShardMaterial重建 M_CF_GlassShard:半透明、双面、边缘更亮的透明玻璃。
BuildGlassShards用一块碎片瓦片填充玻璃定义的碎片,每个碎片取自一个静态网格列表。玻璃页面介绍了碎片。
BuildGlassShardMesh将静态网格重建为一个玻璃碎片:1 cm 厚的凸多边形板,有 3 到 7 个角,宽约 100 cm,带盒体碰撞。相同的 Seed 生成相同的碎片。
BuildDirtLook添加 MPC_CF_Dirt 缺少的污垢外观参数,并使用其默认值。它从不更改已存在的参数,因为其值是项目的调节结果。未被任何污垢函数读取的参数会在警告中被指出。
SetSkinnedSectionDisabled在某个 LOD 中关闭或开启骨骼网格的一个分段,效果与网格编辑器中 Disable 复选框的结果相同。
GetAtlasPath、GetDirtAtlasPath、GetDirtFreshAtlasPath、GetScratchAtlasPath、GetDirtLookPath按项目设置返回晶格图集、污垢图集、新鲜污垢图集、划痕图集和污垢外观集合的完整包名。
GetDefaultAtlasSize与项目槽位尺寸一致的图集大小,即 4 乘 32 个槽位。

库中的其他函数是上文各节所述的构建器和接线函数。

  • 在 Material Editor 中打开已接线的车身材质。MF_CF_Deform 调用为 World Position Offset 和 Normal 提供数据,MF_CF_Paint 为 Base Color、Roughness 和 Metallic 提供数据。
  • 更改偏移量后运行 Crushform.RebakeOffsets。提示会告诉你保存 Crushform 材质函数。保存它们,然后重新打开其中一个并检查其引脚。
  • 在 Play In Editor 中,用 Crushform.DebugImpact 撞击车身。凹陷会在材质中显示,漆面会在被刮擦处磨损。

原因。 该外观没有 Base Color 输出,或者它有一个无引脚可以提供数据的输入。日志会指明是哪一个:

WireLook: %s has the input "%s", which nothing can feed; name it after a pin of %s or %s, or tick Use Preview Value As Default

解决。 将该输入重命名为与某个引脚一致,或在其上勾选 Use Preview Value As Default。然后重新为材质接线。

更改偏移量后玻璃板的裂纹不正确

Section titled “更改偏移量后玻璃板的裂纹不正确”

原因。 MF_CF_GlassCrack 或 MF_CF_GlassCrackData 的重建未被保存,因此材质仍读取旧索引。或者玻璃偏移现在与形变数据块重叠:重建被拒绝并记录在日志中,该函数保留其旧索引。

解决。 保存 Crushform 材质函数。如果日志指出了重叠,请移动 GlassCustomDataOffset,使其 16 个浮点数与形变数据块不重叠,如上文的自定义基元数据表所示。

原因。 材质未保存,或者它位于 /Crushform/ 或 /Engine/ 中,插件会保持这些材质不变。该外观也不会应用到你自己的材质函数内部的调用上。

解决。 保存材质,然后运行 Crushform.RewireLooks。请将调用放在材质本身中,而不是你自己的函数里。