Pull to refresh

Comments 69

Там используется YCbCr, у меня же после него был еще один вариант, более производительный (YCoCg), но более «мыльный» на сильном сжатии (64х64 при исходной 2048х2048). Так как это рантайм, то скорость важнее, чем качество на пограничных значениях.
по тому же принципу работает и JPEG

Там используется YCbCr

Возможно, под «тем же принципом» имелось в виду, что JPEG компоненты «цветов» хранит с меньшим разрешением, чем компоненту «светимости». Какое именно пространство Y** используется, тут менее принципиально.


более производительный (YCoCg)

Непонятно, за счёт чего YCbCr менее производительный — там же просто dot product.

В YCbCr — их 3 (по сути умножение на матрицу3х3) с разными весами, компилятор CG в юнити выдавал больше alu на выходе (8), чем в YCoCg (6). В последней версии был задействован 3 канал для предрасчетов и YCbCr догнал по скорости YCoCg + немного ускорился и YCoCg вариант — оба стали по 5 alu. Т.е. разумнее теперь всегда использовать YCbCr из-за меньшей размытости на экстремальном даунскейле текстуры с цветовой разницей (шейдер с суффиксом «Good quality»).
Да. Только вот видеопроцессор не работает с JPEG по тому же принципу.
Познавательно и интересно. Возьму на заметку. Спасибо!
А вы пробовали yuv420, который применяется при кодировании видео? Под него, по-идее, должна быть даже какая-то аппаратная поддержка на стороне видеокарт.
Так какая поддержка-то? Весь смысл в том, что оно упаковывается в офлайне как препроцессинг, а распаковывается в рантайме в момент рендеринга для каждого пикселя. Видео обычно пакуется разницой к предыдущему кадру, а тут такой информации нет (либо это очень плохо в плане производительности). То есть тут разговор именно про реалтайм производительность в игровом приложении, когда доступа к вендорным аппаратным реализациям нет (требуется обеспечить максимальную кросс-платформенность) — заработает на всем текущем железе, поддерживающем gles2.
Распаковка как раз. Ведь в конце концов, после какого нибудь h264 декодера будет текстура в формате yuv420, в которой цветовых пикселей в 4 раза меньше, чем яркости. А дальше его надо привести к стандартному RGB, чтобы выплюнуть в монитор, и именно это приведение я и имел в виду под аппаратной поддержкой. Степень сжатия, конечно, будет хуже, чем в вашем примере, но работать должно быстрее, если подобной фичей действительно можно воспользоваться.
Я понял в чем проблема — вы путаете cpu и gpu. В этом проекте нагрузка на cpu — ноль, все распаковывается на gpu для каждого пикселя, это и подразумевалось под «реалтаймом». Производительность просто несоизмерима между cpu и gpu. Вот вся эта «война» шла как раз за уменьшение нагрузки на каждый рисуемый пиксель.
Дак нет, я изначально писал из предположения, что при показе всё на стороне gpu делается, понятно, что на cpu такие вещи делать неправильно. Но ведь аппаратная поддержка видеодекодеров на стороне gpu, особенно в мобильных устройствах, есть почти во всех девайсах.
Нет, такой поддержки нет, есть универсальный формат ETC1 для всех android девайсов, есть PVRTC4 для sgx-ов на iOS, на WP вроде стоят adreno, те тоже только ETC1 и специфические для этого гпу-вендора (возможно на дровах сделана реализация DXT1).
А вот еще, из статьи в википедии:
YUV часто путают с цветовым пространством YCbCr, и, как правило, термины YCbCr и YUV используются как взаимозаменяемые, что приводит к некоторой путанице. Когда речь идет о видео или сигналах в цифровой форме, термин «YUV» в основном означает «Y’CbCr».

Собственно, про YCbCr и было в статье. Сегодня был апдейт в репозитории, возвращающий YCbCr в вариант бейка на равне с YCoCg. Получается более качественный контраст на лоурез-«цвете», а по нагрузке — одинаково, 5 алу, 2 фетча.
Разве все кодеки не распаковывают в RGB?
Не изобрели, а адаптировали под реалтайм рендер на дохлом железе.
Нет, это отличается от detail textures — тем, что тут с точностью наоборот!
— в detailed textures на цветную картинку налагается мелкий периодический чёрно-белый узор/фактура,
— а тут на цветную картинку налагается очень большая чёрно-белая картинка без периодичности.
Это не обязательно, «мелкость» узора/фактуры регулируется тайлингом, тут скорее отсылка к способу упаковки таких дитейлов — по 3-4 штуки в rgb/a каналы для уменьшения количества выборок в шейдере и возможности поддержки аппаратного сжатия.
Этот один гейм-дизайнер полтора года назад изобрёл по сути то, на чём основано цветное телевидение уже больше чем полвека.
Это не так. Внутри смешивание по Color-у реализуется через HSL пространство, а цветное телевидение работает через YCbCr. Но идея похожа, да.
Ну, я имею в виду ещё и то что разрешение цветового сигнала по вертикали в два раза ниже канала яркости. Как показала практика, для зрителя это совершенно не заметно. По сути, чёткость картинки определяется чёткостью исходной монохромной картинки, а то что она окрашена сверху цветовыми пятнами, никакого влияния на чёткость не оказывает (до определённого момента, конечно).
На первой картинке соотношение размеров верное — 256х256 у «цветной» текстуры, 2048х2048 у яркости, те тут не 1/4, а 1/64. Смысл тот же, да, результат — настраивается и зависит от жадности того, кто будет настраивать.
Вообще, статья не про то, что цвет и яркость можно разделять, на эту тему проводилось много исследований (даже в статье есть линк на конкретный документ с анализом десятка вариантов). Подумайте, откуда берется 3х сжатие? И нет, статья не про это тоже, не про «detail» текстуры. Статья — про комплексное решение с использованием нескольких несвязанных решений, готовое к применению и не сильно убивающее производительность.
Единственное что, не все текстуры одинаково хорошо будут смотреться после сжатия. Текстуры с тонкими линиями (текстом) будут не очень хорошо выглядеть (это, в принципе, всем знакомо, на примере JPEG vs PNG).
Так тут разговор про «сжатие сжатого», а у сжатых текстур по определению все плохо с четкими переходами цвета.

Такое "сжатие" — было единственным возможным режимом отображения картинки в Z80. :) Экран разбит на блоки 8x8 пикселей, для каждого хранилось 64 бита картинки и два цвета — фон/изображение.

Некорректное сравнение :) Да и там было не 2 цвета — еще был flash. Ну и мультиколор делали с привязкой к началу отрисовки экрана — получалось до 5-6 знакомест сделать полосочкой отдельного цвета. Ускоренный флиппинг бэкбуфера через стек, проигрывание музыки через nmi2. Да, я в курсе, бывший обладатель zs-scorpion 256 :)
Тут проблема была исключительно в скорости распаковки. У меня основное направление — это мобильный геймдев. Там за жирноту в потреблении ресурсов и покалечить могут :) А если вспомнить как работал Rage на старте и на толстом десктопном железе… Нет, нам такой футбол не нужен.
Там проблема была не в скорости распаковки.
Но я даже не о том, а больше о «новизне» вашей технологии. Вы по сути переизобрели JPEG, только первую его часть.
Даже не знаю, может этот комментарий в статью жирным вынести… Статья не про то. Никто ничего не изобретал, была попытка совместить известные технологии, чтобы оно работало максимально быстро на дохлом железе. И да, каждая инструкция на счету была — про это «третья попытка» и реализации множественных цветовых пространств.
Если я правильно понял, суть такова:
1) Переводим исходное изображение в YCoCg
2) Хроминанты даунскейлим
3) В шейдере восстанавливаем

Так?

Тогда мой самый первый комментарий 100% верен — если сверху добавить DCT сжатие — получим ту же технологию что и в Rage.
Убивать... Я же дал ссылку на комментарий где все описано. Почему ничего не сказано про вторую половину? Яркостные данные собираются в 1 текстуру, которая тоже жмется (без даунскейла). Извлечение цвета с его даунскейлом — это вообще побочная штука, которая была нужна исключительно для сжатия грейскейлов. Повторяю — не нужно рассматривать «ааа, это было в телевизерах 50 лет назад» и «ааа, дитейл текстуры изобрели» по отдельности, тут ничего нового, нужно рассматривать в комплексе. И на мобилках это решение будет функционировать без просадок производительности, что и требовалось получить + практически 3х экономия по памяти и филрейту.
По реализации — все правильно + выборка из атласа грейскейлов. На гитхабе лежит тестовый проект, можно посмотреть.
Почему ничего не сказано про вторую половину?

Там где «собрать в атлас»? Не думал что это достойно упоминания, довольно банальная вещь.

Убивать...

Ваша реакция на критику понятна.
Всего хорошего.
Не читать статью полностью, игнорировать один из основных тезисов, указанных в причинах всего это действа в начале — это критика? Что-то не так с этим миром, определенно.
а полноразмерные “грейскейлы” упакуем по 3 штуки в новые текстуры, то получим примерный размер: 0.043Мб * 9 + 3 * 2.7Мб = 8.5Мб

От повторного сжатия в DXT1 / ETC1 / PVRTC4 грейскейлы потеряют в качестве еще больше. Можно увидеть сравнение с текстурой меньшего разрешения?
Отчего же они потеряют больше? Процесс разложения проходит в офлайне (в редакторе, из исходной текстуры) еще до сжатия исходной текстуры в DXT/ETC/PVRTC — генерируются 2 текстуры с размеров в исходную. Потом уже можно менять размер «цветной» текстуры, подбирая на глаз — устраивает результат или нет. Посмотреть можно по ссылке в конце статьи — там готовый код с готовой картинкой + сгенерированные данные. Достаточно распаковать архив в пустой проект unity.
В самом проекте склеивания грейскейлов в 1 атлас нет, сожалею. Есть только указание цветовой плоскости для использования в качестве источника. Склеивание можно повторить в графическом редакторе, например, в gimp / photoshop.
Ну вот как раз от сжатия грейскейлов разных текстур в одном файле.
примеры грейскейлов, сжатых DXT1 в одном файле, и текстур в меньшем разрешении, сжатых по отдельности




1. Отдельно грейскейлы не сильно интересны — все-таки цвет будет маскировать артефакты частично.
2. Если есть плавные градиенты с плавным цветом и появляется бандинг — можно их не упаковывать в один атлас, а держать отдельным грейскейлом со сжатием — в шейдере указать любой канал. В примере сделано так.
3. В свойствах сжатия есть «качество» (в процентах): можно поменять скорость сжатия на результат.
4. Да, не серебрянная пуля, тут скорее упор на потребление памяти на ограниченном железе + небольшое пенальти по скорости распаковки на нем же.
можно их не упаковывать в один атлас, а держать отдельным грейскейлом со сжатием — в шейдере указать любой канал

Тогда ваш метод вообще не будет иметь смысла. С тем же успехом можно оставлять сжатую полноцветную текстуру, она будет занимать столько же памяти, сколько и отдельный грейскейл.
см.пункт 4 :) Если грейскейл может существовать только без сжатия, то явно найдутся и еще 3 такие же грейскейла, а это все равно упаковка в 1 текстуру слоями, но уже в RGB24. Вообще, если на грейскейле бандинг, то и на цветной версии он тоже есть, а это значит текстуры могут быть использованы только без сжатия. А отсюда — экономия от разделения и упаковки грейскейлов будет все-равно.
Вообще, если на грейскейле бандинг, то и на цветной версии он тоже есть

А вот это необязательно. На примерах, которые я кинул, большинство артефактов от того, что грейскейлы от разных текстур сжимаются в одном файле. Ведь DXT не сжимает каналы по отдельности. Про другие методы сжатия сказать ничего не могу.
А качество выкручено в 100% в каждой платформе?
Я сжимал через AMD Compressonator с максимальным качеством и равными весами у каналов.
Тогда могу только посоветовать чередовать / подбирать текстуры для внешней сжималки по примерно одинаковой яркости, возможно пропускать каналы. Еще вариант — провести дитеринг, как делали раньше, но вероятно это неприменимо для конкретного проекта.
А если уменьшить грейскейлы в 2 раза (получить 1/4 площади), склеить в атлас и без сжатия? Возможно, качество устроит ну конкретных изображениях. Ну и от 3 и более картинок в принципе должна быть выгода.
Еще можно попробовать сжимать не напрямую в юнити (там используется NEAREST фильтрация при усреднении), а в photoshop, например. Надо экспериментировать с настройками. Идеального решения на все случаи жизни не существует.
А конвертация HSL -> RGB была бы сильно медленнее?
В том же фотошопе, если поменять цветной и монохромный слои местами и выбрать вместо «Color» режим смешивания «Luminosity», результат визуально такой же.
При этом HSL хорошо знакомый всем формат, не требующий придумывания новых цветовых пространств… Но в конвертере один if точно есть. Или два даже, не помню.
Ну и про это «вторая попытка» — конечная сложность была 17 инструкций + 3 текстурных фетча, сейчас это 6 и 2 соответственно.
Круто. Спасибо! Использую некоторые ваши скрипты из пака утилит для юнити, теперь это надо попробовать.
Рад, что нашлось что-то полезное, только соблюдайте лицензию :)
Кстати, если не секрет — почему лицензия такая странная? Вы специально хотите, чтобы все, кому это надо для коммерческого применения, написали 100500 вариантов того же самого заново?
Вы хотите сделать коммерческое предложение? :)
Вы правда думаете, что кто-нибудь захочет заморочиться?

Просто реально странная ситуация получается. Понятно, что 95% потенциальных пользователей этого — проприетарные игры. Я мог бы понять GPL, скажем — типа, сподвигать людей делать больше открытого кода. Мог бы понять BSD/MIT/что-то подобное пермиссивное — типа, вот — придумал — берите — пользуйтесь. Но смысл CC-BY-NC-SA? «Любуйтесь как есть, но не трогайте?»

Так получается — «ни нашим, ни вашим». С open source в массе своей несовместимо, с проприетарными — тоже не совместимо. Понятно, что пользуясь идеями из статьи — кому нужно — за 20-30 минут сделают свое такое же… В итоге вы получаете массу реализаций описанного вами, но вообще без каких-либо отсылок к вам (как могло бы быть при MIT хотя бы) — в чем вам от этого профит?..
Но смысл CC-BY-NC-SA

Раз такая лицензия существует, значит кому-то нужно.

С open source в массе своей несовместимо

Пояснить можете, почему несовместимо с опенсорсом? Основной посыл — пилите опенсорс и делитесь идеями / наработками. Хотите зарабатывать деньги на чужом труде без вкладывания своего и публикации фиксов в сообщество — попробуйте перелицензировать под коммерцию. Вроде все просто и понятно.
Думаю, в данном конкретном случае вопрос в целесообразности подхода «Хотите зарабатывать деньги на чужом труде....» и т.д.
Всё ценное и так есть в статье в открытом доступе, а объём готового кода слишком мал, чтобы кто-то заморачивался с лицензированием, проще самим с нуля написать.
То есть вы не получите ни денег (т.к. это не имеет смысла для потенциальных покупателей) ни популярности (т.к. ни в одной независимой реализации на вас даже ссылки не будет).

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

У каждого свой путь — пусть кто-то переписывают по-своему, а кому-то проще получать фиксы / апдейты без дополнительных усилий (те по сути делегирование работы на других с получением саппорта). Базовая лицензия выбрана и изменена не будет, двойное лицензирование на коммерцию возможно. Про опенсорс и открытость было написано выше. Да, есть принципиальные воры, тут уж ничего не поделаешь, это на их совести.
Про опенсорс писали потому, что «опенсорс» и «коммерческая лицензия» — это вещи не взаимоисключающие. Особенно в специфике геймдева, где абсолютно не коммерческих проектов почти нет.
А так, не споря с вашими изначальными намерениями, вы в полном праве, по факту вы запретили только ссылаться на себя как на автора концепции. Тут даже «принципиально воровать» нечего.
Пояснить можете, почему несовместимо с опенсорсом?

Потому, что CC-BY-NC-SA будут несовместимы с любыми популярными open source лицензиями. Ни GPL, ни тем более BSD/MIT/другие permissive — не имеют органичения NC.


Основной посыл — пилите опенсорс и делитесь идеями / наработками. Хотите зарабатывать деньги на чужом труде без вкладывания своего и публикации фиксов в сообщество — попробуйте перелицензировать под коммерцию. Вроде все просто и понятно.

Только с такой исходной постановкой задачи желания у кого-то пилить опен-сорс не будет — и да сообщества как бы тоже не будет. Если это (в 95% это будет так) разработчик коммерческой проприетарной игры — то он вынужден будет написать свое. В лучшем случае он выложит это под GPL/MIT, но не как развитие вашего кода, а как проект, написанный с нуля — и туда, может быть, что-то будут контрибьютить. Даже в оставшихся 5% случаев разработчика open source игры — он вынужден будет поступить так же, переписать.


В итоге, да, я абсолютно согласен с maxpsyhos, вы по сути лишили себя авторства. Всю славу, почести и сообщество получит первый, кто перепишет ваш код под MIT.


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

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

А если внимательно прочитать wallpaperswide — то про лицензирование этого изображения там ни слова. В ToS у них что-то расплывчатое про, мол, у нас user-submitted content, если что — ищите концы сами и обращайтесь к оригинальным авторам. Оригинальный автор, судя по странице на wallpaperswide — marxpix на flickr, но я не нахожу у него (или скорее нее) эту фотографию с каким-нибудь четким условием лицензирования. Единственная доступная там фотография — https://www.flickr.com/photos/marxpix/3794841848/ — под CC-BY-ND. Если допустить, что другие ее работы были опубликованы под такими же условиями — то это явный запрет использовать их так, как используете вы.

Тестовый контент не является частью проекта, об этом было указано с указанием источника.
ToS у них что-то расплывчатое

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

А почему цвет можно уменьшить до 256*256? Потери качества при масштабировании до 2048 Будут не видны?

Конечный размер подбирается «на глаз» по качеству, под каждый набор изображений. При площади 1/64 от исходной качество вполне приемлемое, на шумных и относительно однотонных изображениях можно и меньше размер поставить. Ну и разговор шел про «сжатие сжатого»: https://habrahabr.ru/post/316672/#comment_9943234
упакованные данные (CoCg) содержатся в RG-каналах

А что с картинками в которых присутствует синий цвет?
(можно пример?)
RGB данные картинок упаковываются в эту цветовую разницу (2 канала) и восстанавливаются в шейдере. В последнем апдейте третий канал содержит часть промежуточных рассчетов, что позволило еще ускорить обработку и получить одинаковую скорость на YCbCr и YCoCg. Пример — в статье есть линк на гитхаб, вот можно скачать архив и закинуть в пустой юнити-проект, потом из главного меню упаковать любую картинку или сразу 3 (добавлена упаковка грейскейлов в атлас) + настроить материалы и посмотреть.
Sign up to leave a comment.

Articles