предисловие
Рендеринг традиционных веб-страниц основан на пиксельных единицах, поэтому изображения нельзя масштабировать до любого размера, такого как SVG, и они имеют плоские края. То есть увеличение картинки пиксельной логики неизбежно приведет к снижению визуального качества (искажению информации). Поэтому мы часто используем технические средства, чтобы избежать искажений, такие как:
- Замена растровых изображений на SVG
- Замена растровых шрифтов векторными шрифтами, такими как шрифты TrueType.
Если вам придется выполнять манипуляции с пикселями, у нас также есть множество средств для исправления искажения:
- Используйте свойство CSS Image-Rendering для настройки алгоритма выборки при масштабировании изображения.
- Плавный рендеринг шрифтов с помощью свойства CSS Font-Smoothing
- Используйте API сглаживания Canvas при рисовании
- Увеличьте размер элемента, затем используйте Transform, чтобы восстановить размер макета.
- В некоторых особых случаях вы можете использовать аппаратное ускорение браузера, чтобы сгладить алиасинг.
Размытие картинки, чтобы заставить пользователя включить титановый сплав
В этой статье мы кратко коснемся вышеперечисленных моментов и представим новую идею сглаживания с помощью CSS BackgroundImage (я называю это сглаживанием Pixel-Offset Anti-Aliasing). Следует заранее отметить, что текущее разрешение экрана мобильных телефонов достаточно высокое, а производительность процессора очень слабая, что напрямую приводит к тому, что о сглаживании в мобильных браузерах говорить не приходится. Эта статья в значительной степени ограничена большими мониторами на рабочем столе (надеюсь, вы не читаете этот блог с монитором 8K).
Сглаживание и родственные технологии
сглаживание
Искажение информации (алиасинг) и алиасинг изображения — это не одно и то же, но для геймеров их можно почти приравнять. Чтобы использовать сглаживание CSS, мы должны сначала упомянуть о формировании сглаживания.
Почему возникает неровность?
Наши глаза воспринимают форму объекта и распознают «линию», которой на самом деле не существует. Глядя на изображение ниже, мы можем почувствовать линии, хотя они не выглядят очень плоскими:
Рисунок ниже на фиг.1, линии со стрелками представляют сегмент, который мы воспринимаем, остальные сегменты линии пересекают сетку, представляющую сетку пикселей. Его можно узнать из рисунка, главное, чтобы линия со стрелкой, проходящей через это место, была залита желтым цветом. Но идеальная линия идеальна, она абсолютно ровная. Гладкий сегмент неопределенного направления отображается на пиксели, расположенные на экране с низким DPI, произойдет потеря информации. Чем крупнее частицы пикселя, тем серьезнее потеря информации (далее пилообразная).
Как он выглядит как зуб пилы?
Вот нарисовал картинку, можете внимательно ее рассмотреть, а потом встаньте чуть подальше от дисплеящурясьСмотреть:
Вокруг пикселей я добавляю немного недостающей информации желтыми каракулями. Размер желтого граффити на рисунке представляет прозрачность пикселей. Вот сглаженное изображение готового продукта, где видно, что края фигуры заполнены пикселями с прозрачностью:
Общие методы сглаживания
В области звука мы можем уменьшить искажение информации, поступающей в ухо, с помощью высококачественных проигрывателей и звука без потерь. Но в игровой сфере обычные игроки не могут подготовить мониторы 8K дома. Наряду с развитием разрешений мониторов от 720p до 1080p появилось несколько технологий сглаживания, которые также выросли с развитием игровой индустрии.
- SSAA (суперсэмплинговое сглаживание)
Сглаживание суперсэмплирования, оно удвоит разрешение текущего рендеринга экрана, например, 1024 × 768 графики после 2-кратного включения SSAA, фактическая работа видеокарты станет 2048 × 1536, после этого будет пониженная дискретизация. больше Слияние пикселей, которое сопоставляется с одним пикселем дисплея. Смешивание пикселей делает цветовые переходы более естественными и выглядит без заметных глюков. Однако, поскольку аппаратные операции увеличиваются (в геометрической прогрессии), можно предположить, что они будут потреблять чрезвычайно высокую производительность.
- MSAA (многосэмплинговое сглаживание)
Мультисэмплинговое сглаживание, которое выполняет мультисэмплинг данных определенной области буфера — его можно просто понимать как мультисэмплинг краев полигона. Расход производительности высокий, но эффект тоже хороший.
- FXAA (быстрое приближенное сглаживание)
Быстрое приближенное сглаживание, которое находит и сглаживает края всей графики в кадре. Хотя многие графические края не соответствуют краям (например, материалам и текстурам), которые фактически моделируются игрой, FXAA является распространенным выбором для сглаживания из-за низкого потребления производительности и высокой стоимости производительности.
- DLSS (суперсэмплинг с глубоким обучением)
Суперсэмплинг глубокого обучения, в котором используются алгоритмы глубокого обучения с аппаратным ускорением для рендеринга изображений с низким разрешением в режиме реального времени на основе данных из нескольких аспектов геометрии, затенения и временных областей (говорящие люди основаны на таких данных, как прошлые кадры, формы и т. д.). , и импульс пикселя). Реконструирует множественные результаты суперсэмплинга. По сравнению с традиционным рендерингом он может не только значительно улучшить качество изображения, но и значительно повысить частоту кадров.
CSS-сглаживание
Ниже мы упомянем несколько распространенных методов сглаживания.
CSS Font-Smoothing
Свойство font-smoothing принадлежало ранней спецификации CSS и позже было удалено по разным причинам. Однако совместимость по-прежнему возможна с помощью префиксных атрибутов (таких как-webkit-font-smoothing
). В общем, сглаживание шрифта имеет три значения на выбор,none
,subpixel-antialiased
,antialiased
.值的作用正如其名,分别是无抗锯齿,亚像素级抗锯齿和(全像素)抗锯齿。
Вообще говоря, каждый пиксель на экране состоит из трех полос основного цвета (это могут быть три светящиеся точки, такие как красная, зеленая и синяя). Субпиксельное сглаживание, что означает, что шрифт будет отображаться в единицах субпикселя (например, красный свет). Пиксели, которые не излучают свет, отображаются черными, а остальные пиксели кажутся темными при сглаживании, как показано ниже:
Полнопиксельное сглаживание, при котором шрифты отображаются в единицах целых пикселей (включая три полосы красного, синего и зеленого цветов). Во время сглаживания, если размер шрифта превышает единицу в один пиксель, он будет сглажен с примыкающим к нему прозрачным темным пикселем, как показано на следующем рисунке:
Слово «назад» в «Обратной волне», горизонтальная линия посередине, на самом деле имеет ширину менее одного пикселя, поэтому оно также отображается прозрачными темными цветами. За исключением отдельных слов, в@MAXVOLTARЭтот блог с примерами изображений английского набора текста цитируется ниже:
-
none
-
subpixel-antialiased
-
antiliasing
Как выбрать три значения?
Мой совет — просто понять механизм рендеринга и то, как он рендерится.Пиксельное сглаживание делает шрифты немного тоньше, а субпиксельное сглаживание делает шрифты толще. На черном фоне наоборот. Вам не обязательно использовать его только потому, что вы его знаете — у всех трех есть свои преимущества и недостатки. В общем, отбросьте этот атрибут и дайте браузеру решить, как должен отображаться шрифт. Если вы вводите специальные шрифты (например, типографские шрифты) для сглаживания. (Я считаю, что на китайской веб-странице возможности для бесплатной игры должны быть очень ограничены.)
В приложении, если вам интересно, я оставил соответствующую ссылку в конце статьи, вы можете обратиться к ней снова.
CSS Image-Rendering
Свойство Image-Rendering используется для задания алгоритма масштабирования изображения, для этого свойства есть несколько общих значений. См. следующие компоненты:
Можно обнаружить, что после установки значения Pixelated браузер не сглаживает края, а Auto смягчает все изображение. То есть, используя Transform Scale для увеличения изображения, браузер применит алгоритм плавного масштабирования по умолчанию (вероятно, билинейная интерполяция или что-то в этом роде).
Можно ли увеличить картинку в несколько раз, а потом уменьшить до реального размера? Вот результаты теста:
Я не знаю, оптимизирует ли браузер объединение нескольких масштабов или использует какой-то алгоритм выборки, который не теряет информацию об изображении, короче говоряПопытка использовать плавное изображение без изменения размера изображения не сработает..
Аппаратное ускорение сглаживания
Что касается использования браузерной функции сглаживания с аппаратным ускорением, я столкнулся с ней во время экспериментов с PXAA (но я уже писал об этом в блоге). Когда элемент поворачивается с помощью Transform:Rotate, если элемент визуализируется графическим процессором, будут применены свойства сглаживания браузера, соответствующего графическому процессору — например, если вы используете браузер на GTX 1060ti, соответствующая конфигурация можно найти в панели управления NVIDIA, найти в (но это в значительной степени мое предположение, нужно проверить). Это звучит немного сложно, но следующий пример прояснит ситуацию с первого взгляда:
Когда элемент поворачивается и применяется аппаратное ускорение (TranslateZ), визуализированные края сглаживаются. но еслиТолько включение аппаратного ускорения или использование только вращения не даст эффекта..经过我的测试,在 Windows 端 Chrome 内核的浏览器,这种抗锯齿方式能得到一些体验——你甚至可以通过仅旋转 0.1° 来柔和边缘(虽然不明显)。
Это конец технологии сглаживания, связанной с CSS, и следующий раздел начинается с новых идей.
Pixel-Offset Anti-Aliasing
Pixel offset anti-aliasing (сокращенно POAA), это очень волшебный метод, кажется, им никто не делился в интернете, но эффект действительно потрясающий. Я не знаю, что именно работает, но это просто работает (работает!). Вот два изображения, нарисованные с использованием свойства BackgroundImage, позвольте мне показать результат после применения POAA:
Показать результаты
принцип
Обычная технология сглаживания в играх основана на данных, сгенерированных в несколько этапов от модели до освещения до или после рендеринга игры, поэтому мы можем фильтровать информацию в соответствии с содержанием истории кадров, импульсом пикселей, повышающей дискретизацией и т. д. и перестраивать экран. Но контент, отображаемый браузером пользователю, можно назвать отображаемым контентом. Похоже, мы мало что можем сделать для рендеринга внутри браузера (возможно, в будущем появится CSS Houdini). Скажем, используя BackgroundImage для рисования этих пикселей на экране, вы не можете изменить их с помощью рендеринга и не можете сказать браузеру «вы должны сделать это» с предварительно обработанными данными. Но хорошая новость в том, что программисты — это люди, которые верят, что любую проблему можно решить, здесь мы меняем образ мышления.
Я думаю, вы должны помнить, что мы упоминали FXAA в начале. FXAA можно просто обобщить как два шага поиска края -> восстановление края (не профессионально, может быть будет коррекция и т.д., я не знаю). существуетImplementing FXAAВ этом блоге я подробно объясняю, как работает FXAA. Для найденного края фигуры он станет таким после обработки FXAA, см. следующие два рисунка:
Подача исходного изображения в FXAA позволяет определить края объектов по цвету или контрасту и сгладить общий вид, изменив непрозрачность точек вокруг пикселей. Если подумать, при рисовании с помощью BackgroundImage мы уже знаем, где находятся края. Преимущество не спрятано в шляпе короля, оно в коде, который мы пишем. Например, исходный код кругового градиента в предыдущем разделе выглядит следующим образом:
.circle-con {
$c1: #cd3f4f;
$c2: #e6a964;
position: relative;
height: 300px;
background-image: repeating-radial-gradient(
circle at 0% 50%,
$c1 0,
$c2 50px
);
}
Мы можем легко найти края - да, где цвет градиента меняется - 0px (50px). Теперь, когда у нас есть информация о ребре, пришло время реконструировать ребро. Восстановленное ребро можно разделить на следующие этапы:
- Точки, которым нужно каким-то образом добиться прозрачности
- Эти точки должны иметь возможность образовывать отрезки.
- Сегменты линий точно соответствуют нашему фоновому изображению.
- Сделайте сегмент линии наложенным поверх BackgroundImage, чтобы применить наши изменения.
Это общая идея, мы занимаемся рендерингом не через браузер, а через метод постобработки типа FXAA. Поднимите шум на визуализированном изображении. Однако после тщательного рассмотрения вышеуказанных шагов вы обнаружите, что сложность проблемы заключается в том, как создать полосы сглаживания.
Короче говоря, нам нужно продолжать совершенствовать наше мышление.
В BackgroundImage пиксель является базовой единицей и больше не может быть разделен, а прозрачность точки, очевидно, не может быть смоделирована размером точки. Здесь есть два обходных пути:
- Непрозрачность, используйте непрозрачность CSS или функции CSS RGBA, функции SCSS.
- Слияние двух цветов имитирует прозрачность пикселей.Если вы не хотите задействовать JS, SCSS также может решить эту проблему.
Что касается сегмента линии, то его также можно смоделировать с помощью BackgroundImage, например, для приведенного выше кода CSS его можно переписать следующим образом:
.circle-con {
$c1: #cd3f4f;
$c2: #e6a964;
$line-width: 1px;
position: relative;
height: 300px;
background-image: repeating-radial-gradient(
circle at 0% 50%,
$c1 0,
transparent calc($line-width),
transparent calc(50px - $line-width),
$c2 50px
);
}
Получив отрезок, сместите контейнер на несколько единичных пикселей и поместите его в результат теста браузера:
Можно обнаружить, что сегменты линий, состоящие из смешения цветов и прозрачности, будут получены естественным образом. Просто направление прозрачности не то, что нам нужно. Я хотел бы получить шаблон с перевернутыми прозрачными линиями:
Поэкспериментировав, я обнаружил, что работает простое изменение порядка цветов на противоположное. Допустим, это отрезок, нарисованный на 50% контейнера:
.old {
background: linear-gradient(
var(--deg),
transparent,
transparent
calc(50% - var(--line-width)),
yellow 50%,
red 50%,
transparent calc(50% + var(--line-width)),
transparent
);
}
Если цвета линейного сегмента поменять местами, получится:
.new {
background: linear-gradient(
var(--deg),
transparent,
transparent
calc(50% - var(--line-width)),
red 50%,
yellow 50%,
transparent calc(50% + var(--line-width)),
transparent
);
}
Мы получили желаемый эффект размытия сегмента линии! Следующее, что нужно сделать после этого, это подогнать линии.
Далее настал момент стать свидетелем чуда:
Well done!
Вот готовый GIF, который лучше всего смотреть немного дальше от экрана:
В готовом продукте добавлен некоторый контент и скорректированы соответствующие параметры на основе совпадающих строк:
- Различное смешивание темных и светлых значений прозрачности
- Различные смещения для осей X и Y
- Скорректирована толщина подогнанных сегментов линии.
Готовый код выглядит следующим образом:
.repeat-con {
--c1: #cd3f4f;
--c2: #e6a964;
--c3: #5996cc;
position: relative;
height: 300px;
background-image: repeating-linear-gradient(
var(--deg),
var(--c1),
var(--c1) 10px,
var(--c2) 10px,
var(--c2) 40px,
var(--c1) 40px,
var(--c1) 50px,
var(--c3) 50px,
var(--c3) 80px
);
&.antialiasing {
&:after {
--offsetX: 0.4px;
--offsetY: -0.1px;
--dark-alpha: 0.3;
--light-alpha: 0.6;
--line-width: 0.6px;
content: '';
position: absolute;
top: var(--offsetY);
left: var(--offsetX);
width: 100%;
height: 100%;
opacity: 0.5;
background-image: repeating-linear-gradient(
var(--deg),
var(--c3),
transparent calc(0px + var(--line-width)),
transparent calc(10px - var(--line-width)),
var(--c2) 10px,
var(--c1) 10px,
transparent calc(10px + var(--line-width)),
transparent calc(40px - var(--line-width)),
var(--c1) 40px,
var(--c2) 40px,
transparent calc(40px + var(--line-width)),
transparent calc(50px - var(--line-width)),
var(--c3) 50px,
var(--c1) 50px,
transparent calc(50px + var(--line-width)),
transparent calc(80px - var(--line-width)),
var(--c1) 80px
);
}
}
}
Теоретически с помощью функции SCSS можно автоматически определить положение линейного сегмента в коде и сгенерировать заполненные сглаживанием пиксели. Будь то LinearGradient, ConicGradient или RadialGradient, сглаживание возможно. Однако я просто написал это в качестве эксперимента, поэтому я не написал соответствующую служебную функцию. Дополнения на Github приветствуются.
Практика и постскриптум
Когда я бездельничаю дома и играю на CodePen, наблюдая, как большие штрихи рисуются с помощью BackgroundImage, хотя это выглядит хорошо, зубы разрывают сердце. Поэтому мне пришла в голову идея попробовать сделать демо-версию сглаживания (конечно, крепкое здоровье — движущая сила). Изначально эта штука должна была превратиться в фрагмент кода (похожий на Gists, что впрочем не так важно), но позавчера я увидел в статье, рекомендованной Nuggets, пользователя сети, который использовал BackgroundImage для рисования кружочка купонов. с отсутствующими углами, которые подарили мне Inspired, напрямую породили блог «Магия CSS».
Что касается конкретного сценария применения, я должен уточнить, что POAA подходит только для мониторов с низким разрешением (строго говоря, это зависит от DPI, то есть соотношения разрешения и размера. Это похоже на 2K-монитор, который я использую, но потому что из-за своего большего размера, поэтому можно добиться эффектов с помощью POAA), что, естественно, исключает такие устройства, как компьютеры Apple или мобильные телефоны. ПОАА можно использовать только как техническое дополнение.Поскольку делать практический выбор не удобно, я называю это "иллюзией". Если вам нужно рисовать в браузере в продакшене, то вы обязательно сначала решите использовать SVG и Canvas. По моему мнению, выбор рисунка BackgroundImage происходит только тогда, когда требуется время и простота (например, рисование купонов). Это ставит BackgroundImage в неловкое положение, как замену для разработчиков, которые не знают, как использовать SVG. Но... разве SVG не должен быть тем, чем дизайнеры должны овладеть? Так что кто должен рисовать графику, я не знаю.
Напоследок рекомендую всем зайти в мой блог, вмой блогЗдесь вы можете испытать на себе магию POAA с помощью джойстиков и консолей.
Ах, когда я писал эту статью, я выпил как минимум 3 бутылки Fat House Happy Water. Должно быть, я снова толстая и плачу. Я все это видел здесь, так почему бы тебе не утешить меня трижды перед отъездом?/(ㄒоㄒ)/~~
Пасхальные яйца:высвобождение мозга
Ну, то, что я хочу представить здесь, это не «чистое высвобождение мозга», а идея сначала размыть картинку, чтобы сгладить края графики, а затем повысить резкость картинки, чтобы усилить края. Этот метод часто используется в повседневной жизни с использованием таких инструментов, как PhotoShop для обработки изображений; иногда таким же образом обрабатывается улучшение изображения в компьютерных играх.
Сначала размывайте, затем повышайте резкость, два шага нельзя поменять местами, и настройка параметров также очень важна (очень метафизична). Вот что я пробовал, когда экспериментировал в своем блоге:
- CSS Filter объединяет пользовательские фильтры SVG
- CSS-фильтр объединяет фильтры Blur и Contract.
Но к сожалению, уровень ограничен, и желаемого эффекта так и не удалось добиться, так что дело сразу закрыто, и следующий вопрос.