Введение в GLSL

Сегодня вы узнаете, как ускорить процесс рендера примерно в сто раз. Этот метод не универсален, но раскроет вам глаза на массу нюансов. Поэтому к делу и без предисловий. Создам Сюзанну.

При работе во вьювере, вы видите рендер(!), только быстрый.
Язык программирования шейдеров OpenGL Shading Language, попросту GLSL, активируется в тулпанели (вкладка Shading) при активном рендере Internal или Blender Game и не делает с картинкой ровным счётом ничего хорошего, пока вы его не настроете.
В режиме Texture отображается работа источника света Sun (сдвину его в жёлтый), и сейчас, как в космическом вакууме, тени совершенно чёрные. Нужно выставить вертикально вверх направленный голубоватый заполняющий источник света Hemi в пол силы. Теперь Сюзанна словно лежит в лучах летнего солнышка, а цвет неба, словно отражённый от пола, заполняет затенённые участки Сюзанны. Падающая тень в наличии. ГалочкаАmbient Оcclusion включает подобие глобального освещения. А если перейти в режим Blender Game, то в настройках источника света Sun переключение режима буферизации из простого в вариативный, позволит поднять параметр Bias и создать на тени некое подобие рефлексов, а параметром Size или Frustum Size отрегулировать мягкость падающей тени.
Запускаю физическую симуляцию падения головы Сюзанны на плейн — Riggid Body Tools. Не прошло и минуты, а мы получили картинку в динамике, которая прекрасно выглядит прямо в вьювере без привычных многочасовых просчётов. В чём же подвох? А ведь он и правда есть.

Плюсы и минусы GLSL

Недостатки этого рендрера. На момент написания урока в GLSL невозможны даже простые зеркальные отражения, никакого рейтрейсинга и преломлений, гипердинамичного света, моушн блюра (размытие в движении) и вывода слоёв, а так же очень грубая работа с альфа-каналом… Можно сказать, что объекты во вьювере живут сами по себе, и вьювер, в конечном счёте, отображает лишь то, что вы настроили. Любое взаимодействие чуть более сложное, чем тень, нужно настраивать. Если эта новость не вынуждает вас остановить урок, то едем дальше.
Где же наоборот вам может пригодиться(!) знание GLSL? Основное назначение — это игровые материалы. Хотя, GLSL больше похож на огромную коробку конструктора без инструкций по сборке, но при должной сноровке, можно из него собрать самолёт. Игры, интерактивные html-страницы, рендер прямо из вьювера, и даже постобработка видео с цветокоррекцией, для истинных ценителей жанра.

Источники света в GLSL

Начнём с источников света, чтобы к ним больше не возвращаться. Оставлю Hemi, но удалю Sun и создам его заново, чтобы обнулить настройки.

Источник света “Солнце” по умолчанию создаётся без теней, но они легко включаются галочкой Shadow в настройках лампы. Лучи от солнца идут параллельно и все освещённые объекты (и элементы объектов) будут отбрасывать тени в одну сторону.
А вот конус света “Spot”, расширяет тень при удалении от объекта. Иногда требуется именно этот эффект. А если не нужен явный конус света, как от фонарика, расширяем конус света Spot Shape Size почти до 180॰ , и задираем Shadow Size — умножаем на 8. Этот параметр отвечает за разрешение тени. Чем он больше, тем подробнее тень, и тем дольше просчёт. Зато можно получить что-то вроде источника света — Area.
Другие типы источников света не отбрасывают теней. Упомянутый “Area” не работает. “Hemi” просто равномерно заполняет светом пространство. А источник света “Point” может лишь помочь вам добавить блик. Правда, если вам понадобится широкое пятно от объекта, похожее на след от ambient occlusion, вы можете зажечь галочку Negative в настройках источника света Point, или параметр силы света Energy увести в отрицательное значение. Это работает и с другими источниками света, но здесь имеет прикладной эффект. Фактически, вы даже можете добиться цветных рефлексов. Если бы Сюзанна была красной, то Point нужно было бы окрасить в противоположный синий цвет. Тогда он, в отрицательном значении, размажет по поверхности красный рефлекс. Привяжу источники света к Сюзанне и запущу простую физическую симуляцию. Видно, что эти динамические рефлексы (эмуляция Indirect lighting) заметно оживляют картинку. Расстояние их влияния редактируется параметром Distance и другими параметрами, в зависимости от выбранного типа угасания в выпадающем списке Fallof. Туда заглянете сами.

Было бы преcтуплением умолчать о возможности навешивать текстуры на свет. Я вернусь к “солнцу”, и в панели настройки текстур создам для лампы новую (текстуру) и выберу в качестве источника картинки, ветви на белом фоне. Отредактировать размер можно в настройках лампы последним параметром “Frustum Size”. Текстура прекрасно дополняет картинку и всё так же работает в реалтайме.
Тяжело переоценить качественную настройку света в сцене, но пора перейти к самой интересной и сложной части конструктора — будем собирать шейдеры. Материал Blender Game настраивается привычным способом, его параметры регулируются в окне свойств материала.
Выбор небольшой, но и тут есть, на что посмотреть.

Вкладка Diffuse

Помимо простого выбора цвета шейдера (пока назначу белый), есть возможность задать градиент затенения, галочка Ramp: по умолчнанию от светлого к тёмному. Плюсиком назначу промежуточный цвет (чёрный непрозрачный) и поменяю его местами с белым. Раз, два, и получился метализированный отлив. Попробуйте несколько экспериментов сами.
Важно помнить, что градиент затенения Ramp накладывается(!) на текущую модель затенения. У него даже есть фактор наложения. “Factor” в значении “ноль” то же, что и выключенная галочка “Ramp”. Если сейчас сменить цвет шейдера на “красный”, то покраснеет лишь часть Сюзанны, т.к. прозрачность имелась только в левой позиции градиента. Убираем прозрачность, исчезает и красный цвет. Ровно так работает режим наложения “Mix”, который сейчас активирован. И, конечно, можно менять режимы наложения градиента на модель затенения. Например, выставлю “Мultiply”.

Градиент может накладываться не только по фактору затенения. Меняем в списке input “Shader” на “Normal” и получаем материал, работающий, как излюбленные скульпторами MatCaps. Они ориентируются на карту нормалей. Режимы работы градиента не заканчиваются и на этом. Метод интерполяции градиента может сильно повлиять на картинку. Если сменить текущий режим градиента “Linear” на “B-Spline”, градиент станет значительно мягче, а вот в режиме “Constant” во вьювере появится дерзкий туншейдер.

Чуть более сложными для понимания являются режимы интерполяции цветов: RGB, HSV, HSL. Снесу шейдер и создам новый. Тут, в градиете слева будет непрозрачный красный, справа непрозрачный синий. В RGB режиме интерполяция проходит словно по прямой от точки красного, до точки синего. В HSL и HSV режимах интерполяция происходит по огибающей кривой. Это легко заметить, если выставить режим этой кривой ClockWise (по часовой стрелке). Радуга на лицо. О, кстати, если поменять местами точки градиента, и выставить режим “Против часовой стелки”, то получится настоящая тепловая карта освещения. В общем, играться с этими параметрами можно гораздо дольше, чем кажется. И, конечно, цвета реагируют на поворот мартышки или вращение лампы.
Получившаяся карта очень хорошо подходит для демонстрации двух оставшихся без внимания режимов “input”. Здесь “Energy” заставляет реагировать градиент на одноимённый параметр лампы. Если режим “Shader” заполняет градиентом затенение от самой освещённой точки до самой затенённой, то режим “Energy” ориентируется на работу света более тонко и может использовать только область градиента. Т.е. реакция на источник света более тонкая.
Снова к режиму “Energy”. Тень, созданная текстурой лампы, серая и не влияет на градиент. Перехожу в режим “Result”, и теперь градиент учитывает любые(!) затенения объекта. Вот такая фантастика. Покончим с градиентом. Выключу его.

Алгоритмы затенения

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

Lambert — самый простой “пластиковый” алгоритм, регулируется лишь его освещаемость;

Oren-Nayar — “бумажный”, имеет параметр шероховатости;

Minnaert — затемняет центр и, при максимальном значении Darkness: 2, создаёт эффект вельветовой ткани; подойдёт для текстиля (но не для всякого! у хлопка этот эффект чрезвычайно малозаметен. в общем, НЕ стоит пихать его во все материалы тканей, которые только приду вам в голову! иначе будет один сплошной бархат…);

Fresnel — при факторе “один к двум” даёт вывернутый эффект освещённой зоны, тут стоит напомнить, что всё это не готовые материалы, а лишь составные части. Такое затенение пригодиться при эмуляции зеркальных поверхностей.

Toon — мультяшный шейдер, позволяет регулировать Smooth — мягкость перехода от света к тени и Size — размер освещённой зоны.

А теперь, так же коротко о бликах. Вкладка “Specular” (верну интенсивность).

Toon — работает так же, как его собрат (погашу пока интенсинвность Diffuse), но жёсткий переход намекает на возможность использования металлических поверхностях;

Wardlso — для сравнения, отлично подойдёт для фарфора или автомобильной краски;

Blinn, Phong и CookTor — довольно схожи и дают более мягкие блики.

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

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

Сейчас стоит зайти во вкладку Shading, но, буквально из-за одного параметра Emit — свечение. Сделаю для его демонстрации дополнительный материал и назначу его на глаза Сюзанны. Работу свечения можно увидеть только в тени (что хорошо видно, при вращении мартышки), к сожалению, такой материал ничего не подсвечивает. И если потребуется цветной отсвет, то придётся в центре глаза расположить точечный источник света с небольшим радиусом действия. Это значительно прибавит реалистичности.
И ещё галочка Shadeless — она и вовсе убирает любое взаимодействие со светом и похожа по работе на Emit, но не регулируется, а просто включается и выключается.

Итого, у нас есть диффузный шейдер, метал, глянец, текстиль, маткапы, свечение и даже параметрические тепловые карты. А мы ещё даже не поговорили про…

Текстуры

Сразу о главном недостатке: процедурные(!) текстуры во вьювере не отображаются. Только загружаемые картинки: режим “Image or Movie”.

Второй момент: ноды — это лишь дополнение к окну свойств материала, которое расширяет возможности, но мы сразу попробуем ноды настройки материалов, чтобы не рассеивать внимание на два способа, хотя простые(!) материалы предпочтительно настраивать без нодов.
Таймлайн заменяю окном Node Editor, где должен быть включен режим “Material”. Тут пока пусто. В самом материале теперь нужно зажать кнопку “Use shader nodes”. И в это мгновение логика использования материалов резко изменяется. В списке материалов появляется новый материал “Node ”, а в нодовом редакторе два блока: Output (блок вывода) и Material (источник материала). В последнем нужно указать вместо никакого (Сюзанна во вьювере чёрная), наш настроенный материал, чтобы он применился к объекту. Вторая часть название нодового материала при этом меняется на название выбранного источника. Формальности на этом заканчиваются, начинаются приключения.
В списке нода Material можно указать любой шейдер, хранящийся в blend-файле. На выходе из этого нода мы извлекаем настроки шейдера (т.е. ракцию на освещение), а вот на вход можем подать не только цвет, но и текстуры. Чем сейчас и займёмся.
Для начала немного намусорю. Добавлю блоки входных каналов: Camera Data, Lamp Data, Geometry. Приготовьтесь к тому, что помимо привычных способов использования каналов, вскроются совершенно крышесносные варианты.
У нас имеется три типа каналов:
жёлтые — цвет сам по себе или с дополнительной информацией о шейдере;
серые — чёрно-белые маски влияния, создают разнообразные зависимости;
синие — векторные, в цветовой форме передают, например, данные о позиции и вращении объекта.

С них и начнём. Уберу всё, кроме нодов Output и Geometry. Между ними вставлю затайленную текстуру и отправлю на выход. Да, так можно делать, но материал никак не будет затеняться, словно включена галочка Shadless. И так, синие каналы нода Geometry будут влиять на распределение текстуры по объекту. Для наглядности, во вьювере создам кубик и сглаженный шарик. При помощи констрейнов свяжу их трансофрмации: поворот и перемещение. И ещё создам развёртку на скорую руку.

канал UV — самый надёжный и понятный способ распределения текстуры по объекту, если у него есть развёртка. Канал задаёт текстуре координаты развёртки, тем самым прочно сажает текстуру на объект;
канал Orco — текстура натягивается на объект проекцией сверху и крепко сидит на ней, независимо от поворота, позиции или масштаба объекта; быстро, но не всегда практично из-за артефактов на боковых сторонах;
канал Global — здесь наблюдается интересный эффект: координаты текстуры не реагируют на трансформации объекта, текстура статична относительно глобальной системы координат;
канал Local — просто проецирует текстуру из точки обзора и снова текстура глобально остаётся на месте;
канал View — делает то же самое, но текстуру размазывает по виду из камеры;
канал Normal — натягивает текстуры по карте нормалей, что идеально подходит для наложения matcap-текстур.

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

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

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

Зависимости. До сих пор ноды в уроке строились одина за другой. Пора заглянуть поглубже в лес и поглядеть на более ветвистые варианты.

Смешивание по фактору

В основе всего лежит банальный Color Mix, куда заводится два цвета (например синий и зелёный) (в эти же каналы можно заводить шейдеры) и фактор смешивания. На вход в жёлтые каналы можно подать и текстуры и шейдеры, а вот фактор — это всегда чёрно-белая маска, но полученная из чего-угодно. И это самое интересное.
Возьму шарик и расположу его в центре координат. На выход подам канал Geometry Global. Шарик окрасился, а при перемещении видно, что эта окраска демонстрирует глобальные координаты в цветном RGB формате.

Первый основной приём: разложение по каналам. Нод Converter / Separate RGB ставим между двумя рабочими и получаем одноцветную маску. Первый канал R (red), соответствует первой по порядку координате X (икс). Остальные, соответсвенно, двум оставшимся. При перемещении объекта это становится действительно понятно. Маска в глобальных координатах остаётся на месте. Установлю маску по оси Z (зед), по высоте.
Эту маску уже(!) можно использовать в качестве фактора смешивания для нода Mix. В цепочке уже четыре нода. А теперь между первыми двумя вклиним Vector Mapping. С его помощью данные вектор-канала можно масштабировать, разворачивать и попросту перемещать. Это второй приём, который сильно расширит ваши возможности.
Если Mapping манипулирует со всем диапазоном вектор канала, то Converter ColorRamp помогает наглядно работать с видимым диапазоном маски. Это третий распространённый приём.

Итого:

  • разложение Separate,
  • манипулирование Mapping,
  • настройка ColorRamp.

Чтобы дальше было веселее, вместо шарика поставлю Landscape. И применю к нему тот же материал. Пусть это будут горы, вершины которых покрыты снегом. Сейчас не хватает модели затенения, поэтому между последними двумя нодами в цепочке нужно установить простой Material без бликов. И слегка настроить освещение: жёлтое солнышко с тенью и голубоватый заполняющий Hemi. Отлично! Можно продолжать эксперименты. С этого момента наша цепочка начнёт ветвиться.
Моя задача — продемонстрировать как можно больше приёмов на простом примере. Я хотел бы потратить время на реализм, но не могу затягивать урок. Поэтому оставим границу снегов ровной. А вот лощины хочется засеять растительностью. Для этого использую маску, сгененированную цветом на вершинах. Всё просто.
Переключаю вьювер в режим рисования по вершинам. Для наглядности подам на выход материала планируемый Vertex Color. Объект побелел, но это ненадого. Во вьювере в меню выбираю Paint / Dirty Vertex Color и все впадинки темнеют. Можно отрегулировать до нужного результата. Дальше займусь доработкой маски. Вычту из неё верхние точки, оставлю растительность только внизу. Такую маску можно использовать для создания грязи, пыли или мха в трещинах или впадинах состаренных объектов. А можно и вовсе рисовать маску или даже цвета вручную, чтобы разбавить симметричные текстуры. Маска доработана. Создаю новый Mix с новым зелёным цветом, ставлю его в цепочке после первого Mix-а и подаю полученную маску в качестве фактора. Лощины позеленели. Можно поиграть с высотой ландшафта и полюбоваться интерактивностью шейдера. Здесь мы задействовали канал глобальных координат и цвет вершин. С другими вектор-каналами история будет схожая.

Прежде чем мы закончим с нодом Geometry, стоит упомянуть канал Front/Back. Он использует данные о направлениях нормалей и создаёт двухцветную маску: белый цвет окрасит наружние стороны объекта, чёрный фактор — изнанку. Так даже лист бумаги, сделанный одним полигоном, может иметь разные материалы с разных сторон.

И ещё один рабочий инструмент — карта нормалей — normal map. Вывести во вьювер карту нормалей довольно просто. Понадобятся 4 ноды: Geometry, Texture, Material и Output. В качестве текстуры необходимо загрузить растровую карту нормалей, её ориентация по поверхности задаётся одним из каналов Geometry, а затем отправляется в материал. Только обязательно синее к синему — вектор к вектору. Если расположить точечный источник света над такой поверхностью, то, к великому огорчению, будет видна некорректная работа канала нормалей в GLSL. Теплится надежда, что это поправят, а пока вставляем после текстуры нод Mapping и параметрами поворота и/или масшаба стараемся найти оптимальное отображение. Это самое быстрое решение, которое удалось найти. Тут стоит отдать должное окну настройке текстур материала. Если всё-таки настраивать нормали через него, то мало того, что не возникает никакой проблемы, так ещё и открывается возможность менять Bump Mapping Method. Едем дальше.

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

Input — Camera Data

Здесь важен канал Z Depth. Отправлю его сразу на выход. Пока мы получили всего лишь белый ландшафт. Однако, если поставить в разрыв нод Converter — Squeeze Value, можно сдвинуть вектор канал в сторону видимого диапазона. Ещё один нод, который позволяет это сделать Converter Math. При помощи такой маски можно в материале задать атмосферную перспективу. К слову сказать, попросту можно в настройках мира зажечь галочку Mist, но случаи бывают разные и маска не окажется лишней. И ещё один источник…

Input — Lamp Data

Предназначен для извлечения данных об освещении объекта конкретным источником. Выберу лампу Sun. канал
Color — выводит цвет, на излучение которого настроен источник;
Lighth Vector — реагирует на поворот источника света, если это солнце, или на позицию, если это Point или Spot. Извлечь маску, как и раньше, можно разделением на каналы. Так можно заменять один материал на другой при изменении положения или поворота источника света. Причём источник света может и вовсе быть использован не для освещения, а именно для создания этой маски.
Distance — создаёт маску по сфере с единичным радиусом вокруг источника света, если это Point или Spot. Не слишком информативный канал. Граздо богаче другой.
Visibility Factor — он реагирует на рассеивание света, которое регулируется параметром лампы Falloff Distance, а так же дополнительными тонкими настройками, например тип остлабления Custom Curve и кривыми отредактируем спад. Маска отреагрирует и на это, а значит можно создать кольцевую маску, задав кривой несколько горок. Канал работает для источников света Point и Spot. Причём источник света Spot создаёт маску именно по своему конусу свечения. Использовать подобную очень удобно, если вы играетесь с фонариком в реалтаймовой сцене, по такой маске можно смешивать в материале две заранее подготовленные текстуры: освещённую и неосвещённую. Будет отличный результат. И, последний канал…
Shadow — выводит на объект только тени от источника света. Важно! Маска покажет вам падающие тени от других предметов, но не даст вам информацию о собственной тени объекта. Для этих целей можно использовать просто информацию цвета простого белого шейдера.

Математика координат

Урок в большей степени получился о том, как вытаскивать различные типы информации в нодовый редактор материалов. Остаётся показать ещё одно поле экспериментов и уже наконец оставить вас всё это переваривать. Соберите мозги в кучку, осталось немного. Математические действия с координатами. Если мозг после этой фразы решил пойти поспать, похлещите себя по лицу. Покажу операцию на очень простом примере. Закину во вьювер картинку, как плейн, материал переведу в нодовый формат и оставлю только Output. Теперь заведу сюда в виде текстуры ту саму картинку, из которой был сгенерирован плейн. Добавлю третий нод Geometry, где укажу UV-развёртку объекта и подам информацию о ней на текстуру. Три нода и материал Shadless готов к эксперименту.
Сейчас заведу в ноды материалов тайловую тектуру Clouds. Подам на неё и глобальный метод распределения по объекту и отправлю на выход для демонстрации.

А сейчас эта текстура будет смешиваться с координатами распределения UV-развёртки и деформировать их. Для этого добавляем нод Converter — Vector Math. Это нод математических операций с векторными каналами. Результат смешивания двух векторов выглядит на объекте довольно загадочно. Что будет если подать на текстуру плейна не чистый UV-канал, а смешаный с таким вот шумом? Смотрим. Всю картинку сильно покорёжило, как в кривом зеркале, а при перемещении плейна всё выглядит ещё интереснее. Картика динамично плывёт.
Чтобы снизить влияние шума, поставлю после текстуры Clouds нод Color — Hue/Saturation и постепенно снижу Value почти до нуля. Во вьювере всё динамично изменяется. Думаю, картинка говорит сама за себя и вам понятно, как работает эта деформация за счёт смешивания вектор-каналов координат. Как и все остальные данные о распределении текстур, при помощи нода Mapping можно отрегулировать положение или масштаб деформации. А придумать применений этого приёма можно ещё миллион. Всё!

Естественно, все эти приёмы работают не только в GLSL, а рендер вьювера пригодится не только владельцам слабых компьютеров. Качественным превью можно порадовать заказчика (иное превью вообще принимают, как чистовой рендер). Возможно вы затеяли свою игру, а может быть подсели на аддон Blend4Web и выгоняете из блендера интерактивные html-страницы. Об этом расскажу в ближайшем уроке. Так или иначе, Happy Blending, помните, что многие параметры материалов можно ещё и анимировать.

До новых встреч в нашем курсе Blender Level Up!