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

Support DDS or KTX2 format up to BC7 #154

Closed 0x4E69676874466F78 closed 7 months ago

0x4E69676874466F78 commented 2 years ago

Ещё вариант: https://github.com/BinomialLLC/basis_universal/

0x4E69676874466F78 commented 1 year ago

Для DDS с BC7 нужно просто смержиться со свежим мастером.

w23 commented 8 months ago

Заметки:

0x4E69676874466F78 commented 8 months ago

Предварительно:

Что касается вариантов UNORM/SNORM, UNORM/SRGB и UFLOAT/SFLOAT я пока не знаю какие лучше. Сompressonator даже не заявляет какой именно у него BC7, для остальных варианты есть.

Чем сжимать: https://github.com/GPUOpen-Tools/compressonator/ https://github.com/GameTechDev/ISPCTextureCompressor/ надо собирать самому

w23 commented 8 months ago
  • Для normalmap BC5 два канала сжатые блоками BC4, потребуется восстановить компонент Z в пиксельном шейдере

Почему именно BC5? (интересно)

  • Для теста 16бит-нормалей тоже можно попробовать BC6H либо безсжатия ARGB_16F.

Без сжатия жирно (хотя KTX2 умеет тупо в zlib/zstd внутри, но это надо писать)

Что касается вариантов UNORM/SNORM, UNORM/SRGB и UFLOAT/SFLOAT я пока не знаю какие лучше. Сompressonator даже не заявляет какой именно у него BC7, для остальных варианты есть.

Для roughness и metallic UNORM, они в 0..1 диапазоне Для basecolor SRGB может быть нужен только если детали тёмные сохранить, иначе UNORM естественней тупо сразу линейный для освещения. Для нормалей мы сейчас тоже сидим на UNORM, поэтому UFLOAT проще. Надо смотреть, будет ли удобнее/проще математика на SFLOAT/SNORM.

Можно попробовать всякое и сравнить.

w23 commented 8 months ago

Ага, в нормалях мы там фигакс руками из UNORM в SFLOAT (вот эти *2. - 1.): https://github.com/w23/xash3d-fwgs/blob/6bfa4c90fac80ce8a56b47e491f6cd07530a2804/ref/vk/shaders/ray_primary_hit.glsl#L48 Поэтому можно сразу SNORM/SFLOAT

(там, кстати, normal_shading отломана для баунсов и для else)

0x4E69676874466F78 commented 8 months ago

Почему именно BC5? (интересно)

Ну там два канала хорошего качества. Народ рекомедует. Вот ещё можно почитать: https://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/

Для basecolor SRGB может быть нужен только если детали тёмные сохранить

У нас текстуры SRGB, тёмные детали хорошо бы сохранить, мы уже наелись с гаммой вдоволь. Но вообще надо глянуть во что там конкретно сохраняют тузлы. Я до практической только-только подступаю.

(там, кстати, normal_shading отломана для баунсов и для else)

Поэтому у нас там артефакты с чернотой?

w23 commented 8 months ago

У нас текстуры SRGB, тёмные детали хорошо бы сохранить, мы уже наелись с гаммой вдоволь.

Кстати, нет. Мы UNORM: https://github.com/w23/xash3d-fwgs/blob/6bfa4c90fac80ce8a56b47e491f6cd07530a2804/ref/vk/vk_textures.c#L346

Для родных текстур там 1998 год и что попало с гаммой, а вот с пбр пнг текстурами почему оно не шакалит, это сюрприз (или шакалит?)

(там, кстати, normal_shading отломана для баунсов и для else)

Поэтому у нас там артефакты с чернотой?

Не, это другое.

0x4E69676874466F78 commented 8 months ago

@w23 ты не забывай что мы делаем преобразование в линейное пространство (SRGBtoLINEAR), а потом в конце делаем гамма-коррекцию (LINEARtoSRGB).

w23 commented 8 months ago

А это строго говоря неправильно. Потому что так оно би/трилинейную интерполяцию в текстурном блоке в srgb неуклюже делает

0x4E69676874466F78 commented 8 months ago

А это строго говоря неправильно. Потому что так оно би/трилинейную интерполяцию в текстурном блоке в srgb неуклюже делает

У нас тогда было всё довольно плохо, сейчас оно хотя бы ожидаемо работает и выглядит хорошо.

Вариант с переделать принимаемый формат на SRGB и убрать SRGBtoLINEAR возможен, но есть нюанс. https://github.com/search?q=repo%3Aw23%2Fxash3d-fwgs%20SRGBtoLINEAR&type=code

Возможно сейчас удастся безболезненно, но не факт. Там потенциальная проблема здесь:

https://github.com/w23/xash3d-fwgs/blob/1f82f352f96dc35451d5197427cda590fcc5dc82/ref/vk/shaders/denoiser.comp#L273-L276

Это точно нельзя делать втупую, нужно тестировать не уедет ли гамма у текстур.

0x4E69676874466F78 commented 8 months ago

Чтобы примерно понять в чём проблема прочитай комментарии начиная отсюда: https://github.com/w23/xash3d-fwgs/issues/321#issuecomment-1003203617 Не помню пытались ли мы сделать сразу SRGB (вроде да, но тогда не было должного понимания), но можно как-нибудь повторить.

w23 commented 8 months ago

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

  1. Руками отсмотреть, что и где мы конвертируем между sRGB и линейкой.
  2. Если там всё с хорошей точностью консистентно, т.е. все текстуры с цветами мы считаем сргбшными, то можно в текстурах сразу лепить _SRGB, и убрать ручную конверсию.
  3. Но тогда придётся также все "не-цветные" текстуры, вроде шероховатости и металличности, сделать _UNORM (или даже _SNORM попробовать для нормалей). Это надо будет явно указывать при загрузке текстур для PBR материалов.

Кстати говоря, всё вышесказанное является необходимым для корректной загрузки KTX2. Если не сделать, получится несогласованный шлак.

0x4E69676874466F78 commented 8 months ago

Загрузку из PNG бы при этом ещё не сломать. Если играться с этим предлагаю сначала на PNG убедиться что всё правильно.

0x4E69676874466F78 commented 8 months ago

Без сжатия жирно (хотя KTX2 умеет тупо в zlib/zstd внутри, но это надо писать)

У compressonator есть кстати такой вариант

BRLG Lossless Compression using Brotli-G

w23 commented 8 months ago

Интересно, но малоприменимо. Brotli-G:

У KTX2 есть расширяемый режим "а запакуй конкретно данные изображений чем-то". Для этого "чем-то" есть в прям стандарте zlib, zstd, суперкомпрессия эта от universal basis, и ещё какая-то проприетарщина "напишите нам".

zlib поддержать должно быть просто -- в ксаше уже, вроде, есть miniz. В крайнем случае libz есть везде. zstd тоже нетрудно. universal basis крестовый, толстый, не всё умеет. В пень.

Мне было бы интересно потом когда-нибудь подрочить своими руками декомпрессию на гпу в стиле http://gamma.cs.unc.edu/GST/gst.pdf, почему-то не нашёл с ходу ничего такого готового опенсорсного. Можно сделать свою либу, лайки гитхабы сабскрайбы цветы поклонницы.

0x4E69676874466F78 commented 7 months ago

Утверждаем базовую схему: basecolor(+alpha) BC7 (тот что в compressonator видимо SRGB UNORM, но нам надо SRGB) normalmap BC5 SNORM roughness/metalness BC4 UNORM combined roughness+metalness BC5 UNORM ?

0x4E69676874466F78 commented 7 months ago

Кстати а как движковые текстуры к нам прилетают? В сыром несжатом виде? По идее их можно было бы BC1 (RGB5:6:5 + 1bit alpha) пожать на лету. Текстуры ещё там прилетают с 4 мипами их тоже можно было бы пожать. Хотя это наверное экономия на спичках?

w23 commented 7 months ago

sRGB linear-vs-gamma situation is a disaster:

Whether to give up and just treat UNORM as SRGB in shaders depends on whether my assumptions about gamma-vs-linear-texture-interpolator are correct. I propose a test: 2x2 black and white texture (checkerboard), scaled to a significant portion of the screen. This means that texture block will do interpolation for us in whatever texture colorspace is specified. Then we upload this same texture twice: in SRGB format and in UNORM/linear format. Then in shader we just read raw values and display them as they are. We can also SRGBtoLINEAR them in the shade too, and compare the results with "hardware" linearization. So, in total, a table 4x4: format srgb-vs-unorm x shader raw-vs-srgb2linear. Results that I expect: only the SRGB format + raw value looks "uniformly" gradient. All other variants are broken.

(We could also play with srgb framebuffer and linear2srgb in the same fashion.)

w23 commented 7 months ago

Утверждаем базовую схему:

  • basecolor(+alpha) BC7 (тот что в compressonator видимо ~SRGB~ UNORM, но нам надо SRGB)

Как выяснилось, компрессонатор умеет только в UNORM, в BC7_SRGB он не умеет, имея только ошмётки дефайнов для этого формата для DX.

Тут вообще встаёт вопрос, как делает индустрия в целом, потому что выглядит слегонца странно.

  • normalmap BC5 SNORM

Почти. Надо:

  1. Убедиться, что нормалмапа правильно предварительно отнормирована. Если почему-то нет, то отнормировать и перепроверить квантизацию.
  2. Если уже отнормирована, то значит, что 8-битной точности двух каналов недостаточно. Либо как-то уменьшить диапазон -- ограничить, насколько нормалмапа может влиять на нормаль. Либо искать более качественный формат.

Для BC6H HDR мы уже выяснили, что он в -1..1 даёт только 10-битную точность. Проверить, достаточно ли. Если недостаточно, то надо руками тогда перенормировать.

  • roughness/metalness BC4 UNORM
  • combined roughness+metalness BC5 UNORM ?

Вроде так.

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

w23 commented 7 months ago

Кстати а как движковые текстуры к нам прилетают? В сыром несжатом виде? По идее их можно было бы BC1 (RGB5:6:5 + 1bit alpha) пожать на лету. Текстуры ещё там прилетают с 4 мипами их тоже можно было бы пожать. Хотя это наверное экономия на спичках?

Они прилетают уже разжатые RGBA32 (если не dds). Для оригинальных текстур это спички, да, там кот наплакал пикселей.

Для наших PNG жиробасов всё же уместнее их было бы более качественно паковать в оффлайне.

0x4E69676874466F78 commented 7 months ago

Как выяснилось, компрессонатор умеет только в UNORM, в BC7_SRGB он не умеет, имея только ошмётки дефайнов для этого формата для DX.

Существует не только он, я уже нашёл другие проги, но ещё не тестировал, поддержка BC7_UNORM_SRGB там есть. Для compressonator уже создал issue: https://github.com/GPUOpen-Tools/compressonator/issues/277

Тут вообще встаёт вопрос, как делает индустрия в целом, потому что выглядит слегонца странно.

Как понимаю:

  1. преобразуют SRGB в Linear перед упаковкой (жирная потеря в тенях, но учитывая современный подход с basecolor теней в текстурах нет, они стремятся быть плоскими) — это выглядит наиболее реалистичным.
  2. просто пакуют в UNORM и постфактум трактуя как удобно (делая SRGBtoLinear).
  3. забивают на проблемы с гаммой ("и так сойдёт").

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

Убедиться, что нормалмапа правильно предварительно отнормирована. Если почему-то нет, то отнормировать и перепроверить квантизацию.

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

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

Проверю.

Для BC6H HDR мы уже выяснили, что он в -1..1 даёт только 10-битную точность. Проверить, достаточно ли. Если недостаточно, то надо руками тогда перенормировать.

С этим форматом есть проблема, пока нет корректных средств для генерации таких нормалей (те файлы что я кидал они негодные), мне надо доработать materialize для этого. Пока эта задача отлетает на вторичный план, мало когда нужны 10битные нормали, это скорее задел на будущее.

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

Ничего подозрительного, это нормально и решаемо. Я думаю многие вещи сделать через паплайн в chainner и materialize.

0x4E69676874466F78 commented 7 months ago

Проверил быстро через kram (нет под линя, только винда и макось, но для теста сойдёт), kram encode -format bc7 -srgb -srcsrgb -i debug_gradient_color.png -o debug_gradient_color_BC7_SRGB.ktx2 Подгрузил на srgb-gamma бранче и всё ожидаемо нормализовалось: image На всякий случай проверил через серый градиент что формат вообще подгружается (он подгружается). Текстуры для теста: debug_gradient_BC7_SRGB.zip

w23 commented 7 months ago

kram можно попробовать портировать под линь, исходники есть.

0x4E69676874466F78 commented 7 months ago

2x2 black and white texture (checkerboard), scaled to a significant portion of the screen. This means that texture block will do interpolation for us in whatever texture colorspace is specified.

https://github.com/w23/xash3d-fwgs/pull/597#issuecomment-1753975750

0x4E69676874466F78 commented 7 months ago
  1. нормали я ещё не нормализовал (кроме где есть приписка _normalize)
  2. вот debug_dds.zip для тестов DDS, эти текстуры почему-то не грузятся
w23 commented 7 months ago
  1. нормали я ещё не нормализовал (кроме где есть приписка _normalize)

Не горит. Мы, если что, сможем и свой нормализатор написать.

  1. вот debug_dds.zip для тестов DDS, эти текстуры почему-то не грузятся

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

0x4E69676874466F78 commented 7 months ago

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

Ну в движке она есть, я думал там автоматом грузанёт, но нет.

0x4E69676874466F78 commented 7 months ago

Обновление схемы отсюда https://github.com/w23/xash3d-fwgs/issues/154#issuecomment-1750885440 Пока не утверждаем, а разбираемся:

0x4E69676874466F78 commented 7 months ago

Ещё информация:

  1. BC6H примерно всё понятно, всего 3 канала, он даёт достаточно хорошее качество.
  2. Эксперименталньо выяснилось что нормализация карт нормалей ухудшает качество, её стоит избегать. Что ещё сказано в этой статьей https://github.com/w23/xash3d-fwgs/issues/595#issuecomment-1754352511
0x4E69676874466F78 commented 7 months ago

Рано списал со счетов BC5, всё не так однозначно. Можно сказать что на крайних случаях BC5 не справляется, но BC6H имеет тоже свои артефакты/особенности. Нужно делать больше нормалей и ближе к реальности. Сделаю отдельную карту для этого. BC7 плох для нормалей.

0x4E69676874466F78 commented 7 months ago

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

w23 commented 7 months ago

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

Разборки с нормалями имо не для этой ишьи. Надо бы открыть отдельную, и резвиться там.

0x4E69676874466F78 commented 7 months ago

Хорошо, создал #608