ИНТЕГРАЦИЯМАТЕРИАЛЫ И ШЕЙДЕРЫ
Материалы и шейдеры
Каждый деформируемый кузов, колесо, панель и шину рисует материал. Плагин предоставляет функции, которые смещают вершины, рисуют износ краски и грязь, а также данные, которые нужны каждому мешу, чтобы найти своё место в атласе. Эта страница является справочником по этим частям. Пошаговое подключение с десятью связями окрашенного кузова описано в Быстром старте. Идея, стоящая за всем этим, описана в части о материалах в Основных понятиях.
Функции материалов
Заголовок раздела «Функции материалов»Все функции лежат в папке Materials контента плагина, /Crushform/Materials. Их входы и выходы — это пины, к которым подключаются материал или вид. Имена пинов точные, включая пробелы.
| Функция | Входы | Выходы | Сборщик |
|---|---|---|---|
MF_CF_Deform | Normal, Crumple Tiling, Fold Amplitude, Fold Wavelength, Fine Fold Wavelength, Fine Fold Strength | World Position Offset, Normal, Wear Depth, Scratch | UCFContentLibrary::BuildDeformFunction |
MF_CF_Paint | Base 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 Tiling | Base Color, Roughness, Metallic | BuildPaintFunction |
MF_CF_DirtAmount | Нет | Dust, Mud, Snow, Wet, Dirt Fresh, Dirt Ranks, Pattern Position, Pattern Normal | BuildDirtAmountFunction |
MF_CF_WheelDirt | Base Color, Roughness, Metallic, Dust Color, Mud Color, Dirt Strength, Snow Color, Built-in Look | Base Color, Roughness, Metallic | BuildWheelDirtFunction |
MF_CF_WheelDirtAmount | Нет | Dust, Mud, Snow, Wet, Dirt Ranks, Pattern Position, Pattern Normal | BuildWheelDirtAmountFunction |
MF_CF_GlassCrack | Base Color, Opacity, Roughness, Normal, Built-in Look | Base Color, Opacity, Roughness, Normal | BuildGlassCrackFunction |
MF_CF_GlassCrackData | Нет | Crack Mask, Crack Frost, Crack Tilt, от Crack 0 до Crack 3, Crack Radii, Pane U, Pane V | BuildGlassCrackDataFunction |
MF_CF_TireDeform | AxleAxis, HalfWidth, BulgeAmount, RimRadius, RimFalloff, FlattenScale, MaxVertDisp | Result | BuildTireDeformFunction |
MF_CF_TrunkBend | Не задаётся кодом плагина | World Position Offset в мировом пространстве | Создаётся в редакторе, не кодом |
MF_CF_Deform работает в касательном пространстве, поэтому нормаль подключённого материала тоже должна быть в касательном пространстве. MF_CF_Paint и MF_CF_WheelDirt принимают переключатель Built-in Look, статический bool, по умолчанию равный true. Настройки видов используют этот переключатель, как объясняет раздел «Виды» ниже.
У материала шины есть скалярный параметр RimRadius, радиус обода в единицах меша. MF_CF_TireDeform принимает его на вход, а UCFTireComponent читает тот же параметр, чтобы знать, как далеко можно вытолкнуть колесо от препятствия. Побеждает первый слот материала на меше шины, который сам задаёт RimRadius, поэтому материал обода, лишь наследующий значение по умолчанию из мастер-материала, не скрывает собственное значение шины. Если ни один слот его не задаёт, значение по умолчанию даёт первый слот, где параметр есть. UCFTireProfile::RimRadiusOverride в сантиметрах заменяет его.
MF_CF_TrunkBend изгибает ствол дерева. Его собственное описание гласит: “Parabolic trunk bow driven by CPD 0..2; outputs world-space WPO”. Оба его мастер-материала добавляют его после смещения от ветра.
Сборщики пересобирают функцию с нуля в редакторе. Идентификаторы пинов они сохраняют по имени и оставляют функцию несохранённой. Сохраните функцию после пересборки.
Мастер-материалы, коллекция и атласы
Заголовок раздела «Мастер-материалы, коллекция и атласы»| Ассет | Роль |
|---|---|
/Crushform/Materials/M_CF_VehiclePaint | Мастер-материал краски: Clear Coat, с Paint Color поверх Base Texture там, где задан Paint Mask |
/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 | Атлас царапин: Render Target RG8 размером с атлас решётки, с покрытием линиями царапин и направлением каждой точки |
Мастер-материалы берут текстуры из текстур плагина T_CF_Default*, и у каждой текстуры есть обычный и виртуальный параметр. Имена параметров фиксированы. Экземпляры задают их по имени, поэтому переименование одного параметра ломает все экземпляры, которые его задают.
Custom Primitive Data
Заголовок раздела «Custom Primitive Data»Каждый меш несёт собственные данные в Custom Primitive Data, в блоках, которые читают функции материалов. Смещения блоков являются настройками проекта в Project Settings > Plugins > Crushform > Atlas. В Unreal Engine от 5.6 до 5.8 у примитива 36 значений типа float (FCustomPrimitiveData::NumCustomPrimitiveDataFloats).
| Блок | Настройка смещения | Значения типа float | Смещение по умолчанию | Содержимое |
|---|---|---|---|---|
| Деформируемый меш | UCFSettings::CustomDataOffset | 18 | 0 | Слот атласа, столбцы поворота и масштаба от меша к корню, перенос, обратный размер ячейки, шаг квантования и разрешение |
| Колесо | UCFSettings::WheelCustomDataOffset | 2 | 34 | Два целых числа: количество пыли и грязи, а также снега и влаги вместе с рангами слоёв |
| Стеклянная панель | UCFSettings::GlassCustomDataOffset | 16 | 18 | Четыре записи трещин по четыре значения типа float в каждой |
| Шина | UCFSettings::TireCustomDataOffset | 32 | 0 | Четыре записи контакта по восемь значений типа float в каждой |
Блок деформируемого меша содержит по порядку: слот в индексе 0, три столбца поворота и масштаба от меша к корню в индексах с 1 по 9, начало меша в пространстве решётки в индексах с 10 по 12, единицу, делённую на размер ячейки, в индексах с 13 по 15, шаг квантования в индексе 16 и упакованное разрешение в индексе 17. MF_CF_Deform читает те же индексы, поэтому раскладка задана кодом, а не ассетом.
| Atlas | ||
|---|---|---|
| Atlas | RT_CF_LatticeAtlas | |
| Slot Width | 256 | |
| Slot Height | 8 | |
| Custom Data Offset | ||
| Wheel Custom Data Offset | ||
| Tire Custom Data Offset | ||
| Glass Custom Data Offset | ||
| Scratch Atlas | None | |
По умолчанию блоки занимают индексы с 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 выполняет ту же пересборку вручную и существует только в редакторе.
Подключение материала
Заголовок раздела «Подключение материала»Подключение связывает материал с плагином. Для этого нужны три шага:
- Смещение вершин и нормаль проходят через
MF_CF_Deform. - Base Color, Roughness и Metallic проходят через
MF_CF_Paint. Для стекла и салона, которые делят меш с кузовом, не передавайте функцию краски. Они получают вмятины вместе с кузовом и сохраняют собственный вид. - 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 projectdeform = 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 вашего профиля. Амплитуда складок берётся из функции, а не из профиля.
Тот же вызов доступен как функция Blueprint модуля редактора, поэтому его может вызвать Editor Utility Blueprint. Граф ниже подключает материал, прибавляя амплитуду складок по умолчанию к Max Displacement. На пине A стоит 60 см, значение UCFProfile::MaxDisplacement по умолчанию в классе. Задайте здесь значение вашего профиля. Сам материал подставляется в пин Material, который граф оставляет для вас.
Подключение отклоняется, и материал остаётся прежним, если материал получает нормаль в мировом пространстве или использует material attributes, к которым ничего не подключено. В логе в каждом случае назван материал.
Nanite и Max World Position Offset Displacement
Заголовок раздела «Nanite и Max World Position Offset Displacement»Max World Position Offset Displacement материала — это граница. Рендерер использует её, чтобы знать, насколько далеко могут сместиться вершины меша. Граница должна быть не меньше Max Displacement профиля плюс амплитуда складок материала. Складки смещают вершины за пределы вмятин. Амплитуда складок по умолчанию составляет 3 см (CFContent::DefaultFoldAmplitude), и её возвращает get_default_fold_amplitude().
На Nanite граница важнее. Отсечение кластеров расширяет свои границы на эту величину, поэтому слишком короткая граница позволяет рендереру отсечь вмятую панель у края экрана. Подключение повышает границу, когда она слишком мала. К границе материала, который уже имеет собственное смещение и собственную границу, добавляется displacement. Задавайте границу вручную, только если не используете подключение.
Мастер-материалы шин оставляют Always Evaluate WPO выключенным. UCFTireComponent включает смещение для каждого колеса, у которого есть деформер, а материал, который всегда вычисляет смещение, делает этот переключатель бесполезным. Граница мастер-материала колеса составляет 16 см.
Скелетному мешу нужен материал с отметкой Used with Skeletal Mesh в разделе Usage, иначе его шейдеры не компилируются и он не сгибается.
Вид заменяет встроенную отрисовку грязи или трещин в функции на вашу собственную функцию материала. Три настройки выбирают виды в Project Settings > Plugins > Crushform > Look:
| Настройка | Заменяет | Обязательный выход |
|---|---|---|
UCFSettings::BodyDirtLook | MF_CF_Paint | Base Color |
UCFSettings::WheelDirtLook | MF_CF_WheelDirt | Base Color |
UCFSettings::GlassCrackLook | MF_CF_GlassCrack | Opacity |
| Look | ||
|---|---|---|
| Body Dirt Look | None | |
| Wheel Dirt Look | None | |
| Glass Crack Look | None | |
Входы и выходы вида сопоставляются с пинами функции по имени: регистр не важен, пробелы важны. Если к входу вида нельзя подключить ни один пин, подключение завершается ошибкой, пока на этом входе не отмечено Use Preview Value As Default. Вид без обязательного выхода отклоняется. В логе назван недостающий выход:
WireLook: %s lacks the output "%s" that the look of %s cannot do withoutК входу Normal вида всегда что-то подключено: выход нормали встроенного вызова, либо то, что подключено к пину нормали, либо плоская нормаль в касательном пространстве. Выход Normal вида тоже используется. Встроенный вызов с выходом Normal принимает его как собственную нормаль. В противном случае он ставится перед входом Normal у MF_CF_Deform в кузове или перед нормалью материала. У краски кузова нет выхода Normal, поэтому нормаль вида кузова ставится перед MF_CF_Deform.
| Вид | Заменяет | Функция данных | Входы, которые он может иметь | Выходы, которые он может заменить |
|---|---|---|---|---|
| Вид грязи кузова | MF_CF_Paint | MF_CF_DirtAmount | Base Color, Roughness, Metallic, Normal; Dust, Mud, Snow, Wet, Dirt Fresh, Dirt Ranks, Pattern Position, Pattern Normal | Base Color (обязателен), Roughness, Metallic, Normal |
| Вид грязи колеса | MF_CF_WheelDirt | MF_CF_WheelDirtAmount | Base Color, Roughness, Metallic, Normal; Dust, Mud, Snow, Wet, Dirt Ranks, Pattern Position, Pattern Normal | Base Color (обязателен), Roughness, Metallic, Normal |
| Вид трещин стекла | MF_CF_GlassCrack | MF_CF_GlassCrackData | Base Color, Opacity, Roughness, Normal; Crack Mask, Crack Frost, Crack Tilt, от Crack 0 до Crack 3, Crack Radii, Pane U, Pane V | Opacity (обязателен), 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. Сюда входят атласы, профиль по умолчанию, ассет поверхностей, коллекция грязи и функции видов. Это делается для каждого класса настроек модулей времени выполнения плагина: читаются значения по умолчанию класса, куда конструкторы записывают свои значения. Пакеты, на которые ссылаются только свойства, существующие лишь в редакторе (editor-only), не добавляются.
Итог: вид или атлас, на который указывает настройка, попадает в игру, даже если ни одна карта его не использует.
Библиотека контента
Заголовок раздела «Библиотека контента»UCFContentLibrary — это библиотека, на которой построены сборщики и подключение выше. Она находится в модуле CrushformEditor, поэтому существует только в редакторе. Её функции статические и относятся к категории Crushform|Content: их вызывают Python и Editor Utility Blueprint. У библиотеки 24 функции, которые может вызвать Blueprint. Остальные, не описанные выше:
| Функция | Что делает |
|---|---|
WireGlassMaterial | Направляет Base Color, Opacity, Roughness и Normal полупрозрачного стеклянного материала через MF_CF_GlassCrack, сохраняя то, что было к ним подключено. World Position Offset остаётся без изменений. Для стекла вместо WireMaterial используется этот вызов, и функция краски стеклу не назначается. Отклоняет материал, который использует material attributes, нормаль в мировом пространстве или функцию без нужного пина. Вне /Crushform/ и /Engine/ затем он получает вид стекла проекта. |
ApplyLooks | Даёт материалу три вида проекта, каждый встроенному вызову своей цели через подключение вида. Пустая настройка убирает вид. WireMaterial и WireGlassMaterial вызывают её в конце, а Crushform.RewireLooks вызывает её для каждого сохранённого материала. Материалы в /Crushform/ и /Engine/ не затрагиваются. |
RepointFunctionCalls | Переназначает каждый вызов одной функции в материале на другую функцию, сохраняя связи по именам пинов. Возвращает число изменённых вызовов. Используйте, чтобы перенести материал с собственной функции шин на MF_CF_TireDeform. |
BuildVehiclePaintMaterial | Пересобирает M_CF_VehiclePaint, мастер-материал кузова с Clear Coat. Подключение Crushform он не выполняет: следом вызовите WireMaterial. |
BuildWheelMaterial | Пересобирает M_CF_Wheel: MF_CF_TireDeform стоит в World Position Offset, а MF_CF_WheelDirt — в цвете, Roughness и Metallic. |
BuildGlassShardMaterial | Пересобирает M_CF_GlassShard: полупрозрачное двустороннее чистое стекло с более яркими краями. |
BuildGlassShards | Заполняет фрагменты определения стекла осколками из одной плитки; каждый осколок берётся из списка Static Mesh. Осколки описаны на странице о стекле. |
BuildGlassShardMesh | Пересобирает Static Mesh как один осколок стекла: пластина толщиной 1 см в форме выпуклого многоугольника с 3–7 углами, около 100 см в поперечнике, с коллизией-коробкой. Одно и то же значение 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. Затем подключите материал заново.
Трещины на стеклянной панели неверны после изменения смещения
Заголовок раздела «Трещины на стеклянной панели неверны после изменения смещения»Причина. Пересборка MF_CF_GlassCrack или MF_CF_GlassCrackData не была сохранена, поэтому материалы всё ещё читают старые индексы. Либо смещение стекла теперь перекрывает деформируемый блок: пересборка отклоняется и пишется в лог, а эта функция сохраняет старые индексы.
Решение. Сохраните функции материалов Crushform. Если в логе названо перекрытие, сдвиньте GlassCustomDataOffset так, чтобы его 16 значений типа float помещались без пересечения с деформируемым блоком, как показано в таблице Custom Primitive Data выше.
Вид не применяется к материалу
Заголовок раздела «Вид не применяется к материалу»Причина. Материал не сохранён либо находится в /Crushform/ или /Engine/, которые плагин не трогает. Вид также не применяется к вызову внутри вашей собственной функции материала.
Решение. Сохраните материал, затем выполните Crushform.RewireLooks. Поместите вызов в сам материал, а не в собственную функцию.