Режим наложения цветов в шейдере (режим наложения)

внешний интерфейс WebGL дизайнер Photoshop

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

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

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

1. Определение

Во-первых, давайте определим, что такое гибридный режим:

Режим наложения — это технический термин в технологии обработки изображений, который используется не только в широко используемом Photoshop, но также в After Effect, Illustrator, Dreamweaver, Fireworks и других программах. Основное преимущество заключается в том, что цвет объекта можно по-разному смешивать с цветом основного объекта. Когда вы применяете режим наложения к объекту, эффекты режима наложения видны на любых объектах ниже слоя или группы объекта. -- Энциклопедия Байду

Adobe также специально вводит знания о режимах наложения:help.Adobe.com/capable/photo ШО…

Мы просто перечисляем различные режимы наложения:

  • Обычный: отредактируйте или закрасьте каждый пиксель, чтобы сделать его результирующим цветом. Это режим "по умолчанию". (Обычный режим также известен как пороговое значение при работе с растровыми изображениями или изображениями с индексированными цветами.)
  • Растворить: отредактируйте или закрасьте каждый пиксель, чтобы сделать его результирующим цветом. Однако в зависимости от непрозрачности любого местоположения пикселя результирующий цвет случайным образом заменяется пикселями основного или смешиваемого цвета.

  • Затемнить (Затемнить): просмотрите информацию о цвете в каждом канале и выберите основной цвет или более темный цвет наложения в качестве результирующего цвета. Пиксели светлее накладываемого цвета будут заменены, а пиксели темнее накладываемого цвета останутся без изменений.
  • Умножить: просмотр информации о цвете в каждом канале и умножение основного цвета на смешанный цвет. Результирующий цвет всегда более темный. Умножение любого цвета на черный дает черный цвет. Любой цвет остается неизменным с помощью White Multiply. Когда вы рисуете цветами, отличными от черного или белого, непрерывные мазки, нарисованные инструментом рисования, постепенно создают более темные цвета. Это похоже на рисование изображения с несколькими маркерами.
  • Цветной огонь: просмотрите информацию о цвете в каждом канале и затемните основной цвет, чтобы отразить смешанный цвет, увеличив контраст между ними. Никаких изменений при смешивании с белым.
  • Линейный прожиг: просмотрите информацию о цвете в каждом канале и затемните основной цвет, уменьшив яркость, чтобы отразить смешанный цвет. Никаких изменений при смешивании с белым.
  • Темный цвет: сравнивает сумму всех значений канала цвета наложения и основного цвета и отображает цвет с меньшим значением. «Темный» не генерирует третий цвет (который можно получить с помощью смешивания «Темный»), потому что он берет наименьшее значение канала из базовых и смешанных цветов для создания результирующего цвета.

  • осветлить: просмотр информации о цвете в каждом канале и выбор основного цвета или более светлого цвета наложения в качестве результирующего цвета. Пиксели темнее накладываемого цвета заменяются, а пиксели ярче накладываемого цвета остаются без изменений.
  • Экран: просмотр информации о цвете каждого канала и умножение дополнительного цвета накладываемого цвета на основной цвет. Полученный цвет всегда светлее. Цвет остается прежним при фильтрации черным цветом. Фильтрация с помощью белого даст белый цвет. Эффект похож на несколько слайдов фотографий, проецируемых друг на друга.
  • Уловка цвета: просмотрите информацию о цвете в каждом канале и осветлите основной цвет, чтобы отразить смешение, уменьшив контраст между ними. Смешивание с черным не меняет.
  • Линейный уклон: просмотр информации о цвете в каждом канале и повышение яркости основного цвета путем увеличения яркости для отражения совмещенного цвета. Смешивание с черным не меняет.
  • Более светлый цвет: Сравните сумму всех значений канала смешанных цветов и основных цветов и цвета большего значения. «Свет» не генерирует третий цвет (который можно получить с помощью «яркости», поскольку он выбирает максимальное значение канала из основного цвета и смешивает цвета для создания результирующих цветов.

  • Наложение: умножает или фильтрует цвета в зависимости от основного цвета. Узор или цвет накладываются на существующие пиксели с сохранением светотени основного цвета. Базовый цвет не заменяется, но базовый цвет смешивается с накладываемым цветом, чтобы отразить яркость или темноту основного цвета.
  • Мягкий свет: Делает цвет темнее или светлее в зависимости от смеси. Этот эффект похож на рассеянный прожектор, падающий на изображение. Если накладываемый цвет (источник света) светлее 50% серого, изображение становится ярче, как если бы оно было осветлено. Если накладываемый цвет (источник света) темнее 50% серого, изображение затемняется, как если бы оно было затемнено. Затенение с использованием чистого черного или чистого белого дает области, которые заметно затемняются или осветляются, но не являются чисто черными или чисто белыми.
  • Жесткий свет: умножение или фильтрация цвета в зависимости от накладываемого цвета. Этот эффект подобен ослепительному прожектору, падающему на изображение. Если смешанный цвет (источник света) ярче 50 % серого, изображение становится ярче, как в случае эффекта фильтрации. Это полезно для добавления бликов к изображениям. Если смешанный цвет (источник света) темнее 50 % серого, изображение становится темнее, как в случае эффекта мультипликатора. Это полезно для добавления теней к изображениям. Окрашивание чистым черным или чистым белым цветом приведет к чистому черному или чистому белому цвету.
  • Яркий свет: Делает цвет темнее или светлее за счет увеличения или уменьшения контрастности в зависимости от накладываемого цвета. Если смешанный цвет (источник света) ярче 50% серого, сделайте изображение ярче, уменьшив контраст. Если смесь темнее 50% серого, затемните изображение, увеличив контраст.
  • Линейный свет: Делает цвет темнее или светлее, уменьшая или увеличивая яркость, в зависимости от накладываемого цвета. Если смешанный цвет (источник света) ярче 50 % серого, осветлите изображение, увеличив яркость. Если смесь темнее 50% серого, затемните изображение, уменьшив яркость.
  • Контактный свет: замена цвета в соответствии с накладываемым цветом. Если цвет наложения (источник света) ярче, чем 50% серого, замените пиксели, которые темнее, чем цвет наложения, не изменяя пиксели, которые светлее, чем цвет наложения. Если накладываемый цвет темнее 50% серого, пиксели, которые светлее накладываемого цвета, заменяются, а пиксели, которые темнее накладываемого цвета, остаются без изменений. Это полезно для добавления специальных эффектов к изображениям.
  • Жесткий микс: Добавляет значения красного, зеленого и синего каналов смешанного цвета к значениям RGB основного цвета. Значение равно 255, если сумма результатов каналов больше или равна 255; если меньше 255, значение равно 0. Следовательно, значения красного, зеленого и синего каналов всех смешанных пикселей равны либо 0, либо 255. Этот режим изменяет все пиксели на доминирующий аддитивный цвет (красный, зеленый или синий), белый или черный.

  • Разница: просмотрите информацию о цвете в каждом канале и вычтите совмещенный цвет из основного цвета или вычтите базовый цвет из совмещенного цвета в зависимости от того, какой цвет имеет большее значение яркости. Смешивание с белым инвертирует значения основного цвета, смешивание с черным не дает никаких изменений.
  • Исключение: создает эффект, аналогичный режиму «Разница», но с более низкой контрастностью. Смешивание с белым инвертирует значения основного цвета. Смешивание с черным не меняет.
  • Вычесть: просмотр информации о цвете в каждом канале и вычитание накладываемого цвета из основного цвета. В 8-битных и 16-битных изображениях любые результирующие отрицательные значения обрезаются до нуля.
  • Делить: просмотр информации о цвете в каждом канале и разделение совмещенного цвета с основным цветом.

  • оттенок: Создает результирующий цвет со светлотой и насыщенностью основного цвета и оттенком совмещенного цвета.
  • Насыщенность: Создает результирующий цвет со светлотой и оттенком основного цвета и насыщенностью совмещенного цвета. Рисование в этом режиме областей без (0) насыщенности (оттенки серого) не дает никаких изменений.
  • Цвет: Создает цвет результата с легкостью базового цвета и оттенка и насыщение цвета смеси. Это сохраняет серого в образе и полезно для окрашивания как монохромных изображений, так и цветных изображений.
  • Светимость: Создает результирующий цвет с оттенком и насыщенностью основного цвета и яркостью наложенного цвета. Этот режим создает эффект, противоположный цветовому режиму.

Чтобы получить соответствующую формулу расчета, вы также можете просмотреть эффект смешивания непосредственно по этому онлайн-адресу:jamieowen.github.io/glsl-blend/(Картинка использована не очень, эффект не очень хорошо виден)

2. Используйте

Хорошая новость заключается в том, что нам не нужно повторять приведенную выше логику, эта библиотека Github уже помогла нам реализовать большинство гибридных режимов:GitHub.com/Джейми Оуэн/…Шейдер может напрямую видеть:

Когда вам нужны режимы наложения слоев? Вот пример Douyin. Вы можете видеть, что под этим видео есть специальный эффект под названием «Неон»:

Фактическое приложение к эффекту таково:

Итак, как мы можем этого достичь? Во-первых, достигается неоновый эффект, который представляет собой просто круг с размытым краем, как показано ниже:

// 封装了一个函数
vec3 drawLeaks(vec2 _uv, vec2 position, vec2 speed, vec2 size, vec3 resolution, vec3 color, float t, vec2 range) {
    vec2 leakst = _uv;
    vec2 newsize = normalize(size);
    newsize /= abs(newsize.x) + abs(newsize.y);

    leakst -= .5;                           // 坐标系居中
    leakst.x *= resolution.x/resolution.y;  // 等比例缩放

    leakst.x -= position.x;                 // 位置调整x
    leakst.y -= position.y;                 // 位置调整y

    leakst.x -= speed.x * t * 10.;          // 运动速率x
    leakst.y -= speed.y * t * 10.;          // 运动速率y

    if (newsize.x < newsize.y)              // 大小比例调整
        leakst.y *= newsize.x / newsize.y;  
    if (newsize.x > newsize.y)
        leakst.x *= newsize.y / newsize.x;

    float angle = atan(leakst.y, leakst.x); // 笛卡尔转极坐标
    float radius = length(leakst);

    vec3 finalColor = vec3(smoothstep(range.x, range.y, radius))*color*(1.-t);   // 预设size&上色
    return finalColor;
}

void main() {
    vec3 leakColor = drawLeaks(myst, vec2(.0, .0), vec2(.0, .0), 
                        vec2(.0, .0), iResolution,
                        vec3(166./255., 66./255., 65./255.)*1.5, 0., vec2(.3, 0.));

    gl_FragColor = vec4(leakColor, 1.);
}

Эффект следующий:

На данный момент под этим эффектом можно понимать «слой» в PS, мы называем его смешанным слоем (Blend Layer), а затем нам нужно добавить базовый слой (Base Layer) для микширования, давайте сначала попробуем.добавление:

// 这里只展示主要代码
void main() {
    vec3 leakColor = drawLeaks(myst, vec2(.0, .0), vec2(.0, .0), 
                        vec2(.0, .0), iResolution,
                        vec3(166./255., 66./255., 65./255.)*1.5, 0., vec2(.3, 0.));
    
    vec3 texelColor = texture2D(texure, myst).rgb;
    
    gl_FragColor = vec4(leakColor + texelColor, 1.);
}

Вроде бы все ок, но если базовый слой будет белым фоном, то будут некоторые проблемы:

Поскольку используется сложение,Добавить цветЭмпирическое правило состоит в том, что смесь цветов в конечном итоге будет приближаться к самому яркому цвету, и когда любой цвет добавляется к почти белой основе, он будет становиться все ярче и ярче, теряя исходный цвет фильтра. Это дополнение не работает одновременно и для темной, и для белой основы. А умножение? Если вы хотите умножить, вы должны сначала изменить слой наложения на белую основу (иначе любой цвет, умноженный на черную основу, будет черным):

void main() {
    vec3 leakColor = drawLeaks(myst, vec2(.0, .0), vec2(.0, .0), 
                        vec2(.0, .0), iResolution,
                        vec3((255.-255.)/255., (255.-95.)/255., (255.-32.)/255.), 0., vec2(.3, 0.));

    gl_FragColor = vec4(leakColor, 1.);
}

Затем используйте умножение (это некрасиво, но все равно цветное):

Давайте посмотрим, как выглядит темный фон:

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

Когда дизайнеры получат Blend Layer и Base Layer, они, не колеблясь, добавят «цветной фильтр«Смешанный режим, почему они делают это, часто стебель от понимания и ежедневной практики этого смешанного режима, как инженер, не может достичь своего шестого смысла, давайте посмотрим на« цветное »определение:

Просмотрите информацию о цвете для каждого канала и умножьте дополнительный цвет совмещенного цвета с основным цветом. Полученный цвет всегда светлее. Цвет остается прежним при фильтрации черным цветом. Фильтрация с помощью белого даст белый цвет. Эффект похож на несколько слайдов фотографий, проецируемых друг на друга.

Реализация цветового фильтра выглядит следующим образом:

float blendScreen(float base, float blend) {
	return 1.0-((1.0-base)*(1.0-blend));
}

Проще говоря, цветной фильтр удаляет более темные цвета в двух слоях и берет более светлые. Давай попробуем:

float blendScreen(float base, float blend) {
	return 1.0-((1.0-base)*(1.0-blend));
}

vec3 blendScreen(vec3 base, vec3 blend) {
	return vec3(blendScreen(base.r,blend.r),blendScreen(base.g,blend.g),blendScreen(base.b,blend.b));
}

void main() {
    vec3 leakColor = drawLeaks(myst, vec2(.0, .0), vec2(.0, .0), 
                        vec2(.0, .0), iResolution,
                        vec3((255.-255.)/255., (255.-95.)/255., (255.-32.)/255.), 0., vec2(.3, 0.));

    vec3 texelColor = texture2D(texture, myst).rgb;
    gl_FragColor = vec4(blendScreen(texelColor, leakColor), 1.);
}

Этот эффект ожидаем. На самом деле, «неоновый» эффект, который мы получаем на Douyin, тоже одинаков: эффект светлой базы менее заметен, а темной — более очевиден. Так что это может быть так же просто, как угадать: этот специальный эффект Douyin также добавляет неоновые эффекты путем фильтрации цветов.

3. Применимые сценарии

Используя вышеупомянутый смешанный режим и очищая, по сути, режим смешивания слоев, мы можем получить ряд прямых эффектов онлайн-фильтра, это простой случай. Однако не во всех случаях подходит режим наложения слоев, например, в поле поворота,mix()Будет более подходящим для смешивания перехода между двумя слоями.

Режим наложения слоев больше подходит для локального эффекта + сплошного цвета фона, которые необходимо применить к конкретному изображению. Например, приведенный выше случай — случай, а другой случай — Light Leak:

Или блик: