Как написать шейдеры для майнкрафт

Доброго времени суток, уважаемые о/

Данная серия туториалов будет посвящена созданию собственных шейдеров на основе языка openGL Shading Language, или GLSL.

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

Язык GLSL чем-то похож на Java, чем-то — на Си, так что с синтаксисом проблем возникнуть не должно.
Первая часть будет посвящена Фрагментным Шейдерам. Что это такое объясню ниже.

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

Сложно, тёмно и не особо понятно, да? Давайте попробуем упростить вышесказанное и всё таки дать ответ на главный вопрос «что же делают фрагментные шейдеры? «. Готовы?
В двух словах: определяют цвет
Всё. Это действительно всё, что может сделать этот тип шейдера — определить и вернуть цвет одного-единственного полученного пикселя. Но не спешите закрывать урок. Даже с этим, казалось бы, небольшим функционалом можно делать просто умопомрачительные эффекты. Как? Читайте дальше.

На входе фрагментный шейдер действительно получает лишь один пиксель, точнее, его координаты, x и y. А на выходе выдаёт цвет в формате RGBA (красный, зелёный, синий и прозрачность).

Итак, рассмотрим примерный вид программы, которые у вас всех будут в итоге получаться:

#version N

uniform type globalVar1;

void main() {
    // Координата текущего пикселя
    vec2 pixelCoord = gl_FragCoord.xy;
    // Цвет текущего пикселя
    vec4 pixelColor = vec4(0.0);

    /**
     * Любые вычисления и изменение цвета выходного пикселя
     *
     */

    // Присвоение выходного результата
    gl_FragColor = pixelColor;
}

Типы переменных:
В GLSL есть практически все стандартные примитивные типы:

bool

(не

boolean

!), int, uint (unsigned int, т.е. неотрицательное число), float и double.

В добавок к ним есть контейнеры — векторы: vec2, vec3, vec4 (на 2, 3 и 4 значения соответственно) и матрицы: mat2, mat3, mat4 (2×2, 3×3 и 4×4 соответственно). Стандартый тип переменных в них — float. Если нужен, например, вектор int’ов на три компонента, вначале нужно дописать iivec3 (соответственно b — bool, u — uint, d — double).

Грубо говоря, это одно- и двумерные массивы, и доступ к их элементам можно получить через стандартный оператор индексирования — []. Но для нашего удобства был разработан метод swizzling, позволяющий получить доступ к элементам по их идентификаторам (xyzw, rgba или stpq, использующиеся для координат, цветов и точек текстуры соответственно (но не обязательно так)), допустим:

// инициализация:
vec4 v = vec4(0.0); // все компоненты равны, т.е. 0.0, 0.0, 0.0, 0.0
vec2 vect = vec2(0.5, 0.7); // два компонента: 0.5 и 0.7
vec4 result = vec4(vect, 0.0, 0.0); // четыре: 0.5, 0.7 (из первого вектора), 0.0, 0.0
vec4 otherResult = vec4(result.xyz, 1.0); // 0.5, 0.7, 0.0, 1.0

// доступ и операции:
vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.abr;
vec4 otherVec = someVec.xyyx + anotherVec.sttp;

Модификатор uniform — это переменные, передаваемые в шейдер извне (из программы, в которой использовался шейдер). Самый распространённый uniform — time, то есть время. Он используется для анимации, ведь мало кому интересно смотреть на статичные шейдеры, которые проще нарисовать текстурой в фотошопе, чем учить новый язык.

Модификаторы in и out — это входные и выходные данные. Например, переменная gl_FragColor из кода выше как раз таки является переменной с модификатором out, встроенной в GLSL, её тип — vec4. Она используется для извлечения цвета пикселя из шейдера.

«Аннотация» #version указывает версию GLSL, которую вы хотите использовать. Она всегда должна находится на самом верху. Вот небольшая справка соответствия версий OpenGL и GLSL:

(записывать без точки)
2.0 — 1.10
2.1 — 1.20
3.0 — 1.30
3.1 — 1.40
3.2 — 1.50

Начиная с OpenGL 3.3 версии GLSL соответствуют версиям OpenGL, так что, допустим, GL 44 использует GLSL 440
*Источник*

Функции:
В GLSL есть множество встроенных функций, очень похожих на их аналоги из библиотеки Math:
sin(a), cos(a), tan(a); min(a, b), max(a, b) — синус, косинус, тангенс углов; минимальное и максимальное значения.
normalize(a) — возвращает нормализованный (с длинной равной 1) вектор a
length
(a) — возвращает длину вектора a
distance
(a, b) — расстояние между двумя точками (векторами a и b)
И так далее. Полный список можно найти вот тут — *тык* (для OpenGL 4)

Практика:
С теорией покончили, настало время попрактиковаться!
Для этого есть множество удобных и не очень программ и сайтов, лично я при обучении использовал Shader Edit for Android — бесплатная программа из Play Market’а (

нет, это не реклама и мне за неё не платили

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

Итак, давайте для начала покрасим весь экран в один цвет, скажем, зелёный.
Для этого нам понадобится всего одна строка в нашей main функции:
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); — мы создаём вектор на 4 компонента, отвечающий за цвет текущего пикселя (RGBA), присваивая зелёному цвету значение 1.0 (это максимально допустимое значение. Если вам сложно рассчитать нужное число, используйте конструкцию «n/255» чтобы превратить числа из диапазона 0-255 в 0.0-1.0), а так же устанавливая насыщенность цвета на максимум:

8abceEqBV8g.jpg

Теперь давайте превратим сплошной цвет в градиент. Для этого «нормализуем» координаты нашего пикселя по размеру экрана, то есть поделим его координаты на размер окна:
vec2 xy = gl_FragCoord.xy / resolution.xy;
И используем координату y для выбора цвета:
gl_FragColor = vec4(0.0, xy.y, 0.0, 1.0);

jF1uZA1XTRU.jpg

Сможете перевернуть градиент, чтобы чёрный был сверху? А справа? А слева внизу?

rH9eF_1PeJw.jpg

Теперь давайте попробуем вставить изображение. В ShaderToy для этого используются каналы ниже; в Shader Edit нужно нажать на три точки справа вверху и в меню «Add uniform/texture» выбрать и добавить нужный sampler2D, нажав на +, например:
uniform sampler2D img;
Далее, используя функцию texture[2D] мы получаем цвет в нужной нам точке текстуры и возвращаем его программе:
gl_FragColor = texture2D(img, gl_FragCoord.xy)

smxoy1mf_cY.jpg

Вы можете заметить, что экран окрасился в один цвет, совсем не похожий на вашу картинку.
Что же делать? Попробуйте нормализовать координаты (поделить на разрешение экрана):
gl_FragColor = texture2D(img, gl_FragCoord.xy/resolution)

rvQcEtJuhvk.jpg

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

vec2 xy = gl_FragCoord / resolution;
vec4 col = texture(img, xy);
col.b = distance(vec2(0.5), xy);
gl_FragColor = col;

wJcXulwExIw.jpg

Теперь фотографируем всё подряд и пропускаем через этот шейдер :D

Попробуйте сделать чёрно-белый фильтр. А сепию? Осветление/затемнение?

vgBp_SthqPk.jpg

Ну вот и всё.
Для закрепления материала попробуйте создать радугу, имитацию водной поверхности (с волнами) или телевизионные помехи. Не забывайте использовать встроенные в Shader Edit и ShaderToy uniform’ы.

Послесловие:
Вершинный шейдер выполняется ДЛЯ КАЖДОГО пикселя на экране, а таких пикселей может быть миллионы и миллиарды, так что вот пара советов по оптимизации:
— Чем меньше условных операторов, тем лучше
— Старайтесь экономить память, т.е. не создавать переменных, без которых можно обойтись

Следующая часть: Шейдеры GLSL [ч.2 — Добавление в игру]
Всего хорошего!

Доброго времени суток, уважаемые о/

Данная серия туториалов будет посвящена созданию собственных шейдеров на основе языка openGL Shading Language, или GLSL.

Язык GLSL чем-то похож на Java, чем-то — на Си, так что с синтаксисом проблем возникнуть не должно.
Первая часть будет посвящена Фрагментным Шейдерам. Что это такое объясню ниже.

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

Сложно, тёмно и не особо понятно, да? Давайте попробуем упростить вышесказанное и всё таки дать ответ на главный вопрос «что же делают фрагментные шейдеры? «. Готовы?
В двух словах: определяют цвет
Всё. Это действительно всё, что может сделать этот тип шейдера — определить и вернуть цвет одного-единственного полученного пикселя. Но не спешите закрывать урок. Даже с этим, казалось бы, небольшим функционалом можно делать просто умопомрачительные эффекты. Как? Читайте дальше.

На входе фрагментный шейдер действительно получает лишь один пиксель, точнее, его координаты, x и y. А на выходе выдаёт цвет в формате RGBA (красный, зелёный, синий и прозрачность).

Итак, рассмотрим примерный вид программы, которые у вас всех будут в итоге получаться:

Типы переменных:
В GLSL есть практически все стандартные примитивные типы: bool (не boolean!), int, uint (unsigned int, т.е. неотрицательное число), float и double.

В добавок к ним есть контейнеры — векторы: vec2, vec3, vec4 (на 2, 3 и 4 значения соответственно) и матрицы: mat2, mat3, mat4 (2×2, 3×3 и 4×4 соответственно). Стандартый тип переменных в них — float. Если нужен, например, вектор int’ов на три компонента, вначале нужно дописать i — ivec3 (соответственно b — bool, u — uint, d — double).

Грубо говоря, это одно- и двумерные массивы, и доступ к их элементам можно получить через стандартный оператор индексирования — []. Но для нашего удобства был разработан метод swizzling, позволяющий получить доступ к элементам по их идентификаторам (xyzw, rgba или stpq, использующиеся для координат, цветов и точек текстуры соответственно (но не обязательно так)), допустим:

Модификатор uniform — это переменные, передаваемые в шейдер извне (из программы, в которой использовался шейдер). Самый распространённый uniform — time, то есть время. Он используется для анимации, ведь мало кому интересно смотреть на статичные шейдеры, которые проще нарисовать текстурой в фотошопе, чем учить новый язык.

Модификаторы in и out — это входные и выходные данные. Например, переменная gl_FragColor из кода выше как раз таки является переменной с модификатором out, встроенной в GLSL, её тип — vec4. Она используется для извлечения цвета пикселя из шейдера.

«Аннотация» #version указывает версию GLSL, которую вы хотите использовать. Она всегда должна находится на самом верху. Вот небольшая справка соответствия версий OpenGL и GLSL:

Функции:
В GLSL есть множество встроенных функций, очень похожих на их аналоги из библиотеки Math:
sin(a), cos(a), tan(a); min(a, b), max(a, b) — синус, косинус, тангенс углов; минимальное и максимальное значения.
normalize(a) — возвращает нормализованный (с длинной равной 1) вектор a
length(a) — возвращает длину вектора a
distance(a, b) — расстояние между двумя точками (векторами a и b)
И так далее. Полный список можно найти вот тут — *тык* (для OpenGL 4)

Практика:
С теорией покончили, настало время попрактиковаться!
Для этого есть множество удобных и не очень программ и сайтов, лично я при обучении использовал Shader Edit for Android — бесплатная программа из Play Market’а (нет, это не реклама и мне за неё не платили). Для компьютеров можно использовать ShaderToy, но убедитесь, что ваш браузер поддерживает WebGL, иначе ничего не выйдет.

Итак, давайте для начала покрасим весь экран в один цвет, скажем, зелёный.
Для этого нам понадобится всего одна строка в нашей main функции:
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); — мы создаём вектор на 4 компонента, отвечающий за цвет текущего пикселя (RGBA), присваивая зелёному цвету значение 1.0 (это максимально допустимое значение. Если вам сложно рассчитать нужное число, используйте конструкцию «n/255» чтобы превратить числа из диапазона 0-255 в 0.0-1.0), а так же устанавливая насыщенность цвета на максимум:

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

Шейдеры Molly станут настоящей находкой для любителей сюжетных приключений в Майнкрафте. С ними игра будет похожа на классические RPG. Основной упор сделан на красивое освещение подземелий и интерьеров зданий. Также…

Шейдеры Ebin выглядят действительно впечатляюще и при этом не слишком нагружают компьютер. Их главной особенностью являются очень качественные лучи, которые выглядят довольно реалистично, причём не ослепляют игрока. Кроме того, шейдеры…

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

Шейдеры Docteur Dread’s добавляет множество эффектов, но при этом большинство являются ненавязчивым и не сильно отвлекают от игры. С ним Майнкрафте появится реалистичная вода, качественные тени и отражения. Кроме того,…

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

Главной целью шейдеров Robobo1221’s Realistic является достижение максимального реализма без лишних эффектов. С ним поверхности в Майнкрафте будут естественно отражать свет, кроме того, в игре появятся качественные динамические тени. Вода…

Создатели шейдеров Conquest of the Sun использовали в качестве основы пак Chocapic Shaders. Они сделали его более мрачным, убрали слишком яркие блики, а также добавили эффекты тумана. Это было проделано…

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

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

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

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

При этом они не привязаны к версиям игры. Если ты начинал играть с ранних модификаций, таких как 1.5, 1.6 или 1.7, и нашел для себя идеальный шейдер, ты можешь перейти на новую и продолжить его использовать. В актуальных версиях Minecraft, таких как 1.10, 1.11, 1.12 и даже в 1.13 они будут отображаться точно так же.

Всем привет, с вами Drovosek !

Сегодня я решил выложить свою МЕГА огромную сборку шейдеров, в которую входит 327 самых разных шейдеров ! Делал я её около 3 дней: качал шейдеры с официальных сайтов, вытаскивал из других разных сборок и т.д. и получилась вот такая вот не хилая сборочка.

В сборке есть самые разнообразные шейдеры, начиная от самых легендарных Sonic Ether’s Unbelievable Shaders и заканчивая мало кому известными Stazza85 super Shaders, в общем дофига.

В сборке много шейдеров, есть те, которые идут и на слабые компы, а есть и те которые требуют мощное железо. Есть даже наркоманские шейдеры =))

Сборку делал я сам своей собственной мышкой и собственным интернетом =D

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

500 ШЕЙДЕРОВ для Майнкрафт — сборка шейдеров от Drovosek

327 ШЕЙДЕРОВ для Майнкрафт — сборка шейдеров от Drovosek

Я не стал заливать скриншоты абсолютно всех шейдеров, только основных, но думаю этих эпичных картинок будет достаточно, чтобы влюбиться в шейдеры =).
* Все скриншоты взяты с официальных тем данных шейдеров на официальном minecraftforum’е.

Бесплатно скачать последнюю версию Minecraft можно по ссылке:

Создание нового шейдера воды

САМЫЕ ЛЁГКИЕ И МОЩНЫЕ ШЕЙДЕРЫ В МАЙНКРАФТ!

Майнкрафт Программы которые тебе нужны — Майнкрафт Открытия

КАК СКАЧАТЬ и УСТАНОВИТЬ ШЕЙДЕРЫ в МАЙНКРАФТ? — ОТВЕТ ЕСТЬ!

КАК УСТАНОВИТЬ ШЕЙДЕРЫ В MINECRAFT! Самый легкий способ!

Урок 1. Как сделать шейдеры в майнкравт

Урок 2. Способы сделать шейдеры

Урок 3.Видео

Урок 4.

Урок 5.

Урок 6.

Урок 7.

Урок 8.

Урок 9.

Урок 10.

Урок 11.

Урок 12.

Урок 13.

Урок 14.

Урок 15.

Урок 16.

Урок 17.

Урок 18.

Урок 19.

Урок 20.

По теме:

  • Как сделать ветряк в minecraft
  • Как находить алмазы в minecraft
  • Как сменить префикс в minecraft
  • Как сделать кровать в minecraft
  • Как сделать животных в minecraft

Пожалуйста, поддержите наш проект — нажмите лайк!

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

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

Сцена из Minecraft: до (сверху) и после (внизу) применения шейдеров.

Цели данного урока

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

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

Итак, что же такое вообще шейдер?

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

Шейдеры пишутся на особом языке программирования. Однако не стоит волноваться. Вам не придется учить с нуля совершенно новый язык, поскольку для написания шейдеров мы будем использовать GLSL, синтаксис которого очень похож на другие C-подобные языки. (На самом деле, существует достаточно большое количество языков для написания шейдеров, однако, ввиду того, что все они предназначены для выполнения на GPU, они все практически одинаковые)

Итак, приступим!

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

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

Нажав на New Shader, вы должны увидеть вот такое окно:

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

Небольшая черная стрелка внизу редактора скомпилирует ваш код.

Итак, что же здесь происходит?

Сейчас я объясню одним предложением, как работают шейдеры. Готовы? Поехали!

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

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

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

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    fragColor = vec4(1.0,0.0,0.0,1.0);
4
}

Поздравляю! Вот вы и написали свой первый работающий шейдер!

Задача: Сможете ли вы изменить цвет на серый?

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

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    vec4 solidRed = vec4(1.0,0.0,0.0,1.0);
4
    fragColor = solidRed;
5
}

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

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

Входные данные шейдера.

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

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel

4
    vec4 solidRed = vec4(0,0.0,0.0,1.0);//This is actually black right now

5
    if(xy.x > 300.0){//Arbitrary number, we don't know how big our screen is!

6
        solidRed.r = 1.0;//Set its red component to 1.0

7
    }
8
    fragColor = solidRed;
9
}

Прим.: К компонентам любой переменной типа vec4 можно обращаться с помощью obj.x, obj.yobj.z иobj.w, либо obj.robj.g,obj.bobj.a. Эти наборы компонентов ничем не отличаются — это просто разные способы представления одних и тех же данных для улучшения читабельности кода (например, если вы используете переменную vec4 obj для обозначения цветов, другие люди, увидев в коде обозначение obj.r, сразу это поймут).

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

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

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

Давайте улучшим наш код так, чтобы он корректно распознавал, где находится центр экрана. Нам потребуется использовать переменную iResolution из вкладки Shader Inputs:

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel

4
    xy.x = xy.x / iResolution.x; //We divide the coordinates by the screen size

5
    xy.y = xy.y / iResolution.y;
6
    // Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel

7
    vec4 solidRed = vec4(0,0.0,0.0,1.0); //This is actually black right now

8
    if(xy.x > 0.5){
9
        solidRed.r = 1.0; //Set its red component to 1.0

10
    }
11
    fragColor = solidRed;
12
}

Если перейти в полноэкранный режим в этот раз, то теперь экран будет разделен цветами ровно пополам.

Переходим к градиенту.

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

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel

4
    xy.x = xy.x / iResolution.x; //We divide the coordinates by the screen size

5
    xy.y = xy.y / iResolution.y;
6
    // Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel

7
    vec4 solidRed = vec4(0,0.0,0.0,1.0); //This is actually black right now

8
     solidRed.r = xy.x; //Set its red component to the normalized x value

9
    fragColor = solidRed;
10
}

Вуаля!

Задача: сможете ли вы сделать вертикальный градиент вместо горизонтального? А как насчет диагонального? А как насчет градиента из нескольких цветов?

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

Рисуем картинки

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

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

Каналы для входящих данных ShaderToy.

Нажмите на iChannel0 и выберите любую текстуру или изображение, которое вам нравится.

Теперь информация об этом изображении передается вашему шейдеру. Однако, есть одна проблема — у шейдера нет встроенной функции DrawImage(). Вспомним, что единственное, что может делать шейдер — это менять цвет каждого пикселя по отдельности.

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

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

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

Соотносить координаты текстуры с экранными координатами можно любым удобным способом. Можно нарисовать всю текстуру лишь на четверти экрана (пропуская пиксели — то есть уменьшить ее масштаб) или нарисовать лишь часть текстуры.

Сейчас нам важно просто увидеть изображение на экране, поэтому будем соотносить все пиксели один к одному:

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    vec2 xy = fragCoord.xy / iResolution.xy;//Condensing this into one line

4
    xy.y = 1.0 - xy.y;
5
    vec4 texColor = texture2D(iChannel0,xy);//Get the pixel at xy from iChannel0

6
    fragColor = texColor;//Set the screen pixel to that color

7
}

Итак, вот и наш первый шейдер с изображением!

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

Давайте попробуем добавить градиент, как делали выше:

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

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

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

Оживим наш шейдер

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

1
void mainImage( out vec4 fragColor, in vec2 fragCoord )
2
{
3
    vec2 xy = fragCoord.xy / iResolution.xy; // Condensing this into one line

4
       xy.y = 1.0-xy.y; // Flipping the y

5
    vec4 texColor = texture2D(iChannel0,xy); // Get the pixel at xy from iChannel0

6
       texColor.r *= abs(sin(iGlobalTime));
7
    texColor.g *= abs(cos(iGlobalTime));
8
    texColor.b *= abs(sin(iGlobalTime) * cos(iGlobalTime));
9
    fragColor = texColor; // Set the screen pixel to that color

10
}

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

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

Небольшая заметка по отладке шейдеров

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

Заключение

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

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

Финальная задача: Сможете ли вы написать шейдер, который удаляет зеленый экран из видео на ShaderToy и вставляет вместо него другое видео на заднем плане?

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

Понравилась статья? Поделить с друзьями:
  • Как написать шейдер для майнкрафт
  • Как написать шевчуку
  • Как написать шашки на python
  • Как написать шахназарову михаилу
  • Как написать шахматы на питоне