FWGS / xash3d-fwgs

Xash3D FWGS engine
1.55k stars 234 forks source link

Detail textures improvements #1469

Closed Qwertyus3D closed 4 months ago

Qwertyus3D commented 1 year ago

В общем, подниму тему, т. к. вопрос актуальный, на мой взгляд. Текста будет много, на случай, если кто-то, кто не в курсе, пожелает вникнуть в суть проблемы. Прошло уже несколько лет, как из движка тупо выпилили ни за что ни про что систему материалов, которая была отличным и существенным преимуществом движка перед Голдсорсом. FWGS ещё какое-то время поддерживал старую версию движка, в которой материалы работали, но последняя версия 0.19.2 с их поддержкой вышла 18 июня 2019 года, т. е. более 4-х лет назад, а версия 0.20 этой поддержкой так и не обзавелась. Между тем интерес у сообщества присутствует, разного рода текстур-паки выходят, только делать их приходится либо под старый движок, либо по методике подмены детализированных текстур.

В принципе, с тех пор, как в Ксаше был исправлен загрузчик списка деталок, система стала абсолютно рабочей, и почти ничто не мешает её использовать, кроме:

  1. Несовместимость с флипнутыми TGA. Не знаю, какими идеями руководствуются создатели некоторых текстур-паков, но почему-то нередко они сохраняют TGA флипнутыми, т. е. если открыть файл обычным просмотрщиком, то картинка будет перевёрнутой, и лишь где-то в самом файле присутствует тэг, указывающий на то, что при загрузке данного изображения оно должно быть перевёрнуто обратно. Это поддерживается Стимовским Голдсорсом, но Ксаш этот тэг не воспринимает, из-за чего загружает все текстуры строго так, как они сохранены, и если сохранено вверх ногами, то и в игре текстура переворачивается.

  2. Несохранение состояния квара r_wadtextures в файлах конфигурации. Квар по умолчанию при загрузке игры всегда устанавливается на "0". Из-за чего в старых картах Half-Life всегда подгружаются текстуры, вшитые разработчиками на стадии демки Day One. И деталки, соответственно, накладываются поверх этих вшитых текстур. А так как деталки представляют собой, в большинстве случаев, новые текстуры, созданные авторами текстур-паков, то и результат - кривое смешение несочетаемых текстур. И нужно самостоятельно засовывать запись r_wadtextures "1" либо в autoexec.cfg, либо в userconfig.cfg, чтобы игра пропускала вшитые текстуры автоматически.

  3. Кардинальное отличие системы материалов от деталок было в том, что материалы использовать было максимально легко - у нас просто есть файл с именем, аналогичным имени текстуры, движок его находит и загружает без всяких _detail.txt, которые должны быть созданы для каждой отдельно взятой карты. Причём, при размещении материалов в valve, они становятся легко доступными и в любом моде, стоит лишь включить поддержку материалов в меню. И игроку не нужно каждый раз что-то вручную настраивать. Это, собственно, и было главным преимуществом системы материалов - легкость работы с текстур-паком. Всегда понятно, какие текстуры у тебя есть, как они будут использованы.

  4. Важнейший недостаток текстур-паков, основанных на подмене обычных текстур детализированными - это фактическая зависимость текстур-пака от содержимого WAD-файлов. Игра по-прежнему обращается к WAD-текстурам, и накладывает деталки путём смешивания двух текстур, из-за чего возникает зависимость работы текстур-пака от WAD-файлов. Часто текстуры в WADах просто заменяются на серый однотон, который при смешении с деталкой как бы пропускается, чтобы подставляемая TGA-текстура полностью заменила собой базовую. В итоге, если создатель какого-либо мода впихнул в свои WAD-файлы какие-нибудь стандартные текстуры вместо серого однотона, который требуется текстур-паком, то при попытке использовать деталки в таком моде получим опять кривое смешение двух разных текстур поверх друг друга. В то время, как с системой материалов подобное поведение исключалось, т. к. гарантировалась замена любой WAD-текстуры материалом.

В связи с вышеизложенным возникает предложение доработать систему загрузки детализированных текстур, если уж поддержка материалов до сих пор буксует. Т. е. исправить поддержку флипнутых TGA, сохранение значения r_wadtextures и добавить возможность автоматической подгрузки деталок без использования индивидуальных _detail.txt для каждой карты. И желательно - без необходимости зависеть от использования "засеренных" WADов. На основании чего предлагаю следующие шаги по доработке, в отношении автоматизации системы подмены текстур детальными.

  1. В первую очередь, требуется решить вопрос с необходимостью наличия отдельного _detail.txt для каждой карты. Безусловно, если данный файл для карты присутствует, то текстуры должны загружаться по указанным в нём правилам. Напомню, что наложение текстур обеспечивает строка вида: crete3_wall01b detail/crete3_wall01 1.0 1.0 Т. е. первым идёт имя базовой текстуры, как оно задано в файле карты, потом - путь к TGA-текстуре, располагаемой внутри папки gfx. Чаще всего авторы текстур-паков кладут все файлы TGA-текстур в подпапку detail, а далее указывают имя текстуры, которая и будет использована для наложения или подмены. В отличие от системы материалов, у деталок могут отличаться имена совмещаемых текстур и масштаб наложения, что и задаётся цифровыми значениями - соотношение размера исходной текстуры и детальной (пропорции масштаба текстур при наложении друг на друга по ширине и высоте). Изначально детальные текстуры были предназначены не для замены основной текстуры, а для имитации требуемого эффекта поверхности. Поэтому они были маленькими серыми текстурками, которые многократно накладывались поверх базовой текстуры, придавая ей рельеф. В текстур-паках зачастую это сейчас абсолютно не используется, т. к. требуется не имитация фактуры, а просто замена исходной текстуры на новую, более высокого разрешения и качества. В этом случае масштаб наложения текстур всегда будет равен 1.0.

Изначально предполагалось, что в _detail.txt для каждой карты указываются только те текстуры, которые присутствуют в карте, и только те текстуры, которым требуется придать детализацию поверхности. Однако авторы текстур-паков всегда упрощают систему, в следствие чего практически всегда создаётся один мастер-файл, в котором прописываются все текстуры, имеющиеся в WAD-файлах, которые подлежат замене текстур-паком. Так что такой _detail.txt может вместо нескольких строк используемых текстур содержать тысячи строк с правилами подмены даже тех текстур, которых в конкретной карте нет. Надо думать, одно это немного замедляет каждый раз процесс загрузки карты. Далее, авторы текстур-пака (а после них и пользователь, если вдруг захочет играть на новых картах) занимаются самым глупым процессом - полученный _detail.txt многократно копируют для каждой новой карты. Один из текстур-паков, попавшихся мне в руки, содержал полторы тысячи копий одного и того же файла общим весом под 200 Мб. Всё для того, чтобы сократить мучения пользователя текстур-пака (но не избавить его от них полностью).

Каковы возможные варианты решения проблемы недостающих _detail.txt? Думаю, можно использовать путь использования дополнительных значений квара r_detailtextures. В старой версии движка стандартный список деталок был вшит, и при установке значения квара на "2" предполагалась "автоматическая генерация" _detail.txt для каждой новой карты. Надо ли говорить, что фичу никто не использовал, т. к. стандартные детальные текстуры нужно было иметь, чтобы их использовать, нужно было знать о наличии данной фичи и забыть о том, что можно вместо убогой подборки стандартных деталок использовать нормальный текстур-пак. К тому же, присутствовал баг, ломающий загрузку списка детальных текстур для кастомных текстур-паков. В общем, полный спектр причин автогенерацию деталок не использовать. Так вот, сейчас значение r_detailtextures "2" можно использовать для автоматизации использования деталок, но другими способами:

План А. Хардкодом прописать в движке имя для того самого мастер-файла детальных текстур, который приходится бессмысленно копировать вручную. И при установке r_detailtextures "2" игра, не находя специального _detail.txt для отдельной карты, ищет наличие указанного файла, и загружает правила из него. Условно говоря, можно назвать его detailtextures_master.txt. И достаточно будет создать только 1 такой файл со списком всех текстур пака и правил замены, чтобы больше к данному вопросу не возвращаться. Но если игра будет обнаруживать у отдельной карты свой _detail.txt, то приоритет использования будет у него.

План Б. Расширение плана А. Не задавать конкретное имя мастер-файла текстур в движке, а выделить под него отдельный квар имени файла, устанавливаемый пользователем (или автором текстур-пака). Тогда движок будет проверять через этот квар имя, например, "detailtextures_master" или "00_AnyMap_detail", и использовать указанный файл для каждой карты.

План В. Немного сложнее, с расчётом на то, что в перспективе будут использоваться полные текстур-паки, включающие в себя текстуры по принципу системы материалов, когда на каждую текстуру есть просто свой вариант замены. Тогда при включении r_detailtextures "2" файл детальных текстур будет генерироваться для каждой карты, у которой его нет. При генерации файла будет происходить создание списка всех текстур данной карты в формате: texture_name detail/texture_name 1.0 1.0 Т. е. на выходе получаем файл, по которому игра ищет одноимённые текстуры в папке gfx/detail и накладывает их на оригинал с масштабом 1 к 1. В итоге, задача пользователя - иметь полноценный пак текстур с дефолтными именами в дефолтной папке, и вообще не париться обо всём остальном. Для апгрейда такого пака потребуется минимум ручных усилий, т. к. всё будет расчитано на прямую замену текстур по имени.

  1. Второй вопрос относится к зависимости детальных текстур-паков от отредактированных WAD-файлов, которые обычно поставляются в комплекте с ними. Соответственно, речь о возможных проблемах подмены текстур в тех модах, которые поставляются с какими-либо перекопированными из других модов популярными вадниками (нубы так вообще от незнания копируют текстуры ХЛ в свой мод), либо вшитыми в карты стандартными текстурами. Ну либо кто-то берёт известный вадник, и добавляет прямо в него несколько новых текстур, используемых модом. Тогда и вадник такой удалить нельзя, и использовать деталки поверх стандартных текстур не выйдет. Поэтому нужно решение для тех, у кого есть полноценный пак текстур, чтобы его можно было использовать автоматически с любым модом, не занимаясь вопросами ручной адаптации пака под запихнутые в него стандартные текстуры.

Тут, думаю, можно воспользоваться либо отдельным новым кваром, либо использовать r_wadtextures в значении "2" (или, возможно, r_detailtextures "3"). Результатом должно стать игнорирование содержимого WADов или вшитых в карту текстур при наличии детальной текстуры. Т. е. деталка должна полностью заменить собой исходную текстуру, как если бы вместо неё была та самая серая однотонная болванка. Единственное, я тут не совсем представляю механику работы транспарентных текстур (со знаком "{") с деталками, но очевидно, что отключение WAD-текстур сделает необходимым использование текстур с альфа-каналом для их подмены. Также есть момент в отношении текстур воды (со знаком "!"), что из них может браться цвет для установки значения подводного тумана, в связи с чем тоже могут быть какие-либо тонкости. Поэтому хотелось бы узнать о возможных проблемах, если они есть, чтобы подумать о вариантах их решения. Но вообще, полное или преимущественное игноририрование содержимого стандартных текстур было бы хорошим подспорьем при создании текстур-паков, удобных в использовании. Чтобы не приходилось редактировать дополнительно базовые текстуры, как это было в случае с системой материалов.

TLDR: предлагается превратить поддержку детализированных текстур в полноценный аналог отключенной системы материалов, для чего пофиксить баг флипнутых TGA, сохранение состояния квара r_wadtextures и расширить функционал деталок путём автоматизации их использования на любых картах, включая полную замену WAD-текстур текстурами высокого разрешения.

П. С. Кстати, хотелось бы уточнить, как обстоят дела с возможностью использовать другие форматы, кроме TGA? Нужна поддержка каких-либо сжатых форматов в перспективе использования текстур высокого разрешения. В принципе, JPG блоками 1х1 очень неплохо сжимает практически без потери качества, PNG со сжатием всяко лучше пухлых TGA, но если какие-то другие форматы предпочтительнее для движка, хотелось бы знать. Вообще я пробовал сжимать в DDS, но там зачастую получаются нежелательные артефакты, да и вообще формат очень замороченный, куча стандартов, опций, приложений по сжатию, каких-то консольных утилит, рассчитанных на шарящих программистов, что во всём этом сложно разобраться. Непонятно вообще, есть ли какой-то удобный компромисс между степенью сжатия и качеством сохранения. Очень не хочется терять часы времени на то, чтобы достичь хорошего результата.

a1batross commented 1 year ago

Я пока не дочитал до конца.

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

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

К слову, у нас есть поддержка чтения PNG в замену lossless форматам TGA и BMP, и KTX в замену lossy DDS.

mittorn commented 1 year ago

Я тоже хочу вернуть систему материалов, просто это было далеко не приоритетной задачей. wad сам по себе слишком убог, а детайлы совсем не для этого

А какие фильтры сжатия у нас есть? KTX так же может использовать lossless сжатие и при этом быть быстрее png Конечно zstd жирный, но как я понимаю, для ktx можно любой фильтр сжатия использовать

Qwertyus3D commented 1 year ago

Попробовал познакомиться с KTX. Первая тулза с Гитхаба - типичный набор консольных утилит. Для тех, кто знает, чего он хочет и зачем он это будет делать. Для тех, кому бы просто попробовать конвертнуть, оценить те или иные опции, проверить полученный результат всё это ничего не даёт. Хорошо, нашёл другую тулзу, уже с GUI. Но тут другой типичный случай - куча опций, форматов сжатия, хз какой вообще выбрать. При этом пакетная конвертация в GUI всё равно не предусмотрена - конечно, ведь любому, кто работает с графикой, больше, чем 1 текстуру конвертировать не нужно :D . Ладно, попробовал сжать. При первой же попытке при сжатии в формат, предложенный по умолчанию, программка ругнулась, что у текстурки не то соотношение пикселей и конвертировать её вообще нельзя. Выбрал другую, кратную 16 пикселям по сторонам - опять не подошла. Сжал, наконец, в двух других форматах. В одном сжалась на четверть, при том, что обычный ZIP ту же текстуру сжимает более, чем в 4 раза. Во втором случае сжал наполовину, но текстурка стала чёрно-белой. Попробовал сжать в PNG - сжалась в 5 с лишним раз :D . Вопрос, нафига тогда KTX, который непонятно, чем сжимать и непонятно как просматривать после этого :)

Qwertyus3D commented 1 year ago

Кстати, JPG, визуально неотличимый от оригинала, на 90% сжатия (и блоками 1х1 для повышения качества) ту же текстурку сжал аж в 18,5 раз. А потом вообще выяснил, что текстурка изначально была сохранена в TGA с пустым альфа-каналом, т. е. размер файла изначально был завышен, и любое сжатие уже на четверть вес должно было бы сократить.

a1batross commented 1 year ago

Я не уверен, что стоит поддерживать JPEG. Это всё-таки не формат игровых данных (как и PNG на самом деле, но на него были конкретные планы -- использовать в качестве HD логотипов в мультиплеере и иметь возможность сохранять скриншоты в человеческом формате вместо BMP), а место на диске нынче не самое дорогое.

Впрочем тот кто хочет может запросто себе его вернуть: https://github.com/FWGS/Xash3DArchive/blob/4a8069e48c4fd64b1739abcd9a32a4ca10a04434/engine/common/imagelib/img_jpg.c. Imagelib с тех пор не сильно поменялся :)

lewa-j commented 1 year ago

Смысл KTX как и DDS в том что он хранит текстуры в формате сжатия понятном gpu. При загрузке таких текстур их не нужно разжимать, они отправляются на Gpu как есть и занимают там столько же памяти. jpg и png, как и просто текстура в zip архиве, хоть и мало занимают места на диске, требуют распаковки на этапе загрузки и после этого занимают в разы больше места в видеопамяти.

TLDR ktx это быстрая загрузка и экономия видеопамяти.

Qwertyus3D commented 1 year ago

Не имею возможности сравнивать конкретный результат, соглашусь, что так оно, видимо, и есть, но хотелось бы использовать такой сжатый формат, который хоть как-то сжимает, и при этом не портит текстуру. И желательно, чтоб после этого полученный результат легко было просмотреть (с DDS это ещё возможно, т. к. поддерживается неспециализированным софтом, а вот KTX под вопросом). Опять же, как понять, какие конкретно опции сжатия или формата выбирать из десятков возможных вариантов, желательно с возможностью пакетной конвертации. Допустим, в случае с Паранойей 2 Дядя Миша всячески сопротивлялся, говорил, что сжатые форматы не нужны, и первый релиз состоялся с несжатыми текстурками. Потом спустя какое-то время он сам сделал обновление и отконвертировал все текстуры в DDS, даже, вроде бы, сделал специальную утилиту для перегонки, и радовался полученному результату. Тем не менее, я сравнивал визуально, и артефакты на DDS-текстурах в "переиздании" П2 местами заметны, при том, что процент сжатия по весу не такой большой вышел в целом. Т. е. выигрыш специализированных форматов, наверное, в скорости, но вот с освоением данного инструментария возникают проблемы.

lewa-j commented 1 year ago

К сожалению все gpu форматы сжатия с потерями.

Qwertyus3D commented 1 year ago

Вот вроде адекватный инструмент: https://github.com/GPUOpen-Tools/Compressonator/releases Прогнал в DDS пак текстур по стандарту BC7, сжатие вышло в 1,59 раз лучше, чем у максимально сжатого PNG. В просмотровщике визуально потери качества нет, но смущает факт, что отконвертированные текстуры отображаются так, как если бы они на пиксель смещались влево. Т. е. слева как будто пиксель от текстуры отсекается, а справа как будто генерируется тонкая полоска, продолжающая изображение. Возможно, это какой-то косяк просмотровщика, в игре не смог понять, присутствует ли это смещение на деле или нет.

Qwertyus3D commented 1 year ago

Вообще всё выглядит так, как если бы срезанная полоска с левого края текстуры перекидывалась на правый край. Может, особенность формата сжатия какая-то. Или это какие-то особенности взаимодействия с NVidia, карточка у меня зелёная, а не красная, а софтина от ATI.

nekonomicon commented 1 year ago

Несовместимость с флипнутыми TGA. Не знаю, какими идеями руководствуются создатели некоторых текстур-паков, но почему-то нередко они сохраняют TGA флипнутыми, т. е. если открыть файл обычным просмотрщиком, то картинка будет перевёрнутой, и лишь где-то в самом файле присутствует тэг, указывающий на то, что при загрузке данного изображения оно должно быть перевёрнуто обратно. Это поддерживается Стимовским Голдсорсом, но Ксаш этот тэг не воспринимает, из-за чего загружает все текстуры строго так, как они сохранены, и если сохранено вверх ногами, то и в игре текстура переворачивается.

Ну вот нет, это явная ошибка в рендере ксаша, так как дядя Миша там что-то с проверкой намудрил, а перевёрнутые tga ксаш переворачивает везде включая рендер, и с последним это явная ошибка. На одной из карт в Tyrian: Ground Assault из-за этого переворачивается скайбокс. То есть по факту ксаш поддерживает флипнутые tga, но GoldSource в рендере рисует их как есть не переворачивая, а ксаш переворачивает. Upd: точнее GoldSource как раз таки игнорирует атрибут для флипа в случае с содержимым resource/background и рендером, а вот иконки и WON'овские контролы как раз таки переворачиваются. И мне кажется это связано с тем, что модули hl.exe, hw.dll и gameui.dll имеют независимые по разному написанные загрузчики tga. В случае с ксашем атрибут учитывается для всего и переворачивается все, исключая содержимое resource/background потому меню выставляет специальный флаг с пометкой Steam background completely ignore tga attribute 0x20 (stupid lammers!), в рендере предусмотрено выставление этого флага тоже, но похоже проверка не верная и флаг для текстур никогда не выставляется.

Я не уверен, что стоит поддерживать JPEG.

Только если новомодный jpegxl, старый формат морально устарел уже, да и декодеры у него жутко медленные, исключая те, что юзают SIMD, многопоток и CUDA.

Прогнал в DDS пак текстур по стандарту BC7, сжатие вышло в 1,59 раз лучше, чем у максимально сжатого PNG

Максимально пожатый PNG можно ещё уменьшить на ~30% утилитой zopflipng, но он может медленнее декодироваться после этого.

a1batross commented 1 year ago

А можно приложить ссылку на текстурпак в котором перевернуты текстуры?

Qwertyus3D commented 1 year ago

https://www.moddb.com/games/half-life/addons/hl-detail-textures-steam-non-xash3d

a1batross commented 1 year ago

Выставил флаг TF_NOFLIP_TGA для detail текстур в 34d76643429dd44342b7b1683de916a6aac330a2

CortexReaver commented 11 months ago

NVIDIA Texture Tools Exporter, available as a standalone GUI tool or a Photoshop Plugin. It supports loading from KTX1 and KTX2 textures and can export to KTX2.

source: https://github.com/KhronosGroup/KTX-Software/wiki/

Don't know how true it is, I've only used the older version of NVIDIA photoshop plugins to work with DDS formats.

0x4E69676874466F78 commented 11 months ago

Вы тут говорите про KTX, но в движок добавлена именно KTX2, не KTX1. Если вы попробуете загрузить KTX(1) оно работать не будет.