Математика в 3Д ► 14. Lens Flares. Маски
Продолжаем создавать Lens Flares - блики линзы. Сегодня создадим несколько масок, которые можно использовать в сочетании с другими элементами, чтобы фрагментарно ограничивать их видимость.
О том, как настроен проект, я подробно рассказывал в первой части.
О том, как настроен проект, я подробно рассказывал в первой части.
Буду очень благодарен всем, кто решит стать платными подписчиками или разово задонатить на означенные цели. Это сильно мотивирует на продолжение.
Прошлый раз мы остановились на подключении нескольких копий лучей с разными настройками к общему дереву нодов ↓
Маска в виде луча.
↑ Для первой маски мы сможем использовать ту же маску, которую мы использовали в лучах для скрытия шва. Чтобы не создавать её заново, войдём внутрь группы с помощью Tab, и выделим вот эти ноды: разделение по осям XYZ с помощью Separate XYZ, запуск градиента по кругу с помощью Math > Arctan 2, переброска отрицательных значений в положительный диапазон с помощью Math > Absolute, инвертирование результата путем вычитание его из единицы с помощью Math > Subtract. Выделяем ноды, нажимаем Ctrl+C - курсор мыши в этот момент должен находиться в окне Shader Editor.
↑ Выходим из группы с помощью Tab, нажимаем Ctrl+V, чтобы вставить скопированные ноды. Они могут вставиться где-то вне пределов видимости, поэтому с помощью колёсика мыши можно отъехать назад и попытаться их найти, после чего с помощью G перетащить куда-нибудь поближе, где с ними будет удобно работать.
↑ Подключаем координаты Object, смотрим как выглядит результат. Его мы сможем использовать, чтобы контролировать обрезку лучей, сфер или других элементов по какому-нибудь одному направлению.
↑ Чтобы контролировать вращение, перед входом в Separate XYZ ставим Shift+A > Vector > Mapping
↑ Контролировать ширину полосы мы будем с помощью верхнего значения в Math > Subtract. Поскольку арктангенс даёт значения от -Пи до Пи, чтобы минимальное значение диапазона стало 1, и маска заполнила собою всю ширину, нужно вычесть арктангенс из значения равного 2Пи, для этого просто вбиваем в Math > Subtract вместо цифр формулу pi*2 - и Блендер самостоятельно подставит числовой результат
↑ Вычитая арктангенс из 0, верхним значением диапазона значений, который он возвращает в виде градиента, мы получаем 0, то есть маска полностью схлопывается.
↑ Как и в случае со сферической маской, чтобы удерживать конечный диапазон в пределах от 0 до 1, но чтобы при этом он не обрезался, как в случае с Clamp, а продолжал равномерно распространяться от низшего до высшего значений, мы будем использовать одно и то же число, чтобы вычитать из него арктангенс, и чтобы на него же делить получившийся результат с помощью Math > Divide (деление).
↑ И, опять же, как и для сферической маски, мы будем контролировать огибающую градиента - смещение диапазона с помощью Math > Power (возведение в степень). Значения от 1 до 0 будут сдвигать диапазон ближе к 1, а градиент к белому цвету, делая края маски более чётко очерченными, а значения выше 1 будут сдвигать диапазон ближе к 0, а градиент - к чёрному цвету, делая края маски более размытыми.
↑ Добавим вспомогательные ноды Value и объединяющую линки точку Reroute, выделим все нужные ноды и Reroute
↑ С помощью Ctrl+G объединим выбранные ноды в группу
↑ Перед подключением параметра Rotation у нода Mapping к свободному входу для создания нового входа группы, сбросим значение вращения, чтобы вход создался сразу с правильными дефолтными настройками.
↑ Подключаем параметр Rotation нода Mapping к свободном входу и в N-панели во вкладке Group выставляем порядок и переименовываем входы. Ограничиваем максимальное значение для входа, определяющего ширину маски значением 2Пи, точно так же вбив pi*2, как мы уже делали раньше для нода Math.
↑ Используя Ctrl+H, чтобы скрыть неиспользуемые входы и H, чтобы свернуть ноды, компактизируем их, оставляя открытыми только те, в которых есть какие-то важные для понимания работы системы настройки. Например, я оставил открытым Math > Divide, чтобы показать мне из будущего, в какой момент осуществляется клэмпинг, не позволяющий маске проваливаться в отрицательные значения. Ограничиваем минимальное значение для параметра Exponent 0.0001, чтобы избежать возведения в нулевую степень, которое приведёт к заливанию всего экрана белым цветом.
↑ Выходим из группы, удаляем вспомогательные ноды Value, они были нужны только для автоматического создания входов группы при её создании. Ставим значок щитка, чтобы Блендер случайно не удалил группу при закрытии проекта, если она нигде не будет использована. Переименовываем группу во что-то осмысленное, например - Mask Radial
↑ Подключаем систему из прошлых уроков обратно. И мне пришло в голову, что называть ширину маски Offset было не совсем правильно, поэтому я переименовываю этот вход в Width, что будет более явно отражать суть параметра.
↑ Чтобы использовать получившийся результат в виде маски, нам надо перемножить его с помощью Math > Multiply (умножение) с элементом, на который мы хотим эту маску наложить. После этого элемент с наложенной маской мы можем с помощью Math > Add (сложение) добавить к остальным элементам.
↑ Настройки крупным планом
↑ Так выглядит маска
↑ Так выглядит элемент, который надо замаскировать.
↑ Так выглядит замаскированный элемент. Чёрный - это 0, белый - это 1. Всё, что было чёрным (нулём) или в маске или в элементе, становится чёрным, потому что любое число при умножении на 0 даёт 0 - поэтому мы, напомню, и используем для смешивания именно умножение. А белым остаётся только то, что было белым и там, и там, потому что при умножении на 1, любое число остаётся самим собой.
Маска в виде кольца.
↑ Для маски в виде кольца мы будем использовать Vector Math > Length
↑ Для начала инвертируем её. На этот раз нам это нужно не чтобы получить белую сферу в центре, а чтобы получить отрицательные значения за её пределами. Зачем?
↑ Чтобы с помощью Math > Absolute перекинуть их в положительный диапазон и получить кольцо с нулевым значением по краю сферы. Кольцо тьмы. Не смотрите на него долго, а то оно начнёт смотреть на вас. Буа-ха-ха-ха!
↑ Инвертируем результат, вычтя его из 1 с помощью Math > Subtract (вычитание), чтобы кольцо тьмы стало кольцом света во тьме. Как там пелось? "Брат мой, крест твой в круге, брат круг мой объял крест, брат мой крест мой в круге, брат, круг твой объял крест, брат мой..." Вот. А из песни слова не выкинешь. Ранний Калугин неподражаем. О чём бишь я? Ах да!
↑ Теперь с помощью первого Subtract, определяющего, из какого значения мы вычитаем значения сферы, мы будем, соответственно, контролировать границу сферы - или позицию кольца. А с помощью второго Subtract - ширину сферы. Добавим вспомогательные Value и сразу в N-панели во вкладке Node в графе Label назовём их, чтобы не забыть, какой параметр за что отвечает.
↑ Добавим Math > Power (возведение в степень), чтобы контролировать огибающую - или ближе к каким значениям смещается диапазон - или размытость границ маски. Добавим вспомогательный Value и к нему.
↑ Можно выравнять для красоты все ноды с помощью S > X > 0, выделить их для добавления в группу...
↑ ...нажать Ctrl+G, в N-панели во вкладке Group определить порядок входов, придумать им осмысленные названия...
↑ Установить при необходимости значения по умолчанию, минимальные и максимальные значения. Для экспоненты опять же стоит выставить минимальное значение на 0.0001, чтобы избежать неожиданных залитий экрана белым, вследствие возведения в нулевую степень.
↑ Выходим из группы, удаляем вспомогательные Value, нажимаем значок щитка, чтобы избежать случайного удаления группы, переназываем группу во что-то осмысленное, например - Mask Ring.
🛈 Я специально во всех группах пишу сначала слово Mask, а потом уточняю, какая именно это маска, чтобы когда потом при добавлении в материалы мы будем искать их среди всех групп проекта, все маски шли одна за другой. Блендер сортирует в меню названия добавленных групп по имени.
↑ Однако, поднимая ширину до значений выше единицы, мы предсказуемо столкнёмся с той же проблемой, которую уже решали, когда делали сферическую маску - вместо того, чтобы растягивался градиент, в центре образуется залитая белым область.
↑ Решать мы будем эту проблему так же, как решали для сферы (не в конечном её варианте, где мы просто масштабируем входящие векторные координаты, а в самом уроке). Мы будем использовать созданную в первой части нод-группу Mix Values, а в качестве фактора - Math > Greater Than с нижним значением равным 1, чтобы после того, как значение Width в создаваемой сейчас группе превысит единицу, использовалось значение, подключенное в нижний слот Mix Values, а между значениями Width от 0 до 1 использовалось, то, что мы уже успели создать к этому моменту, подключенное в верхний слот Mix Values. На словах звучит путано, просто посмотрите скриншот.
↑ Сама группа Mix Values, которая смешивает два числовых значения по тому же принципу, по которому MixRGB смешивает два цвета, изнутри выглядит так.
↑ В комментариях подсказали её оптимизированный вариант, который делает то же самое, но используется на одну операцию меньше. В дальнейшем мы будем использовать его. Попробуйте проанализировать, что здесь происходит, самостоятельно.
↑ Итак, в качестве фактора для Mix Values мы используем Math > Greater Than (больше чем), который анализирует входящий параметр Width, и пока он меньше или равен 1, заливает всё чёрным цветом (0), а когда он становится больше 1, заливает всё белым цветом (1). В качестве первого значения, которое будет использоваться, пока фактор равен 0, то есть пока Width не превышает 1, подключаем всё, что создали до этого. Для второго значения, которое будет использоваться, когда фактор равен 1, то есть когда Width превысит значение 1:
• с помощью Ctrl+Shift+D дублируем Math > Subtract (вычитание) с сохранением входящих линков
• отключаем у него Clamp
• с помощью Math > Divide (деление) делим то, что выходит из него на то же значение, которое используется для верхнего входа в Subtract. То есть увеличивая в Subtract значение, из которого мы вычитаем градиент кольца, мы с помощью деления компенсируем результат во столько же раз, оставляя диапазон в границах от 0 до 1.
↑ Компактизируем ноды, оставляем открытыми только те, в которых есть важные для понимания работы параметры. В данном случае я оставил Subtract с Clamp открытым, чтобы потом у меня не возникло вопроса, зачем здесь рядом два одинаковых нода Subtract с одними и теми же входящими значениями.
↑ К маскируемому элементу маска добавляется точно так же, как и предыдущая - с помощью умножения
↑ Мало того, с помощью умножения мы можем сочетать две маски между собой, оставляя белым только те участки, где у обоих масок цвет белый. Умножать друг на друга маски и элементы можно в любой последовательности, поскольку, как мы помним, от перемены мест множителей произведение не меняется. А те, кто учат в школе детей, что умножая две тарелки на три сырника мы получим тарелки, и ещё и оценки снижают за изменение порядка множителей (и множимых, штээээ?) - форменные диверсанты.
Если вам нравятся эти уроки, скажите спасибо тем, кто забирает их к себе на стенки, рассказывает о них друзьям, знакомым, в сообществах, пабликах, чатах, коммьюнити. Этих людей всё ещё очень мало, но именно благодаря их действиям вы сейчас можете видеть эти уроки.
Со своей стороны выражаю большую благодарность спонсорам. Ваша поддержка даёт мне силы продолжать.