w23 / xash3d-fwgs

Vulkan Ray Tracing fork of Xash3D FWGS engine. Intended to be merged into master at some point in the future.
160 stars 16 forks source link

materials: new format #470

Open 0x4E69676874466F78 opened 1 year ago

0x4E69676874466F78 commented 1 year ago

Недостатки текущего формата материалов:

  1. заточен под патчинг существующих текстур, слабо подходит для переиспользования материалов (особенно актуально при разработке нового контента, см. PrimeXT).
  2. требует написания спец парсера для интеграции с другими инструментами.

Нам нужен более удобный формат для унификации с PrimeXT, чтобы не мешать им своими заморочками. Предлагаю немного изменить текущий формат и сделать его JSON-совместимым, по сути всё отличие заключается в наличие двоеточия и запятых в конце. Вложенных структур не планируется, то есть существующий парсер не придётся как-либо ощутимо менять в этом плане. Но помимо этого вводится ещё понятие самих материалов, которые можно указать внутри блока замены текстуры, с этим сложнее.

Суть сводится к объявлению материалов отдельным блоком:

{
"material": "blabla",
//параметры материала (ещё предстоит договорить об наименовании)
},
{
"material": "blabla2",
//параметры материала
},

дальше мы внутри блока замены текстуры указываем этот материал:

{
"for": "#models/zombie/Sci3(Shoe).mdl",
"material": "blabla blabla2", // массив материалов которые нужно здесь использовать
},

Внутри блока с "for" по прежнему будут работать строки с параметрами материалов. Это по сути просто взятие параметров из блока материалов и вставка их в блок замены текстуры. Таким образом можно будет переиспользовать одни и те же параметры для разных текстур и где-то переопределить внутри блока "for" параметры из "material", это и так сейчас работает если указывать одинаковые ключи, то возьмётся последний.

Внутри патчей мы можем заменить "_xvk_texture" "texturename" на "_xvk_material" "materialname".

Возможно тут будет проблема у парсера из-за одинакового наименования (я не помню как парсер устроен), если так, то можно внутри блок с "for" использовать "set_material" "blabla blabla2".

Минус подхода что придётся держать временную хэшмапу с материалами.

0x4E69676874466F78 commented 1 year ago

@SNMetamorph

0x4E69676874466F78 commented 1 year ago

https://github.com/SNMetamorph/PrimeXT/issues/160

SNMetamorph commented 1 year ago

@SNMetamorph

Да, определённо нам надо как-то в этом плане совместимость обеспечить

w23 commented 1 year ago

Начал я думать про то, как нам причесать и лучше организовать материалы. Свалю текущее понимание сюда.

Набор параметров для отрисовки, из которых нужно сварганить материал, выглядит примерно так:

  1. Собственная текстура. int index в таблицу текстур, прилетающих из движка. Per-geometry. Одна и та же текстура может быть использована по-разному в разных контекстах далее. Этот параметр статичный за исключением анимированных текстур у брашей.
  2. Дополнительный "тип" материала. Per-geometry.
    • studio: chrome. Эффект: environment mapping в традиционном рендере, где координаты текстур для вершин генерячатся специально. В лучах это только влияет на шероховатость.
    • sprite: glow. Выключает depth test, рисуя спрайт поверх всего. Эффект: или блум (можно будет потом выпилить вообще), или это чтобы убрать артефакты у спрайтов близ поверхностей, например, хитпоинта пылесоса. Можно убрать в пользу специального рендер типа внизу.
    • у брашей ещё есть sky (специальный материал для скайбокса), анимированные текстуры (влияют на текстуру, и её emissive; моргающий монитор).
  3. Render mode. Per-model. Прилетает динамически, не известен заранее при загрузке. В традиционном рендере влияет на:
    • наличие и тип альфа блендинга (аддитивный, смешивание)
    • наличие альфа-теста
    • тест глубины, и запись в буфер глубины
    • подмену текстуры одним цветом По сути есть ограниченный набор из (см https://github.com/w23/xash3d-fwgs/blob/935c2e7f5e503cb2ac9980575040535a2c8c79a7/ref/vk/vk_render.h#L66-L105):
    • Обычный непрозрачный материал. Большая часть всего именно это.
    • Обычный материал с альфа-тестом. Всякие решётки, перила, заборы, сетки.
    • Аддитивный блендинг с тестом глубины. Спрайты, бимы и всякое прочее как бы светящееся.
    • Аддитивный блендинг без глубины. Только glow у спрайтов.
    • Смешивание с альфа-фактором с тестом глубины (есть вариант и с записью в буфер глубины) TBD Стёкла, спрайты дыма, и пр?
  4. Blend factor. Может анимироваться в зависимости от renderfx. Per-model.
  5. Model color. Per-model. Прилетает вместе с entity_t (TBD: откуда? может анимироваться? на что конкретно влияет и не влияет?)
  6. Emissive color. Per-geometry. Прилетает с .rad файлом и патчами. Может быть анимирован вместе с текстурой. Не используется в традиционном рендере, но важен для лучей и GI.
w23 commented 1 year ago

С другой стороны, в лучах было бы удобно потреблять описание материала, состоящее из:

Наблюдения:

w23 commented 1 year ago

Ща покормлю детей и закину сюда про то, как я предлагаю реализовать эту трансформацию, сек.

w23 commented 1 year ago

Поправка: kRenderTransColor для брашей полностью выключает текстуры, заменяя их на константный цвет. То есть текстуры/материалы могут быть динамические и по этому критерию тоже. Пока неясно, для чего именно это используется, для какого эффекта, и что нам нужно делать.

0x4E69676874466F78 commented 1 year ago

Model color. Per-model. Прилетает вместе с entity_t (TBD: откуда? может анимироваться? на что конкретно влияет и не влияет?)

Раньше в ксаше был баг и текстура модели могла быть окрашена (но не заменена сплошным цветом) через ключ rendercolor с соответствующим rendermode, но сейчас этого бага больше нет и модель не может принять цвет теперь в этом плане поведение как и в goldsrc. Анимироваться цвет и раньше насколько я знаю не мог.

metalness_map. Текстура, один компонент, [0-1] (в реальности [0, 1] без градации?).

В реальности градации есть и хардкодить бинарное 0/1 не надо, пусть будет плавающим как сейчас. Иногда это очень полезно в сложных ситуациях.

model_color, RGB, [0-1].

Насколько я понимаю умножение цветом через base_color полностью повторяет это, то есть параметр избыточный по крайней мере в формате материалов.

emissive_map в будущем?

По скорее бы! Хочется моделям добавить эмиссив текстуры, тем же блокам с аккумуляторами для костюма и для "реактора" гауспушки.

w23 commented 1 year ago

Для выбора конечного материала для употребления лучеризатором должен использоваться следующий набор критериев:

  1. Имя первоначальной текстуры. Параметр "for" в текущей системе материалов. Статичное.
  2. Тип chrome для студийных моделей. Сейчас там подменяется roughness_map на серую текстуру. Статичный.
  3. render_type. Нужен для определения режимов полупрозрачности. Динамический.
  4. Возможно, тип объекта, и его render_mode. Дело в том, что для разных типов объектов (браши-модели-спрайты-...) mode резолвится в type по-разному, теряя информацию. Это может быть важно (а может и не быть). Динамический.

Также не исключено, что нужен будет нелинейный маппинг из blend в transmittance. Но в простом варианте их достаточно перемножить.

В простом варианте можно добавить к материалу параметр "for_type", который помимо фильтрации по имени текстуры будет ещё и рендер типу фильтровать. Возможные значения, например: "BlendMixDepth", "BlendMix", "BlendAdd", "BlendAddDepth".

w23 commented 1 year ago

metalness_map. Текстура, один компонент, [0-1] (в реальности [0, 1] без градации?).

В реальности градации есть и хардкодить бинарное 0/1 не надо, пусть будет плавающим как сейчас. Иногда это очень полезно в сложных ситуациях.

Ок, оставляем.

model_color, RGB, [0-1].

Насколько я понимаю умножение цветом через base_color полностью повторяет это, то есть параметр избыточный по крайней мере в формате материалов.

Сейчас у нас он есть отдельным параметром в формате материалов. Не знаю, насколько он используется. Выглядит так, что это разные вещи -- один цвет статичный, приглушает базовую текстуру. А другой -- динамический, прилетает из движка.

emissive_map в будущем?

По скорее бы! Хочется моделям добавить эмиссив текстуры, тем же блокам с аккумуляторами для костюма и для "реактора" гауспушки.

Для красоты это добавить просто. Сложно сделать, чтобы оно влияло на освещение нормально, т.к. оно будет ломать семплирование.

0x4E69676874466F78 commented 1 year ago

Сейчас у нас он есть отдельным параметром в формате материалов. Не знаю, насколько он используется.

model_color? это когда он был добавлен? я не в курсе и он никак там не используется.

А другой -- динамический, прилетает из движка.

Ну как уже выяснили баги больше нет и красить модель не надо для соответствия ксашевому гл даже если там прилетает цвет через ключ энтити.

Для красоты это добавить просто. Сложно сделать, чтобы оно влияло на освещение нормально, т.к. оно будет ломать семплирование.

Ты про то что сложно потекстельно сделать маску для сэмплирования? Ну для начала можно сделать проще, пусть свет считается как из цельного полигона, но визуально освещение ограничено текстелями текстуры. Примерно что я предлагал для обычных светящихся текстур ограничением через эмиссив маски.

w23 commented 1 year ago

Сейчас у нас он есть отдельным параметром в формате материалов. Не знаю, насколько он используется.

model_color? это когда он был добавлен? я не в курсе и он никак там не используется.

Не, model_color берётся из энтити. base_color берётся из .mat файла: https://github.com/w23/xash3d-fwgs/blob/aab689a37b95d47632b3526d2018c157aaff34f8/ref/vk/vk_materials.h#L11

А другой -- динамический, прилетает из движка.

Ну как уже выяснили баги больше нет и красить модель не надо для соответствия ксашевому гл даже если там прилетает цвет через ключ энтити.

То есть там цвет вообще не учитывается никак?

Для красоты это добавить просто. Сложно сделать, чтобы оно влияло на освещение нормально, т.к. оно будет ломать семплирование.

Ты про то что сложно потекстельно сделать маску для сэмплирования? Ну для начала можно сделать проще, пусть свет считается как из цельного полигона, но визуально освещение ограничено текстелями текстуры. Примерно что я предлагал для обычных светящихся текстур ограничением через эмиссив маски.

Ага. Это сделать условно быстро.

w23 commented 1 year ago

Всякие другие ишьи, релевантные вот этому всему:

w23 commented 1 year ago

Блин, я балбес, хайджекнул эту issue, которая была про совершенно другое :smiling_face_with_tear:.

Начал пробовать начерновить всякую сыроту, как можно было бы сделать:

# Creates a new material 'mat1' with the same values as 'mat0', but with transmittance set to 0.7
# This material does not patch any existing tex_ids directly, only used if referenced by surface patches, or inherited by other material.
{
  "new" "mat1"
  "inherit" "mat0"
  "transmittance" "0.7"
}

{
  "for" "mat2"
  "for_rendermode" "TransColor TransTexture"
  "for_model" "brush studio" # also possible: beam sprite tri
  "mode" "mix"
}

# Any Chrome material will get roughness rewritten to 0.5
{
  "for_chrome" "1"
  "roughness" "0.5"
}

# Glow
{
  "for_rendermode" "Glow"
  "for_model" "sprite"
  "mode" "glow"
}

Но тут много непонятного:

0x4E69676874466F78 commented 1 year ago

То есть там цвет вообще не учитывается никак?

Да модель нельзя никак покрасить, рендер-моды можно ставить (но не все работают), рабочие можешь посмотреть через карту test_bug_model_renderassassin, заморозь физику там (playersonly) иначе часть нападут, потому что я заметил была разная работа режимов на cycler энити и monster* энтити. Порядок там такой: 1 стобец 1 ячейка cycler 1 стобец 2 ячейка monster_zombie 2 стобец 1 ячейка cycler 2 стобец 2 ячейка monster_zombie и так далее они чередуются по столбцам. 1 столбец renderamt 0, 2 столбец renderamt 128, 3 столбец renderamt 255 у всех прописан rendercolor 255 0 0 и дальше каждый горизонтальный ряд это rendermode, если идти от игрока то от 0 до 5 (normal, color, texture, glow, solid, additive). У ассасинок порядок повторяется. Как видно по карте сейчас в GL никто не окрашивается как и в goldsrc.

К #211 (и вообще) может быть релевантно https://github.com/FWGS/xash3d-fwgs/pull/729 как я понимаю zgdump не в состоянии закончить, хотя осталось там не много:

1. Вернуть R_ShowTextures в ref api
2. Поправить оформление в texturelib
3. Прикрутить текстуры неба
4. Протестировать текстуры-заглушки
5. Решить, стоит ли оставлять оригинал текстуры в ref_ и вообще для чего оно использовалось раньше 
0x4E69676874466F78 commented 1 year ago

"for_model" "brush studio" # also possible: beam sprite tri

Если такое делать то надо поменять формат у моделей и спрайтов, а то сейчас там: "for" "#models/v_crowbar/chrome.mdl" "for" "#sprites/muzzleflash(frame:00).spr"

Возможно можно при "for_model" "studio" автоматически подставлять #models в начале и .mdl в конец, получается в материалах достаточно будет написать "for" "v_crowbar/chrome" или вовсе "for" "chrome" если подумать о автоматической структуре относительно путей (тогда в таком случае и не нужен "for_model" "studio" в 99,9% случаев), чтобы внутри папки models были уже подпапки типа v_crowbar и т.д. подставлялось оно автоматически внутри v_crowbar.mat, что я хотел изначально, но тогда видимо ты был уставшим/ленивым. Тогда не понадобятся ещё мусорные импорты что мне пришлось наплодить.

Со спрайтами сложнее, так как есть кадры, но можно сделать примерно так же как с моделями только вместо имени текстуры там будут номера кадров, типа: "for" "00" То есть внутри папки sprites найти подпапку muzzleflash, внутри там будет muzzleflash.mat где будет этот for с номером кадра.

"mode" "mix"

Что это такое?

"for_model"

Предлагаю переименовать в "for_geom" чтобы не было коллизий смысла, т.к. о моделях обычно думают о студиомоделях, а формат у нас для конечного пользователя.

На тему Glow была идея там не режим подставлять, а кастомный шейдер (пусть и который мы заранее объявили и интегрировали).

В остальном надо смотреть по ходу дела.

w23 commented 1 year ago

Возможно можно при "for_model" "studio" автоматически подставлять #models в начале и .mdl в конец, получается в материалах достаточно будет написать "for" "v_crowbar/chrome" или вовсе "for" "chrome" если подумать о автоматической структуре относительно путей (тогда в таком случае и не нужен "for_model" "studio" в 99,9% случаев), чтобы внутри папки models были уже подпапки типа v_crowbar и т.д. подставлялось оно автоматически внутри v_crowbar.mat, что я хотел изначально, но тогда видимо ты был уставшим/ленивым. Тогда не понадобятся ещё мусорные импорты что мне пришлось наплодить.

Пока не очень понимаю, о чём именно идёт речь. Похоже, что это про несколько другую проблему? Покажи мусорные импорты, я попробую разобраться.

Со спрайтами сложнее, так как есть кадры, но можно сделать примерно так же как с моделями только вместо имени текстуры там будут номера кадров, типа: "for" "00" То есть внутри папки sprites найти подпапку muzzleflash, внутри там будет muzzleflash.mat где будет этот for с номером кадра.

Про кадры интересная проблема. Это уже какой-то недо-макро-язык нужно тащить. Боюсь, что руками по всем анимациям и кадрам пройтись будет тупо быстрее.

"mode" "mix"

Что это такое?

Это значит, что в лучах цвет этой геометрии должен смешиваться с тем, что за ней: $src \alpha + dst (1-\alpha)$ mode влияет на то, как данная модель/набор геометрий участвует в отрисовке кадра:

"for_model"

Предлагаю переименовать в "for_geom" чтобы не было коллизий смысла, т.к. о моделях обычно думают о студиомоделях, а формат у нас для конечного пользователя.

А "for_source" "sprite", например?

На тему Glow была идея там не режим подставлять, а кастомный шейдер (пусть и который мы заранее объявили и интегрировали).

Оно там немного распределённое, нет одного простого места, куда воткнуть. Это один ровно случай, впрочем, можно не пытаться обобщать.

В остальном надо смотреть по ходу дела.

Ага, я пока склоняюсь к забить и захардкодить выставление mode по признакам из rendermode и пр. Потом по мере патчинга выявлять законы и исключения -- будет понятнее, как делать.

0x4E69676874466F78 commented 1 year ago

Пока не очень понимаю, о чём именно идёт речь. Похоже, что это про несколько другую проблему? Покажи мусорные импорты, я попробую разобраться.

Сейчас у нас для wad файлов не требуется писать импорт, достаточно создать папку с wadname.wad с файлом wadname.wad.mat внутри где уже определять что надо. В случае же с моделями и спрайтами у нас только по 1 точке входа, models/models.mat и sprites/sprites.mat и внутри этих файлов приходится городить на каждую модель и спрайт по своему импорту, чего в случае с вад файлами делать не нужно. Открой эти файлы поймёшь. Более того в случае с вад файлами нам надостаточно писать просто имя текстуры, без всяких этих "#models/v_crowbar/chrome.mdl и "#sprites/muzzleflash(frame:00).spr".

Про кадры интересная проблема. Это уже какой-то недо-макро-язык нужно тащить. Боюсь, что руками по всем анимациям и кадрам пройтись будет тупо быстрее.

Не понимаю тебя какой макро-язык, сейчас мне приходится писать:

// sprites/bexplo.spr/bexplo.spr.mat
{
"for" "#sprites/bexplo(frame:00).spr"
//"basecolor_map" "Frame 0.png"
}

{
"for" "#sprites/bexplo(frame:01).spr"
//"basecolor_map" "Frame 1.png"
}

логичнее писать (когда у нас автоматические импорты как в случае с wad'ами)

// sprites/bexplo.spr/bexplo.spr.mat
{
"for" "00"
//"basecolor_map" "Frame 0.png"
}

{
"for" "01"
//"basecolor_map" "Frame 1.png"
}

На лету сгенерировать из файлового пути и значения for не должно требовать какого-то там макро-языка. то есть из данных

sprites/bexplo.spr/bexplo.spr.mat
"for" "00"

получить

#sprites/bexplo(frame:00).spr

не должно быть сложным. Тем более если делать по схеме wad то у тебя не просто путь у тебя понимание что там произошло определение модели/спрайта поэтому не должно быть нужным писать имя модели/спрайта для for.

А "for_source" "sprite", например?

А чем тебе geom не нравится? geom от geometry (такое сокращение есть в словарях с ожидаемым значением формы и т.п.), всё что ты описал геометрия, но source можно конечно тоже.

0x4E69676874466F78 commented 11 months ago

Предварительные подробности относительно PrimeXT:

  1. будет немного другая структура, где в моде две директории materials с материалами и textures с текстурами. По наличию этих папок и можно будет определять что перед нами PrimeXT и нужно включить другую логику обнаружения материалов и текстур.
  2. имя файла материала = имя файла wad-текстуры; следовательно нужно будет проверять наличие файлов материалов относительно wad файла; внутри директорий wad нет подпапок; найдя файл материалов уже можно получить пути/имена текстур.
  3. в моделях могут быть подпапки т.к. в самих моделях допустимы и используются в имени подпапки (в wad так нельзя).
  4. fallback если не существует файла с материалом, либо в нём не указан путь до нужных текстур, тогда нужно пытаться их загрузить из пути textures/имятекстуры.dds где у имятекстуры помимо обычного случая есть ещё варианты с суффиксами _norm/_hmap/_luma/_gloss/_pbr, где _norm карта нормали, _hmap высот, _luma свечения, далее _gloss или _pbr упакованная текстура с roughness/metalness.
0x4E69676874466F78 commented 7 months ago

@SNMetamorph хочет расширение vmat, я думаю это не принципиально. https://github.com/SNMetamorph/PrimeXT/issues/160#issuecomment-1457200022 Мы можем поддержать и mat и vmat в принципе.

0x4E69676874466F78 commented 7 months ago

Поправка: kRenderTransColor для брашей полностью выключает текстуры, заменяя их на константный цвет. То есть текстуры/материалы могут быть динамические и по этому критерию тоже. Пока неясно, для чего именно это используется, для какого эффекта, и что нам нужно делать.

Просто геометрия без текстуры, подозреваю что использовалось исходно как оптимизация, т.к. полупрозрачная текстура дороже. Например встречается в стёклах для труб на одном из уровней.

0x4E69676874466F78 commented 7 months ago

Подытожим (пишу с точки зрения пользователя). Возможно это лучше перенести в новую issue, а эту закрыть.

Новый формат будет JSON-совместим, это значит что его можно будет распарсить JSON-парсером.

Нужно по аналогии с wad подгружать только необходимые материалы для моделей и спрайтов. Сейчас всегда инклудится всё через pbr/models/models.mat и pbr/sprites/sprites.mat где просто тонны инклудов, от этого нужно уйти. Движок отдаёт строки в виде: #models/zombiegibs1/Sci3(Shoe).mdl #models/zombiegibs1/SCIZOM3_LegBack1.mdl #sprites/zerogxplode(frame:00).spr #sprites/zerogxplode(frame:01).spr У нас ожидаются пути pbr/models/modelname.mdl/modelname.mat pbr/sprites/spritename.spr/spritename.mat В данном случае zombiegibs1 это modelname, а Sci3(Shoe) это текстура в zombiegibs1.mdl, немного неинтутивно. Со спрайтами проще, zerogxplode это spritename. То есть нужно вычленить из строк имя спрайта и модели после чего подключить соответствующий файл материала. Ещё для чистоты и удобства поменять бы внутренний формат имени у этих материалов. Сейчас они указываются ровно так же строкой:

{
"for" "#models/zombiegibs1/Sci3(Shoe).mdl"
//"basecolor_map" "Sci3(Shoe).png"
//"normal_map" "Sci3(Shoe)_normal.png"
//"metal_map" "Sci3(Shoe)_metal.png"
//"roughness_map" "Sci3(Shoe)_roughness.png"
}

{
"for" "#models/zombiegibs1/SCIZOM3_LegBack1.mdl"
//"basecolor_map" "SCIZOM3_LegBack1.png"
//"normal_map" "SCIZOM3_LegBack1_normal.png"
//"metal_map" "SCIZOM3_LegBack1_metal.png"
//"roughness_map" "SCIZOM3_LegBack1_roughness.png"
}
{
"for" "#sprites/zerogxplode(frame:00).spr"
//"basecolor_map" "Frame 0.png"
}
{
"for" "#sprites/zerogxplode(frame:01).spr"
//"basecolor_map" "Frame 1.png"
}

Я предлагаю избавиться от мусора в "for", то есть в случае модели писать: "for" "Sci3(Shoe)" то есть сразу имя текстуры модели, т.к. мы уже знаем материал какой модели заинклудили, тем более он содержится даже в имени файла материала. А в случае спрайта просто писать номер кадра: "for" "00" Ситуация ровно та же как с моделью. Всё по аналогии с wad файлами там мы тоже не указываем путь к wad файлу, а сразу пишем имя текстуры.

Текстуры могут быть подгружены без всяких файлов материалов, для этого достаточно не описывать "for" для текстуры и создать файлы ИМЯТЕКСТУРЫ_тип.{png,ktx,dds}, где тип всевозможные алиасы: basecolor, albedo, (без _типа считается basecolor, то есть ИМЯТЕКСТУРЫ.dds это basecolor), diffuse normal, normalmap, norm roughness, rough metalness, metallic, metal height, displacement, hmap metalroughness, combined, pbr, gloss emissive, luma

Совершенно отдельный режим работы для совместимости с PrimeXT. Это всё не обязательно делать прямо сейчас, но нужно иметь ввиду.

  1. Требуется поддержать расширение vmat
  2. В primext две директории materials с материалами и textures с текстурами. По наличию этих папок и можно будет определить что перед нами PrimeXT и нужно включить другую логику обнаружения материалов и текстур.
  3. Внутри папки с материалами есть папки с именами wad файлов, все файлы материалов внутри называются как имена wad-текстур; следовательно нужно будет проверять наличие файлов материалов относительно wad файла; внутри директорий wad нет подпапок; найдя файл материала уже можно получить пути/имена pbr текстур.
  4. в моделях могут быть подпапки т.к. в самих моделях допустимы и используются в имени подпапки (в wad так нельзя).
  5. fallback если не существует файла с материалом, либо в нём не указан путь до нужных текстур, тогда нужно пытаться их загрузить из пути textures/имятекстуры.dds где у имятекстуры помимо обычного случая есть ещё варианты с суффиксами _norm/_hmap/_luma/_gloss/_pbr, где _norm карта нормали, _hmap высот, _luma свечения, далее _gloss или _pbr упакованная текстура с roughness/metalness.

Теперь непосредственно сам формат материалов. Допустимые поля: for // целевая текстура for_model_type // тип целевой геометрии: brush, studio, sprite, triapi for_rendermode // режим рендера у геометрии: "kRenderNormal", "kRenderTransColor", "kRenderTransTexture", "kRenderGlow", "kRenderTransAlpha", "kRenderTransAdd" mode // вариант из: opaque, alphatest, add, mix, translucent; либо Regular, AlphaTest, BlendAdd, BlendMix: проломления определяются по transmittance > 0 // я не понял что в итоге material // имя нового материала use // назначение материала текстуре base_color_map (albedo_map) // текстура, RGBA, [0-1] base_color (albedo) // цвет, RGBA, [0-1], умножается с цветом текстуры normal_map // текстура, RGB, [0-1], нормализованная normal_scale // скаляр, [0-1], "приглушает" нормаль из текстуры roughness_map // текстура, один компонент, [0-1] roughness // скаляр, [0-1], умножается с текстурой metalness_map // текстура, один компонент, [0-1] metalness // скаляр, [0-1], умножается с текстурой transmittance // скаляр [0-1] refractive_index // скаляр [0-1] emissive // цвет, RGB, [0-~1e6] emissive_map // текстура, RGBA, [0-1]

Создание материала

{
    "material": "MAT_NAME",
    "base_color_map": "base.png",
    "normal_map": "irregular.ktx2",
    "base_color": "1 .5 0",
    // ...
},
{
    "material": "mirror",
    "base_color_map": "white",
    "base_color": "1 1 1",
    "roughness": "0",
    "metalness": "1",
    // ...
}

Назначение материала на текстуру

{
    "for": "+EXIT",
    "use": "MAT_NAME"
}

Возможно переопределение:

{
    "for": "+EXIT",
    "use": "MAT_NAME",
    "base_color": "1 0 0"
}

Текстура по прежнему может быть описана без материала. Сложные примеры:

{
    "for": "wood",
    "for_model_type": "brush",
    "for_rendermode": "kRenderTransAlpha",
    "use": "mat_glass",
    "mode": "translucent",
    "base_color_map": "glass2.ktx"
}
{
    "for_model_type": "brush",
    "for_rendermode": "kRenderTransAlpha",
    "mode": "translucent",
    "map_normal": "glass1.ktx"
}

Приоритет материалов решается просто, наибольшой полнотой, чем больше критериев тем приоритетнее блок над остальными. Такой подход позволит ещё на одну и ту же текстуру задать разные материалы под каждый режим рендера. Конфликт (более одного варианта на те же самые фильтры) решается правом первого, с предупреждением в консоль/лог о дубликате.

Отдельно про патчи: Внутри патчей мы меняем текстуру через "_xvk_material" "materialname", а "_xvk_texture" остаётся как вспомогательное для #526 чтобы заменить нужную текстуру на гранях браш-модели на целевой материал.

w23 commented 7 months ago

Подытожим (пишу с точки зрения пользователя). Возможно это лучше перенести в новую issue, а эту закрыть.

Ща погоди я сюда подытожу подытоживание, как я всё понял это, и прокомментирую.

Новый формат будет JSON-совместим, это значит что его можно будет распарсить JSON-парсером.

Это "задача 1" (не в смысле приоритета, а просто номер). Мой комментарий: я бы не хотел делать/тащить сюда json парсер без необходимости. Только если нам кровь из носу надо быть совместимыми с кем-то.

Нужно по аналогии с wad подгружать только необходимые материалы для моделей и спрайтов. Сейчас всегда инклудится всё через pbr/models/models.mat и pbr/sprites/sprites.mat где просто тонны инклудов, от этого нужно уйти. Движок отдаёт строки в виде: #models/zombiegibs1/Sci3(Shoe).mdl #models/zombiegibs1/SCIZOM3_LegBack1.mdl #sprites/zerogxplode(frame:00).spr #sprites/zerogxplode(frame:01).spr У нас ожидаются пути pbr/models/modelname.mdl/modelname.mat pbr/sprites/spritename.spr/spritename.mat В данном случае zombiegibs1 это modelname, а Sci3(Shoe) это текстура в zombiegibs1.mdl, немного неинтутивно. Со спрайтами проще, zerogxplode это spritename. То есть нужно вычленить из строк имя спрайта и модели после чего подключить соответствующий файл материала.

Разумно и понятно зачем. Это "задача 2а".

Ещё для чистоты и удобства поменять бы внутренний формат имени у этих материалов. Сейчас они указываются ровно так же строкой:

{
"for" "#models/zombiegibs1/Sci3(Shoe).mdl"
//"basecolor_map" "Sci3(Shoe).png"
//"normal_map" "Sci3(Shoe)_normal.png"
//"metal_map" "Sci3(Shoe)_metal.png"
//"roughness_map" "Sci3(Shoe)_roughness.png"
}

{
"for" "#models/zombiegibs1/SCIZOM3_LegBack1.mdl"
//"basecolor_map" "SCIZOM3_LegBack1.png"
//"normal_map" "SCIZOM3_LegBack1_normal.png"
//"metal_map" "SCIZOM3_LegBack1_metal.png"
//"roughness_map" "SCIZOM3_LegBack1_roughness.png"
}
{
"for" "#sprites/zerogxplode(frame:00).spr"
//"basecolor_map" "Frame 0.png"
}
{
"for" "#sprites/zerogxplode(frame:01).spr"
//"basecolor_map" "Frame 1.png"
}

Я предлагаю избавиться от мусора в "for", то есть в случае модели писать: "for" "Sci3(Shoe)" то есть сразу имя текстуры модели, т.к. мы уже знаем материал какой модели заинклудили, тем более он содержится даже в имени файла материала. А в случае спрайта просто писать номер кадра: "for" "00" Ситуация ровно та же как с моделью. Всё по аналогии с wad файлами там мы тоже не указываем путь к wad файлу, а сразу пишем имя текстуры.

Это "задача 2б". Её чуть сложнее сделать -- загрузка материалов становится контекстно-зависимой. Подозреваю, что её в общем виде сделать будет нетривиально, и по ходу реализации наломаем всякого. Пока предлагаю оставить как есть.

Текстуры могут быть подгружены без всяких файлов материалов, для этого достаточно не описывать "for" для текстуры и создать файлы ИМЯТЕКСТУРЫ_тип.{png,ktx,dds}, где тип всевозможные алиасы: basecolor, albedo, (без _типа считается basecolor, то есть ИМЯТЕКСТУРЫ.dds это basecolor), diffuse normal, normalmap, norm roughness, rough metalness, metallic, metal height, displacement, hmap metalroughness, combined, pbr, gloss emissive, luma

Это "задача 3".

Совершенно отдельный режим работы для совместимости с PrimeXT. Это всё не обязательно делать прямо сейчас, но нужно иметь ввиду.

1. Требуется поддержать расширение vmat

2. В primext две директории materials с материалами и textures с текстурами. По наличию этих папок и можно будет определить что перед нами PrimeXT и нужно включить другую логику обнаружения материалов и текстур.

3. Внутри папки с материалами есть папки с именами wad файлов, все файлы материалов внутри называются как имена wad-текстур; следовательно нужно будет проверять наличие файлов материалов относительно wad файла; внутри директорий wad нет подпапок; найдя файл материала уже можно получить пути/имена pbr текстур.

4. в моделях могут быть подпапки т.к. в самих моделях допустимы и используются в имени подпапки (в wad так нельзя).

5. fallback если не существует файла с материалом, либо в нём не указан путь до нужных текстур, тогда нужно пытаться их загрузить из пути textures/имятекстуры.dds где у имятекстуры помимо обычного случая есть ещё варианты с суффиксами _norm/_hmap/_luma/_gloss/_pbr, где _norm карта нормали, _hmap высот, _luma свечения, далее _gloss или _pbr упакованная текстура с roughness/metalness.

Это "задача 1" выше -- поддержка совместимых с чем-то внешним форматов.

Теперь непосредственно сам формат материалов. Допустимые поля: for // целевая текстура for_model_type // тип целевой геометрии: brush, studio, sprite, triapi for_rendermode // режим рендера у модели: kRenderTransColor, kRenderTransTexture, kRenderTransAlpha, kRenderGlow mode // вариант из: opaque, alphatest, add, mix, translucent; либо Regular, AlphaTest, BlendAdd, BlendMix: проломления определяются по transmittance > 0 // я не понял что в итоге material // имя нового материала use // назначение материала текстуре base_color_map (albedo_map) // текстура, RGBA, [0-1] base_color (albedo) // цвет, RGBA, [0-1], умножается с цветом текстуры normal_map // текстура, RGB, [0-1], нормализованная normal_scale // скаляр, [0-1], "приглушает" нормаль из текстуры roughness_map // текстура, один компонент, [0-1] roughness // скаляр, [0-1], умножается с текстурой metalness_map // текстура, один компонент, [0-1] metalness // скаляр, [0-1], умножается с текстурой transmittance // скаляр [0-1] refractive_index // скаляр [0-1] emissive // цвет, RGB, [0-~1e6] emissive_map // текстура, RGBA, [0-1]

Создание материала

{
  "material": "MAT_NAME",
  "base_color_map": "base.png",
  "normal_map": "irregular.ktx2",
  "base_color": "1 .5 0",
  // ...
},
{
  "material": "mirror",
  "base_color_map": "white",
  "base_color": "1 1 1",
  "roughness": "0",
  "metalness": "1",
  // ...
}

Лёгкое причёсывание формата, "задача 4". Тут почти ничего не надо делать, кроме добавления новых полей?

Назначение материала на текстуру

{
  "for": "+EXIT",
  "use": "MAT_NAME"
}

Возможно переопределение:

{
  "for": "+EXIT",
  "use": "MAT_NAME",
  "base_color": "1 0 0"
}

Текстура по прежнему может быть описана без материала. Сложные примеры:

{
  "for": "wood",
  "for_model_type": "brush",
  "for_rendermode": "kRenderTransAlpha",
  "use": "mat_glass",
  "mode": "translucent",
  "base_color_map": "glass2.ktx"
}
{
  "for_model_type": "brush",
  "for_rendermode": "kRenderTransAlpha",
  "mode": "translucent",
  "map_normal": "glass1.ktx"
}

Селектор материалов, "задача 5а"

Приоритет материалов решается просто, наибольшой полнотой, чем больше критериев тем приоритетнее блок над остальными. Такой подход позволит ещё на одну и ту же текстуру задать разные материалы под каждый режим рендера. Конфликт (более одного варианта на те же самые фильтры) решается правом первого, с предупреждением в консоль/лог о дубликате.

Алгоритм селекции материалов, "задача 5б". Это, кстати, нифига не просто. По мере возрастания сложности, варианты:

  1. Тупо брать первый. Быстро делать, быстро работает (нашли совпадение, вышли).
  2. Применять всё в порядке записи/загрузки. Быстро делать, долго работает. По сути как предыдущий вариант, но надо идти по всем правилам (тысячи их тысячи геометрий каждый кадр для анимированных).
  3. Более сложные критерии. Очень долго делать -- надо выдумывать структуры данных, поддерживающие эти критерии, делать дополнительную сортировку, етц. Изобретать свой SQL из песка и слюны, короче. Работать тоже непонятно, насколько быстро будет.

Отдельно про патчи: Внутри патчей мы меняем текстуру через "_xvk_material" "materialname", а "_xvk_texture" остаётся как вспомогательное для #526 чтобы заменить нужную текстуру на гранях браш-модели на целевой материал.

Индивидуальные патчи, "задача 6".

0x4E69676874466F78 commented 7 months ago

Это "задача 1" (не в смысле приоритета, а просто номер). Мой комментарий: я бы не хотел делать/тащить сюда json парсер без необходимости. Только если нам кровь из носу надо быть совместимыми с кем-то.

Нам не нужно тащить JSON-парсер, нам нужно просто соответствовать JSON-формату формально, перечитай выше тред, там про это было исходно. Обработать лишние : и , не должно быть проблемой. В PrimeXT подразумевается JSON. Вложённость там не подразумевается. Игнорировать [ в начале и ] в конце не должно быть проблемой.

Это "задача 2б". Её чуть сложнее сделать -- загрузка материалов становится контекстно-зависимой. Подозреваю, что её в общем виде сделать будет нетривиально, и по ходу реализации наломаем всякого. Пока предлагаю оставить как есть.

Нужно больше подробностей. Задачу "задача 2б" можно же решить просто по самим путям разбирая их в процессе. То есть уже есть имя файла и этого достаточно чтобы сформировать строки уровня: #models/zombiegibs1/Sci3(Shoe).mdl #sprites/zerogxplode(frame:00).spr для совпадения в "for". Или как там работает сравнение у загруженных материалов? Мы могли бы формировать эти строки внутри памяти, типа читаешь из файла одно а в памяти уже сформированная строка как выше.

Лёгкое причёсывание формата, "задача 4". Тут почти ничего не надо делать, кроме добавления новых полей?

Соответствие JSON, переименовка полей, новые поля, всё да.

Алгоритм селекции материалов, "задача 5б". Это, кстати, нифига не просто. По мере возрастания сложности, варианты:

Ну наибольшая полнота это упорядочить правила по полноте и стопать по первому полному совпадению. Мы можем руками упорядочить, но разве сложно отсортировать материалы по правилам? Если реально сложно то забей, я просто буду руками вверху определять нужные материалы по полноте.

0x4E69676874466F78 commented 7 months ago

@w23 там @lifekilled предлагает добавить ещё параметры френеля и преломления, можно это ещё пробросить до кучи? Нужно только пробросить реализует в шейдере он сам.

SNMetamorph commented 7 months ago

@w23 там @lifekilled предлагает добавить ещё параметры френеля и преломления, можно это ещё пробросить до кучи?

А что за параметры френеля?

0x4E69676874466F78 commented 7 months ago

@SNMetamorph

А что за параметры френеля?

Ну Fresnel. https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel.html https://web.archive.org/web/20230307041737/https://www.dorian-iten.com/fresnel/

0x4E69676874466F78 commented 7 months ago

fresnel Если речь за конкретно параметры то наверное его сила?

0x4E69676874466F78 commented 7 months ago

https://docs.unity3d.com/Packages/com.unity.shadergraph@6.9/manual/Fresnel-Effect-Node.html

LifeKILLED commented 7 months ago

Эта картинка на отражении - это Френель. Сонаправленность проскости и взгляда усиливает отражение. Для каждого материала он свой. Можно сделать поле в материале, чтобы просто привязывать к каким-то текстурам и потом уже в шейдере разбираться, как его использовать

LifeKILLED commented 7 months ago

Преломление тоже у разных материалов разное. По сути нужны просто поля в материалах, которые будут настраивать дизайнеры. Если будет и то, и то, можно будет делать всё от стекла и до воды.

Но также можно еще и добавить какие-то параметры специально для воды, например, масштаб и высоту волн, чтобы она процедурно анимировалась

Либо действительно прокинуть func_water для drag'n'drop совместимости с модами, а стекло при этом просто захачить

LifeKILLED commented 7 months ago

А еще помимо френеля (усиление доли отражений) есть еще и аналогичный эффект у прозрачки, это угол полного отражения. Если смотришь на стекло по касательной с определенным углом, оно полностью перестает пропускать через себя свет и превращается в зеркало. Получается 3 переменных у материала.

  1. Френель
  2. Преломление
  3. Полное отражение

Что-то такое. По сути просто дополнительные цифры в материале, которые будут использоваться либо в лучах, либо в PBR рендере без лучей, если сделаем и такое

SNMetamorph commented 7 months ago

Я в курсе, что эффект Френеля из себя представляет. Меня волнует, что конкретно там нужно вынести наружу? Ведь я насколько помню в аппроксимации Шлика доступна для модификации только переменная F0 - она обозначает множитель отраженной доли света при нулевом угле между нормалью и вектором направления взгляда. Для воды он равен около 0.1, для других поверхностей типично хардкодят 0.04. Вот про эту штуку речь?

LifeKILLED commented 7 months ago

Да, достаточно F0

0x4E69676874466F78 commented 7 months ago

Полное отражение

https://en.wikipedia.org/wiki/Total_internal_reflection

0x4E69676874466F78 commented 7 months ago

Параметры "for_model_type" и "mode" в материалах не будут использоваться. Нам и так понятно какой тип модели перед нами относительно системы материалов (разные директории), они не пересекаются. Если надо патчить triapi-текстуры то опять же отдельная директория. Режим рендера патчиться будет через патчи, то есть выбирается энтити и меняется ей рендермод, т.к. рендермод применяется ко всей энтити целиком.