Глитч-эффекты своими руками

Очень простыми средствами добавляем в игру немного сумасшествия

Глитч-эффекты своими руками

Всем привет! Для моей новой игры мне понадобилось сделать визуальные эффекты, искажающие изображение в стиле "глитч-арта". Глитч-арт использует идею ошибочной интерпретации данных, за счёт которого изображение сильно и пугающе искажается. Вы наверняка видели много примеров этих эффектов в сети.

Пример чужого творчества<br />
Пример чужого творчества

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

Эффекты чрезвычайно простые, поэтому буду брать вас количеством, а не качеством. Я буду использовать шейдеры для Unity, но вся описанная ниже информация актуальна для любых движков, использующих шейдеры, а так же для ПО, имеющим прямой доступ к данным изображения.

Немного теории

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

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

Глитч-эффекты своими руками

Как видно, изображение сдвинулось влево, потому что изображение читается построчно, слева направо. Возьмём 2 строки в 4 пикселя. Каждый пиксель у нас будет характеризоваться тремя цветовыми компонентами: красным (R), зелёным (G) и синим (B). Вырежем из первой строки 4 байта посередине и мы получим такое преобразование:

Изображение сдвинулось, в том числе пиксели из второй строки переместились на первую. В конце появился шум из неизвестных данных. <br />
Изображение сдвинулось, в том числе пиксели из второй строки переместились на первую. В конце появился шум из неизвестных данных.

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

Но так это работает только с несжатыми данными изображений. Если мы возьмём какой-нибудь другой формат, который сжимает информацию, особенно проприетарный, то никто не знает, как поведёт себя алгоритм.

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

Ну а теперь, когда мы разобрались в теории, пора приступать к конкретике

Настроим среду для отображения эффектов

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

Создаём в Unity новый файл типа Shader/Image Effect Shader. Если у вас нет такой функции, то можете взять исходник отсюда.

Создаём в Unity новый скрипт, назовём его CameraEffect. Исходный код для скрипта можно взять отсюда.

Создадим новый материал. Укажем для него новосозданный шейдер. Поменяем цвет например на жёлтый.

На камере создаём новый компонент типа CameraEffect. Указываем новосозданный материал в качестве параметра поля Material.

Если всё получилось правильно, то должно получиться что-то подобное (мы взяли изображение с камеры и наложили на него жёлтый оттенок):

Глитч-эффекты своими руками

Теперь, добавим в наш шейдер несколько новых опций (помним, что опции нужно объявлять дважды: в разделе Properties и в теле самого шейдера между CGPROGRAM и ENDCG):

Этими опциями мы будем пользоваться позже<br />
Этими опциями мы будем пользоваться позже

Эффект сдвига

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

Глитч-эффекты своими руками

Загрузим пустую чёрную текстуру, посмотрим на изображение - оно не изменилось. Потому что чёрный цвет - 0 по всем каналам, значит и искажений нет.

Глитч-эффекты своими руками

Тогда попробуем подставить простую текстуру, например одну красную полосу (не забываем для всех текстур, импортируемых в Unity в качестве эффекта, отключать сжатие и использовать Point Filter Mode, чтобы искажающая текстура не искажалась сама).

Ой, слишком сильный сдвиг. Давайте будем редактировать степень сдвига с помощью переменной _Force.

Глитч-эффекты своими руками

Сделаем эффект волны с помощью красного градиента (в том числе и с помощью ступенчатого):

Попробуем добавить несколько полос разной ширины и контрастности:

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

Глитч-эффекты своими руками

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

Глитч-эффекты своими руками

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

Сдвиг всего изображения

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

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

Глитч-эффекты своими руками

И результат:

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

Цветовой сдвиг

Обычного сдвига мало, он слишком непримечательный. Чаще всего вместе обычным сдвигом изображения добавляют цветовой. Попробуем добавить его и мы. Я воспользуюсь классическим подходом смены цветовых компонент, но это можно делать любым способом. Здесь я меняю красный канал на зелёный, зелёный на синий, а синий на красный.

Глитч-эффекты своими руками

Взглянем теперь на сцену, но с применением цветового сдвига (я сделал сцену немного ярче, потому что она была преимущественно серая, а серый при сдвиге снова даёт серый):

Глитч-эффекты своими руками

Генерируем полосы

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

  • Случайно находим начальную координату региона по оси Y.
  • Случайно находим конечную координату региона по оси Y так, чтобы она не сильно отклонялась от начальной координаты
  • Сдвигаем все пиксели между начальной и конечной координатой влево на случайную величину, одинаковую для всего региона
  • В случайном порядке меняем R на G, G на B или R на B
  • Повторяем в зависимости от необходимого количества искажений

Поскольку шейдер не умеет выдавать случайные величины, можно использовать текстуру с шумом или же генерировать псевдослучайные величины с помощью функций sin и cos с передачей времени в качестве аргумента.

Надеюсь, кому-нибудь понятно, что я тут написал
Надеюсь, кому-нибудь понятно, что я тут написал

Частичный цветовой сдвиг

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

Глитч-эффекты своими руками

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

Глитч-эффекты своими руками
Глитч-эффекты своими руками

Добавляем шума

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

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

Глитч-эффекты своими руками

Как и в прошлом случае, в качестве текстуры искажений используем обычные полосы. Результат:

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

На DTF я так же веду блог о разработке игр, в который попадает всё, что не заслуживает отдельной статьи. Например, там же я опубликовал статью о том, как я не очень удачно пытался сделать ещё один глитч-эффект под названием datamosh. Подписывайтесь, если вам интересен подобный контент.

4545