для чего нужны шейдеры

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

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

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

Роль уникальных шейдеров в создании спецэффектов для компьютерных игр

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

Что же делать, если перед вами стоит задача создать оригинальный визуальный эффект? Если вам надо сделать игру или какой-то из ее этапов особенно запоминающимся? Здесь не обойтись без создания уникального шейдера. Рассмотрим конкретную ситуацию на примере игры Circle of Life, разработанную студией zGames. В этой игре особый акцент необходимо было придать анимированному объекту – сферической области. Геймплей уже изобиловал достаточным количеством простых эффектов, поэтому этот элемент нужно было выделить с помощью специальных визуальных трансформаций. Так как стандартных инструментов для создания задуманных визуальных эффектов оказалось недостаточно, было решено разработать уникальный шейдер. В итоге, финальный объект реагирует на удерживание пальца на сенсорном экране, увеличиваясь в объеме и меняя структуру. Благодаря уникальным визуальным трансформациям эта сферическая область стала одним из ключевых элементов игры, к которому приковано внимание игрока (ниже показана шейдерная анимация главного объекта игры Circle of Life).

для чего нужны шейдеры

«За» и «против» использования шейдеров в играх

для чего нужны шейдеры

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

для чего нужны шейдеры

Рассмотрим еще один пример. Допустим, вы создаете игру, сюжет которой построен вокруг параллельных миров с порталами, точками соприкосновения и прочими космогенными элементами. Вы разработали уникальный шейдер для светящегося кристалла в пещере, который искажает пространство. Из-за визуального акцента на кристалле у игрока может сложиться впечатление, что этот объект важен в основной сюжетной линии или является “пасхалкой” (секрет, который нужно обнаружить), хотя это всего лишь элемент декора в интерьере. В итоге это может просто сбить игрока с толку или даже разочаровать, если ему пришлось потратить время на исследование впустую. В результате нарушается “флоу” (состояние погруженности в игровой процесс). Ниже приведен пример из игры Perimeter. Здесь шейдеры создают слишком много красивостей. Становится непонятно, где сосредоточена важная информация (зоны действия вышек), а где эффект применен просто для визуального разнообразия. Игроку труднее ориентироваться в игровой сцене. Приходиться затрачивать больше времени на понимание ситуации и принятие решений.

для чего нужны шейдеры

Поэтому, взвешивая “за” и “против” разработки шейдера, стоит более тщательно продумать целесообразность и уместность использования этой техники.

Составляем оценку трудозатрат на разработку шейдеров: возможные трудности

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

для чего нужны шейдеры

Во-вторых, оценка должна включать время, требуемое на отладку программы. Ведь сразу создать идеально функционирующий шейдер вряд ли получится. Необходимо помнить, что процесс разработки шейдеров и традиционного ПО отличаются. Системные приложения располагают рядом средств, позволяющих их отладить качественно. Чего не скажешь об инструментах для отладки шейдеров. Для каждого пикселя 3D объекта программа может выполняться по 50 раз за секунду. Остановить такой процесс в определенном месте для проверки корректности работы программы крайне сложно. В настоящее время для отладки шейдеров используется расширение Microsoft Visual Studio со встроенным графическим отладчиком. Еще одна сложность, подстерегающая на пути шейдерной разработки — отсутствие четкого представления как будет выглядеть конечный результат самостоятельно и в игровом процессе. Может возникнуть необходимость в его доработке или даже повторной разработке. Так что и этот момент необходимо учитывать при составлении оценки.

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

Немного о процессе разработки

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

Шейдеры и устройства виртуальной и дополненной реальности

Обладая огромным потенциалом передачи сложных визуальных эффектов, устройства виртуальной и дополненной реальности уже занимают ведущее место в рядах популярных гаджетов для компьютерных игр. Несомненно, шейдеры добавляют реализма объектам игр, разрабатываемых для этих носимых устройств. Но на сегодняшний день не все VR- или AR-шлемы смогут воспроизвести эффекты на основе сложных шейдеров вследствие аппаратных ограничений – недостаточно мощной видеокарты и процессора. Более того, не все VR- и AR-платформы предоставляют полный набор функций, необходимых для программирования нативных шейдеров. Тем не менее, индустрия устройств виртуальной и дополненной реальности продолжает активно развиваться. Появление качественного 3D контента с использованием сложных визуальных эффектов на основе шейдеров дело самого ближайшего будущего.

Подводя итоги

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

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

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

Источник

Шейдеры. Что и как

Расскажу, как в общем случае они работают, что умеют и как их используют

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

Слово «шейдер» в контексте разработки игр очень популярно, слышать его могли и те, кто игры не делает. Само слово изначально появилось от англ. shading (затенение) — первые шейдеры использовались, чтобы передавать глубину с помощью работы со светом, блеском, тенями и прочим. Со временем шейдеры стали использоваться для совершенно разного вида постобработки и вообще отрисовки примерно всего.

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

Теперь разберемся, как это все работает.

В общем случае цель шейдера — отрисовать некоторый объект. Поэтому возьмем куб, распишем процесс его отрисовки и посмотрим, где используются шейдеры и зачем. Сначала опишем сам куб. Для графической карты это 8 точек, между некоторыми из которых есть плоскость. Каждая из точек описывается тремя числами (правильно сказать, что это вершины). Помимо этого у кубика есть цвет и положение внутри мира.

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

1. Получение входных данных из памяти.
2. Выполнение шейдера вершин.
3. Растеризация.
4. Выполнение шейдера пикселей (фрагментов).
5. Проведение тестов «глубины».
6. Отрисовка на текстуру для экрана.

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

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

1. Шейдер вершин.
2. Шейдер фрагментов.

Как сказано было ранее, этот шейдер (или группа шейдеров по очереди) занимается переводом координат относительно объекта, в координаты на текстуре.

На картинке начало координат немного не соответствует реальным, что все так же не влияет на понимание процесса 🙂

Пройдемся по состояниям. В первом у нас, очевидно, входные координаты без излишков. На втором они были перенесены в координаты относительно начала «мира». Потом они переносятся в координаты относительно точки смотрящего (видно на второй картинке), но заметно, что картинка плоская. Их проекция происходит далее и мы получаем наши итоговые координаты. Все эти операции производятся шейдером. Помимо прочего, он позволяет не только отобразить реальные координаты, но и модифицировать их так, чтобы исказить объект для эффекта. Например, я недавно писал шейдер, который переворачивал спрайт, чтобы отрисовать его тень:

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

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

Теперь достаточно в каждом пикселе просто брать цвет из текстуры. Но чтобы это сделать, нужно добавить для каждой точки куба еще информацию: UV канал. Это координат вида (u, v). Отсюда и название, так как x и y были заняты. Она присваивается вершине объекта и обозначает точку на текстуре, которая ей соответствует. Чтобы было понятнее, если мы хотим на каждую грань куба нарисовать знакомое нам лицо, то UV координаты для каждой грани будут выглядеть предельно просто:

Модифицировать их никак не надо. Более того, считать координаты для каждой точки — тоже не нужно. Этим занимается GPU, самостоятельно интерполируя точки из вершин. Тогда достаточно просто сказать для каждой точки что-то вроде

Это очень условный пример, но примерно так в простейшем случае оно и работает:

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

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

Источник

Шейдеры. Или почему мир игр стал визуально так похож на наш!

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

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

Может кто-то уже и догадался по названию поста(глупый вопрос, конечно, там ж написано), речь пойдет о шейдерах. Что это, для чего и почему. Постараюсь разложить все по полочкам. Начнем:)

Что вообще такое эти самые шейдеры. Шейдеры — это программки, которые исполняются на видеокарте и описывают эффекты, методы обработки и прорисовки графики. Изначально GPU преимущественно обрабатывали 2D графику. В это время появляются так называемые акселераторы(ускорители). Они берут на себя часть операций, связанную с обработкой графических данных, сами прорисовывают каждый пиксель и определяю его цвет. Все это использовали видеокарты NVIDIA Riva128 и 3Dfx Voodoo. Эти карты брадли на себя только такие задачи как текстурирование и закраску, все остальное выполнял СPU. Естественно картинка была соответствующей. Подумайте сами, процессор и так загружен другими системными задачами, а тут еще ему и графические данные прорисовывать приходится, которые, по сравнению с арифметическими расчетами, просто звери.

для чего нужны шейдеры Но в те времена этого было достаточно конечному пользователю. Далее начали применяться графические библиотеки такие как Open Gl, Direct 3d. Они снимали с CPU значительную часть нагрузки и брали на себя. Теперь видеокарта строила сцену с нуля. Производителям видеоигр в те времена такое решение было удобно. Все применяемые в тех играх эффекты были уже аппаратно встроены в видеокарты. Их было достаточно для игр того поколения. Но ничего не стоит на месте, разработчики видеоигр стремились вырваться вперед по сравнению с конкурентами и появилась потребность как-то улучшать имеющиеся эффекты 3D графики. Тогда то и появилась проблема — для того, чтоб апгрейдить какой-то эффект, разработчикам видеоигр приходилось подождать годик, чтоб вышла видеокарта, поддерживающая данный эффект. Что было и дорого и длительно по времени. Тогда — то и появились шейдеры. Так началась новая эра развития трехмерной графики в игровой индустрии.

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

для чего нужны шейдерыПиксельные шейдеры или геометрические. В отличие от вершинных, геометрические шейдеры оперируют на уровне примитивов. Проще говоря, они делят изображение на примитивы(точки, отрезки, треугольники) и работают с каждым в отдельности. Сглаживают, освещают, анимируют, добавляют эффекты HDR и Motion Blur. Главное назначение пиксельных шейдеров заключается в комплексном смешивании текстур, просчете освещенности и оптических свойств моделей, постобработке кадра. В общем, почти все, что мы видим в современных играх, — плод трудов пиксельных шейдеров!

для чего нужны шейдеры для чего нужны шейдеры Естественно, как вы навреное уже поняли, шейдеры пишутся игровыми программистами. С развитием трехмерной графики, написание шейдеров усложняется. Раньше они вообще состояли из небольшого куска кода на ассемблероподобном языке, а сейчас же существует несколько шейдерных языков, которые ориентированые на достижение максимального качества визуализации. Ни одна современня игра не обходится без шейдеров, если вы видите потрясную картинку с ослепительным эффектом, то знайте, это все работа шейдеров. Без них мы бы до сих пор играли в игры типо первых Quake, Doom, Unreal. Так же необходимо отметить, что современные игры сочетают в себе много шейдеров одновременно, которые выполняются параллельно вашей видеокартой.

Однако, но хоть шейдеры — это программы, их количество напрямую связано с качеством вашей видеокарты. Их количество настроено изначально на заводе-производителе и самому изменить это параметр невозможно. Хотя, обладателям консолей не стоит этого бояться т.к игры изначально оптимизируют под консоли и она в любом случае пойдет на приемлемом качестве. И как раз из-за шейдеров обладателям ПК приходится сверять системные характеристики и постоянно увеличивать мощность своего компьютера. Так же нужно помнить, что всего хорошего должно быть в меру. Программист, который разрабатывает шейдеры должен четко понимать что, где и как шейдер должен делать. Иначе получится полная ж… иными словами переизбыток шейдеров ничего хорошего не сулит!

для чего нужны шейдеры И под конец хочу сказать, что без шейдеров не было бы ничего из того, что мы сейчас имеем. Шейдеры — это мощное средство для реализации достижений сложной трехмерной графики. Чем сложнее эффекты, тем прокаченней и больше по количеству нужно шейдеров. И… у меня плохо с заключением… и если вы еще до сих пор не поняли что такое шейдеры, то сходите съешьте шоколадку и прочитайте этот пост еще раз:) Спасибо за прочтение!

для чего нужны шейдеры Эй-эй, это между прочим пример сглаживания!)

Источник

Руководство начинающего программиста графических шейдеров

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

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

для чего нужны шейдеры
Сцена в Minecraft до и после применения нескольких шейдеров.

Цель этой инструкции

Что такое шейдер?

Шейдер — это просто программа, которая запускается на одном из графических ядер и говорит видеокарте, как нужно отрисовать каждый пиксель. Программы называются «шейдерами», поскольку они часто используются для контроля эффектов освещения и затенения («shading»). Но, конечно, нет никаких причин ограничиваться только этими эффектами.

Шейдеры пишутся на специальном языке программирования. Не беспокойтесь, вам не нужно прямо сейчас идти и изучать с нуля новый язык программирования. Мы будем использовать GLSL (OpenGL Shading Language), который имеет С-подобный синтаксис. Существуют и другие языки программирования шейдеров под различные платформы, но, поскольку их конечной целью является всё тот же запуск кода на GPU, они имеют достаточно схожие принципы.

Данная статья будет рассказывать лишь о так называемых пиксельных (или фрагментных) шейдерах. Если вам стало интересно, а какие они бывают ещё — вам следует почитать о графическом конвейере (например, в OpenGL Wiki).

Поехали!

Для наших экспериментов мы воспользуемся ShaderToy. Это позволит вам взять и начать писать шейдерный код здесь и сейчас, не откладывая это дело на потом из-за необходимости устанавливать какие-то определённые инструменты или SDK. Единственное, что вам необходимо — это браузер с поддержкой WebGL. Создавать аккаунт на ShaderToy не обязательно (только, если вы захотите сохранить там свой код).

Заметка: ShaderToy сейчас в стадии беты, так что на момент прочтения вами этой статьи некоторые нюансы его UI могут измениться.

Итак, нажимаем кнопку New в правом углу, что приведёт к созданию нового шейдера:

для чего нужны шейдеры

Маленькая чёрная стрелка под кодом компилирует и запускает шейдер.

Что здесь происходит?

Я сейчас объясню, как работает шейдер, ровно одним предложением. Вы готовы? Вот оно. Единственным предназначением шейдера является вернуть четыре числа: r, g, b и a.
Это всё, что может и должен сделать шейдер.

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

Итак, теперь у нас есть достаточно знаний для того, чтобы, например, залить весь экран чистым красным цветом. Значения каждой из компонент rgba (red, green, blue и «alpha» — то есть «прозрачность») может быть в диапазоне от 0 до 1, так что в нашем случае мы просто вернем r,g,b,a = 1,0,0,1. ShaderToy ожидает финальный цвет пикселя в переменной fragColor.

Мои поздравления! Это ваш первый работающий шейдер!
Мини-задание: сможете залить весь экран серым цветом?

vec4 — это просто тип данных, так что мы можем объявить наш цвет как переменную:

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

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

Входные параметры шейдера

Каждый пиксельный шейдер имеет в своём распоряжении несколько полезных переменных. В нашем случае наиболее полезной будет fragCoord, которая содержит координаты x и y (а также z, если нужно будет работать в 3D) текущего пикселя. Для начала попробуем закрасить все пиксели в левой половине экрана в черный цвет, а в правой — в красный:

Заметка: для доступа к компонентам переменных типа vec4 вы можете использовать obj.x, obj.y, obj.z, obj.w или obj.r, obj.g, obj.b, obj.a. Это эквивалентные записи. Таким способом мы получаем возможность именовать компоненты vec4 в зависимости от того, чем они являются в каждом конкретном случае.

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

Если что-то не является встроенной переменной, вы можете переслать эту информацию от CPU (основного кода вашего приложения) к GPU (вашему шейдеру). ShaderToy делает это за вас. Вы можете просмотреть все доступные шейдеру переменные во вкладке Shader Inputs. В GLSL они называются uniform-переменными.

для чего нужны шейдеры

Давайте исправим наш код таким образом, чтобы он корректно определял середину экрана. Для этого нам понадобится uniform-переменная iResolution:

Теперь даже при увеличении окна предпросмотра (или переходе в полноэкранный режим) мы получим поделенный ровно пополам черно-красный прямоугольник.

От разделения экрана к градиенту

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

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

Если вы не пропустили вышеуказанное задание с вертикальным градиентом, то уже знаете, что верхний левый угол имеет координаты (0;1), а не (0;0), как можно было бы предположить. Это важно, запомните это.

Рисование изображений

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

Если бы мы писали шейдеры на какой-нибудь обычной платформе, то должны были бы передать изображение шейдеру как uniform-переменную (таким же образом, как передавалось разрешение экрана). ShaderToy делает это за нас. Есть четыре входных канала внизу:

для чего нужны шейдеры

Кликните на канале iChannel0 и выберите любую текстуру (изображение). Теперь у вас есть картинка, которая будет передана вашему шейдеру. Но есть одна проблема: функции DrawImage() у нас нет. Вы ведь помните — всё, что может сделать шейдер, это вернуть значение rgba для одного пикселя.

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

для чего нужны шейдеры

Мы можем сделать это с помощью функции texture(textureData,coordinates), которая принимает на вход текстуру и координаты (x, y), а возвращает цвет текстуры в данной точке в виде переменной типа vec4.

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

И вот она, наша картинка!

для чего нужны шейдеры

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

для чего нужны шейдеры

Поздравляю, вы только что написали свой первый пост-процессинг эффект!

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

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

Добавляем немного движения

До этого момента все наши эффекты были статические. Мы можем делать намного более интересные вещи, используя входные параметры, предоставляемые нам разработчиками ShaderToy. iGlobalTime это постоянно увеличивающаяся переменная — мы можем использовать её в качестве основы для переодических эффектов. Давайте попробуем поиграть с цветами:

В GLSL есть встроенные функции синуса и косинуса (да и много других полезных). Компоненты цвета не должны быть негативными, так что мы используем функцию abs.

Мини-задание: можете ли вы сделать шейдер, который будет периодически плавно делаеть картинку черно-белой, а потом снова полноцветной?

Отладка шейдеров

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

Заключение

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

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

Последнее мини-задание: сможете ли вы написать шейдер, который заменит зелёный фон (есть в некоторых видео на ShaderToy) на другую картинку или видео?

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

Источник


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *