Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

materials: new format #470

Open
Tracked by #574
0x4E69676874466F78 opened this issue Mar 6, 2023 · 36 comments
Open
Tracked by #574

materials: new format #470

0x4E69676874466F78 opened this issue Mar 6, 2023 · 36 comments
Labels
dev-tools Tools helpful for development enhancement New feature or request materials
Milestone

Comments

@0x4E69676874466F78
Copy link
Collaborator

0x4E69676874466F78 commented Mar 6, 2023

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

  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
Copy link
Collaborator Author

@SNMetamorph

@0x4E69676874466F78
Copy link
Collaborator Author

SNMetamorph/PrimeXT#160

@SNMetamorph
Copy link

@SNMetamorph

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

@w23
Copy link
Owner

w23 commented Apr 22, 2023

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

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

  1. Собственная текстура. int index в таблицу текстур, прилетающих из движка. Per-geometry.
    Одна и та же текстура может быть использована по-разному в разных контекстах далее. Этот параметр статичный за исключением анимированных текстур у брашей.
  2. Дополнительный "тип" материала. Per-geometry.
    • studio: chrome. Эффект: environment mapping в традиционном рендере, где координаты текстур для вершин генерячатся специально. В лучах это только влияет на шероховатость.
    • sprite: glow. Выключает depth test, рисуя спрайт поверх всего. Эффект: или блум (можно будет потом выпилить вообще), или это чтобы убрать артефакты у спрайтов близ поверхностей, например, хитпоинта пылесоса. Можно убрать в пользу специального рендер типа внизу.
    • у брашей ещё есть sky (специальный материал для скайбокса), анимированные текстуры (влияют на текстуру, и её emissive; моргающий монитор).
  3. Render mode. Per-model. Прилетает динамически, не известен заранее при загрузке. В традиционном рендере влияет на:
    • наличие и тип альфа блендинга (аддитивный, смешивание)
    • наличие альфа-теста
    • тест глубины, и запись в буфер глубины
    • подмену текстуры одним цветом
      По сути есть ограниченный набор из (см
      typedef enum {
      kVkRenderTypeSolid, // no blending, depth RW
      // Mix alpha blending with depth test and write
      // Set by:
      // - brush: kRenderTransColor
      // - studio: kRenderTransColor, kRenderTransTexture, kRenderTransAlpha, kRenderGlow
      // - sprite: kRenderTransColor, kRenderTransTexture
      // - triapi: kRenderTransColor, kRenderTransTexture
      kVkRenderType_A_1mA_RW, // blend: src*a + dst*(1-a), depth: RW
      // Mix alpha blending with depth test only
      // Set by:
      // - brush: kRenderTransTexture, kRenderGlow
      // - sprite: kRenderTransAlpha
      // - triapi: kRenderTransAlpha
      kVkRenderType_A_1mA_R, // blend: src*a + dst*(1-a), depth test
      // Additive alpha blending, no depth
      // Set by:
      // - sprite: kRenderGlow
      kVkRenderType_A_1, // blend: src*a + dst, no depth test or write
      // Additive alpha blending with depth test
      // Set by:
      // - brush: kRenderTransAdd
      // - beams: all modes except kRenderNormal and beams going through triapi
      // - sprite: kRenderTransAdd
      // - triapi: kRenderTransAdd, kRenderGlow
      kVkRenderType_A_1_R, // blend: src*a + dst, depth test
      // No blend, alpha test, depth test and write
      // Set by:
      // - brush: kRenderTransAlpha
      kVkRenderType_AT, // no blend, depth RW, alpha test
      // Additive no alpha blend, depth test only
      // Set by:
      // - studio: kRenderTransAdd
      kVkRenderType_1_1_R, // blend: src + dst, depth test
      ):
    • Обычный непрозрачный материал. Большая часть всего именно это.
    • Обычный материал с альфа-тестом. Всякие решётки, перила, заборы, сетки.
    • Аддитивный блендинг с тестом глубины. Спрайты, бимы и всякое прочее как бы светящееся.
    • Аддитивный блендинг без глубины. Только glow у спрайтов.
    • Смешивание с альфа-фактором с тестом глубины (есть вариант и с записью в буфер глубины) TBD Стёкла, спрайты дыма, и пр?
  4. Blend factor. Может анимироваться в зависимости от renderfx. Per-model.
  5. Model color. Per-model. Прилетает вместе с entity_t (TBD: откуда? может анимироваться? на что конкретно влияет и не влияет?)
  6. Emissive color. Per-geometry. Прилетает с .rad файлом и патчами. Может быть анимирован вместе с текстурой. Не используется в традиционном рендере, но важен для лучей и GI.

@w23
Copy link
Owner

w23 commented Apr 22, 2023

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

  • 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] (в реальности [0, 1] без градации?).
  • metalness. Скаляр, [0-1] ([0,1]?), умножается с текстурой.
  • transmittance. Скаляр [0-1].
  • refractive_index. Скаляр [0-1].
  • model_color, RGB, [0-1].
  • emissive. RGB, [0-~1e6].
  • emissive_map в будущем?
  • mode. Вариант из: Regular, AlphaTest, BlendAdd, BlendMix. Преломляквы детектятся по transmittance > 0.

Наблюдения:

  • base_color{,_map} нужен для всех вариантов вообще.
  • BlendMix нужны только: base_color{,_map} и model_color с альфой.
  • BlendAdd как BlendMix но ещё жуёт emissive.
  • model_color, emissive, mode динамические.
  • model_color, mode зависят от энтити и render_mode.
  • emissive может зависеть от per-surface патчей.

@w23
Copy link
Owner

w23 commented Apr 22, 2023

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

@w23
Copy link
Owner

w23 commented Apr 22, 2023

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Apr 22, 2023

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
Copy link
Owner

w23 commented Apr 22, 2023

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

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

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

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

@w23
Copy link
Owner

w23 commented Apr 22, 2023

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

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

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

model_color, RGB, [0-1].

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

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

emissive_map в будущем?

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

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Apr 22, 2023

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

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

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

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

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

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

@w23
Copy link
Owner

w23 commented Apr 23, 2023

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

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

Не, model_color берётся из энтити. base_color берётся из .mat файла:

vec4_t base_color;

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

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

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

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

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

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

@w23
Copy link
Owner

w23 commented Apr 23, 2023

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

@w23
Copy link
Owner

w23 commented Apr 23, 2023

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

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

# 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"
}

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

  • где баланс между хардкодом некоторых особенностей, и конфигурируемостью?
    • Глоу и хром захардкодить проще, чем делать конфигурацию достаточно гибкой.
    • Могут существовать комбинации рендермоды+типы моделей+текстуры, которые могут быть исключениями из общих правил.
      • Можно в принципе их дождаться, накопить статистику из нескольких примеров, и понять тогда, как лучше сделать уже на конкретном.
  • порядок применения более общих патчей (например, chrome) и конкретных материалов, приоритеты.

@w23 w23 added this to the Materials milestone Apr 23, 2023
@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Apr 23, 2023

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

Да модель нельзя никак покрасить, рендер-моды можно ставить (но не все работают), рабочие можешь посмотреть через карту test_bug_model_render_assassin, заморозь физику там (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 (и вообще) может быть релевантно FWGS#729 как я понимаю zgdump не в состоянии закончить, хотя осталось там не много:

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Apr 23, 2023

"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
Copy link
Owner

w23 commented Apr 23, 2023

Возможно можно при "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 влияет на то, как данная модель/набор геометрий участвует в отрисовке кадра:

  • opaque -- обычный непрозрачный материал со всем набором PBR текстур и параметров. Принимает освещение.
  • alphatest -- как opaque, но с alpha test дырками.
  • add -- аддитив, добавляется к тому, что за ним: $dst + base\_color * model\_color * \alpha$. Использует только base_color и model_color. Не принимает освещение, светится сам безотносительно.
  • mix -- смешивается с тем, что за ним: $dst * (1-\alpha) + base\_color * model\_color * \alpha$. Остальное так же, как у add.
  • translucent (или какой там корректный термин). Полупрозрачный PBR материал, который может пропускать лучи в себя (стекло, вода, ...).

"for_model"

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

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

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

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

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

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Apr 24, 2023

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

Сейчас у нас для 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
Copy link
Collaborator Author

0x4E69676874466F78 commented May 21, 2023

Предварительные подробности относительно 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
Copy link
Collaborator Author

0x4E69676874466F78 commented Sep 18, 2023

@SNMetamorph хочет расширение vmat, я думаю это не принципиально.
SNMetamorph/PrimeXT#160 (comment)
Мы можем поддержать и mat и vmat в принципе.

@0x4E69676874466F78
Copy link
Collaborator Author

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

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Sep 25, 2023

Подытожим (пишу с точки зрения пользователя). Возможно это лучше перенести в новую 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
Copy link
Owner

w23 commented Sep 26, 2023

Подытожим (пишу с точки зрения пользователя). Возможно это лучше перенести в новую 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
Copy link
Collaborator Author

0x4E69676874466F78 commented Sep 26, 2023

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

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

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

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

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

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

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

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Sep 26, 2023

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

@SNMetamorph
Copy link

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

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

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Sep 26, 2023

@0x4E69676874466F78
Copy link
Collaborator Author

0x4E69676874466F78 commented Sep 26, 2023

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

@0x4E69676874466F78
Copy link
Collaborator Author

@LifeKILLED
Copy link

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

@LifeKILLED
Copy link

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

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

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

@LifeKILLED
Copy link

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

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

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

@SNMetamorph
Copy link

SNMetamorph commented Sep 26, 2023

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

@LifeKILLED
Copy link

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

@0x4E69676874466F78
Copy link
Collaborator Author

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

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

@0x4E69676874466F78
Copy link
Collaborator Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dev-tools Tools helpful for development enhancement New feature or request materials
Projects
Status: 🔖 Ready
Development

No branches or pull requests

4 participants