Как написать Шейдер LCD дисплея?📺

Вот это будем делать

Однажды, гуляя по миру «Organism» VR Chat, заметил экран в дальней части одной из комнат. Я не придал этому значения, пока не подошел ближе.

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

Вдохновившись увиденным, тем же вечером сел за решение этой задачи, результатом которой поделюсь в этой статье.

Также в ней вы научитесь таким трюкам как:

  • Степинг/Пикселизация
  • Маскинг
  • Мультимапинг

Версия в статье будет содержать реализацию в ShaderGraph, но она так же свободно интерпретируется в любой среде.

Что понадобится

🖼 Опыт написания шейдеров

🔣 Базовые знания математики

🍌 Хакерская музыка на фоне

Как реализовать?

Начнем с разбора работы самого дисплея.

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

<a href="https://www.youtube.com/watch?v=6n29TXWj1fw" rel="nofollow noreferrer noopener" target="_blank">https://www.youtube.com/watch?v=6n29TXWj1fw</a> подробнее об устройстве матрицы
https://www.youtube.com/watch?v=6n29TXWj1fw подробнее об устройстве матрицы

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

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

Сильно упрощая, пиксель состоит из 3 субпикселей RGB(Красный, Зеленый, Синий), смешивание которых в различных пропорциях приводит к получению новых цветов.

Как написать Шейдер LCD дисплея?📺

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

Какую информацию удалось из этого извлечь?

  • Изображение разбивается на пиксели
  • Каждый пиксель нужно изобразить в виде 3 субпикселей

Как собрать?

Для пикселизации изображения применяется одноименная техника, также известная как степинг.

Рассмотрим пример с градиентом, где приведены значения от 0 до 100ед. Наименьшая разница в значении соседствующих цветов составляет 0,01ед., взяв случайную точку градиента, получаем значение с точностью до второго знака после запятой. Пусть мы не можем визуально определить границу каждого из цветов, но она есть, и составляет 0,01ед.

Как написать Шейдер LCD дисплея?📺

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

Как написать Шейдер LCD дисплея?📺

Наконец, попробуем составить градиент всего из 4 полос, 25ед. которого будут представлять 1 шаг. Теперь разница видна невооруженным взглядом и нам удалось успешно «пикселизировать» градиент.

Как написать Шейдер LCD дисплея?📺

Как нам добиться того же результата для обработки изображения?

Для этого мы преобразуем оригинальный UV объекта воспользовавшись тем же степпингом, однако, его координаты ограничены значениями от 0.0 до 1.0 и для семплирования нам так же необходима UV в этих границах.

Начнем с преобразования координат умножив их значения, например на 5.

Graphing
Graphing
ShaderGraph
ShaderGraph

Теперь, округлим получившиеся значения воспользовавшись floor().

Graphing
Graphing
ShaderGraph
ShaderGraph

Остается поделить получившиеся значения на то же, которое мы использовали для умножения, в нашем случае это 5.

Graphing
Graphing
ShaderGraph
ShaderGraph

Теперь мы можем в пикселизацию(🎉). Самое время переходить к пикселю.

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

Как написать Шейдер LCD дисплея?📺

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

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

Как написать Шейдер LCD дисплея?📺

В эстетических целях можем приблизить вид пикселя к более реалистичному.

Как написать Шейдер LCD дисплея?📺

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

ShaderGraph
ShaderGraph

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

ShaderGraph
ShaderGraph

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

Умножим UV(в нашем случае на 5), и из получившихся значений оставим только дробную часть при помощи fract().

ShaderGraph
ShaderGraph

Теперь разделим пикселизированое изображение на RGB каналы и умножим их на соответствующие каналы маски.

ShaderGraph
ShaderGraph

И наконец, объединив получившиеся значения в vec3(), достигаем желаемой цели 🍾

ShaderGraph
ShaderGraph
Как написать Шейдер LCD дисплея?📺

Благодарю за прочтение и, разумеется,

Ссылка на Git содержит UnityPacage с собранным в ShaderGraph шейдером из статьи.

Если у вас есть желание поддержать автора статьи, то вы можете:

-Бахнуть по кнопке лайк, чтобы она взорвалась ❤

-Поделиться этой статьёй с людьми, которым интересна тема компьютерной графики.

-Подписаться на мои проекты:

https://vk.com/shakoretka - вк паблик в котором я делюсь своими знаниями, творчеством и вещами которые нахожу интересными(в основном это игры и геймдев)

https://www.twitch.tv/shakoretka - твич канал на котором я периодически провожу трансляции игр и разработки, а также активно общаюсь с гостями в чате <3

https://dtf.ru/u/294992-shakoretka - блог на DTF в котором я публикую статьи

-Оставить фидбек под статьёй и пожелания о топиках, которые были бы вам интересны.

-Типнуть на кофеёк можно по ссылке на DonationAlerts

Также после последней статьи мне написало множество человек (чему я безмерно рад ❤ спасибо вам), одним из которых стала HR, которая находится в поиске специалиста на должность Технического Художника. Можете ознакомиться с ее предложением в комментариях и если оно вас заинтересует, связаться с ней🤝

7070
48 комментариев

Ого, на этой помойке щитпостов кто-то всё ещё пишет статьи про геймдев и в частности шейдеры. Респект.

17
Ответить

Муар слишком наркоманский. Вот мой вариант:
https://youtu.be/V_3sPfabvzQ

5
Ответить

Выглядит потрясающе 🔥

Ответить

для типа мало, но продолжай. Интересно про шейдеры. Только юзать бы что повеселее, анрил например)

2
Ответить

Будь у меня больше свободного времени, с удовольствием показал бы реализацию в разных средах 🥹Поэтому использую то, чем владею свободнее всего, благо решение универсальное и легко воссоздается на UE. Благодарю за интерес ❤️

1
Ответить

Когда начнет миповатся текстура с RGB пикселями всё превратится в говно) Это уже заметно когда на видео камера далеко от экрана отдаляется

2
Ответить