Pull to refresh

Comments 40

Огромное спасибо за такую познавательную статью!
Для тех у кого «шейдеры = магия», это как раз то, что позволяет дать начальное понимание этой кухни.
Shadertoy — вот это настоящая магия. И целые игры с продвинутой графикой, которые там на шейдерах написаны. Ну ОК, не игры а демосцены (user input нет), но там уже полшага остаётся.
Супер! А как? Это ещё одна фича Shadertoy — проброс кликов мыши в шейдер? Не видел такого в описании.
Проброс кликов мыши и позиции там был с ооочень давных времен, как юниформ переменная:
uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click
Инпут с клавиатуры тоже появился вскоре как текстура. Но основная проблема была в том, что негде было промежуточный стейт хранить. И только с появлением рендера в текстуру стало возможным писать вот такие игры.
Проморгал, спасибо. Тестура в качестве буфера данных — красивый ход :)
Спасибо! Очень интересно! Давно интересовала данная тема, но не мог найти простого описания. Надеюсь что вы продолжите писать на эту тему для начинающих.
Очень интересно.
Было бы здорово в будущем увидеть статью о тех подходах, которые используют в реальных шейдерах для игр. Например, хотя все примеры из статьи мне показались тривиальными, я всё равно не могу понять, как таким методом попиксельной обработки можно из верхней половины картинки из майнкрафта получить нижнюю.

Например, вода. Как я понимаю, там каким-то образом должен учитываться наклон поверхности относительно линии взгляда и окружающие объекты, причём с учётом их положения в 3D-пространстве. Я даже предположить не могу, как всё это получается только лишь попиксельными манипуляциями с плоской картинкой.
Или освещённость. Там явно как-то учитывается, какой стороной поверхности повёрнуты к солнцу. Как этого добиться с помощью принципов, описанных в статье?
UFO just landed and posted this here
Иногда сцена рендерится несколькими камерами. Вид из одной камеры является текстурой для смешивания с текстурами предметов, либо становится картой глубин, картой теней, еще можно смешивать текстуры ориентируясь на угол между нормалями плоскостей текстуры и экрана, и так далее, (что знал — всё написал)
Хорошая ремарка про картинку с Майнкрафтом. Опять получилась статья «Как нарисовать сову.»

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

О, спасибо, наличие дополнительных масок всё проясняет :)
Нет там битовых масок. GPU вообще битовые операции раньше не умел, и с интами там все плохо. В идеале GPU работает с флоатами.
Например диффузная компонента обычного Фонга — это косинус угла между инвертированной нормалью и направлением света.
Скалярное произведение двух векторов это результат умножения длин векторов на косинус между ними: |a||b|cos(ab)
Если длины векторов равны единицы, то скалярное произведение вернет косинус. Именно то, что нам нужно для освещения.
Для specular компоненты фонга — вектор луча сначала отражают вдоль нормали, а потом смотрят насколько он попадает в глаз. Через то же самое скалярное произведение.
О каких однобитовых масках вы говорите? Для классического фонга например там одно скалярное произведение на дифузный цвет, и два на спекуляр.
Углы там никто не считает, а скалярное произведение от нормализованных векторов возвращает косинус угла, вот его и используют.

А теперь то же самое, но по русски и чуть подробнее. Я не игродел, а описал решение как оно было сделано в одной программе для проектирования шкафов (из ДСП). Там уровень освещенности поверхности рассчитывался, реально, в шейдере.
Млиииин! ОдноБАЙТные маски у меня там были.

Вот выше описал:
https://habrahabr.ru/company/infopulse/blog/324476/#comment_10129732
А вот в псевдокоде вычисление коэффициента диффузного освещения (diffK)
vec3 N = normalize(pixelNormal); // pixelNormal - нормаль к поверхности в освещаемом пикселе
vec3 lightN = normalize(lightDir); // lightDir - вектор от источника света на освещаемый пиксель
float diffK = dot(-N, lightN); //косинус угла между этими векторами, наш коэффициент диффузного освещения
diffK = clamp(diffK, 0, 1); //но нас интересуют только положительные косинусы, обрезаем отрицательную часть
Простой эффект «волны на воде» даёт displacement shader:
new_pic(x,y) = old_pic( x+dx(x,y), y+dy(x,y) )
где d — ограниченная и (почти) гладкая функция.
Тут подробнее ответил

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

UFO just landed and posted this here

Спасибо, стало понятнее. А вершинные шейдеры тоже получают униформные переменные или как?

UFO just landed and posted this here
Премного благодарен. Вы приоткрыли занавесу тайны =)
Крайне надеюсь на продолжение.
У оригинального автора есть ч. 2 и ч. 3
https://gamedevelopment.tutsplus.com/tutorials/a-beginners-guide-to-coding-graphics-shaders-part-2--cms-24111

https://gamedevelopment.tutsplus.com/tutorials/a-beginners-guide-to-coding-graphics-shaders-part-3--cms-24351
С нетерпением ждем переводов )
Не заметил, что статья — перевод, пока Вы явно на это не указали. И не поверил бы, если не соответствующая плашка. Текст читается хорошо, и даже комментарии в коде на русском. Перечитал еще раз отдельные абзацы — очень хороший перевод, побольше бы таких на хабре.

Так что да, все равно надеюсь на продолжение =)
Перевод действительно хороший, но пара английских шаблонов всё-таки в него просочилась. Я на середине заподозрил, что это перевод, и оказался прав :) Но — да, однозначно отличный материал и хороший перевод. Уже не в первый раз замечаю качественный материал от Инфопульс.
Спасибо огромное! Статья — что надо! Есть необходимость научиться выводить через шейдер 10 битные yuv планы видеокадра и собирать из них целый кадр. С 8ми битными разобрался без проблем. А вот 10-ти битные пока — магия.
Посмотрите в сторону формата текстуры DXGI_FORMAT_R10G10B10A2_UNORM и DXGI_FORMAT_R10G10B10A2_UINT если у вас DX. Для OGL можно нагуглить аналоги констант для этих форматов.
отличная статья и перевод, увлекло не оторваться
Я бы на таких штуках тригонометрию в школе преподавал. Наглядно же видно как арктангенс работает и к чему тут число Пи. А то «пишем формулу: синуск квадрат альфа плюс косинус квадрат альфа...» — скукота.
прикольно.
даже руки зачесались. слегка перепилил, вроде стало ещё круче. ))
https://www.shadertoy.com/view/lssyDl
Спасибо большое! Читать интересно, примеры вроде не очень сложные, но решать прямо приятно :)
Единственным предназначением шейдера является вернуть четыре числа: r, g, b и a.

Люблю когда простые вещи объясняют просто. Отличная статья, спасибо за перевод!
Sign up to leave a comment.