EN
Andrey Sokolov
Andrey Sokolov
725 subscribers
goals
17 of 500 paid subscribers
Когда я наберу 500 платных подписчиков, смогу больше времени уделять записи видео и разработке аддонов для Blender.
360.79 of $ 1 135 money raised
Донаты || Donates
37.59 of $ 568 money raised
Cделать аддон True Time Remapping бесплатным для всех желающих навсегда. Make True Time Remapping add-on free for everyone forever.
113.49 of $ 114 money raised
На дисковый накопитель 4Tb для хранения бэкапов курса «Blender Избушка».

Математика в 3Д ► 19. Lens Flares. Подключаем Геометрические Ноды

Приношу извинения за задержку и огромное спасибо за собранные лайки - уже, страшно подумать, месяц назад собранные! Серия Математика в 3Д продолжается!
Сначала я предполагал уместить всё обещанное в один урок, чтобы завершить тему с Бликами Линзы и двигаться дальше, но когда поймал себя на том, что пишу двухсотую строку кода, и до конца остаётся ещё прилично, решил, что всё-таки надо как-то разделить материал на смысловые части. Поэтому сегодня, для разгона, после перерыва будет приведение всего, что уже было сделано, в удобочитаемый вид, а также замена вычислений в скрипте на вычисления в Геометрических Нодах.
Буду очень благодарен всем, кто решит стать платными подписчиками или разово задонатить на означенные цели. Напомню, что в прошлый раз мы остановились на том, что отрендерили с помощью скрипта несколько сотен элементов боке в разных вариациях ↓
Первый и главный вопрос - зачем нужна замена скрипта на геоноды, если у нас уже есть готовая работающая система. В первую очередь - для организации интерфейса, то есть удобного взаимодействия пользователя с системой. Сейчас, чтобы заменить в системе любой из объектов, нужно вспоминать, где в шейдере используются драйверы, в каких из них используются объекты, залезать внутрь, смотреть, редактировать. Плюс в самом редакторе шейдеров дерево нодов продолжает расти, и если нам, например, понадобится (а нам понадобится) в разных местах подключать вычисление текстурных координат с разными корректировками, то в скором времени либо паутина нодов станет окончательно нечитаемой, либо нам придётся выполнять одни и те же вычисления по несколько раз в ущерб производительности, либо убирать всё внутрь нод-групп, плодя их количество.
Геометрические ноды решают эти проблемы. Их можно настроить таким образом, чтобы объекты, участвующие в расчётах, можно было заменять прямо в модификаторе на объекте, даже не открывая нодовый редактор - это что касается пользовательского интерфейса. Плюс один раз посчитанные в геонодах атрибуты можно сколько угодно раз подключать в редакторе шейдеров, в любом месте, и это не приводит к дополнительной нагрузке - это что касается сохранения дерева нодов читаемым и удобным для дальнейшей разработки. 
Может показаться, что это всё пустая трата времени, но на самом деле это, напротив, экономия времени, вашего будущего времени и времени других людей, которые будут этим пользоваться.
Когда я говорю, что дерево нодов перестаёт быть читаемым, я имею в виду вот это ↓
↑ Поверьте, это далеко не самый хаотичный вид дерева нодов. Но сколько времени у вас займёт, месяц спустя после последнего открытия проекта, чтобы разобраться, что здесь что? Что это за серая рамочка слева, она ещё нужна? Что это за не подключенные ни к чему ноды тут и там? Визуально видно, что какие-то группы нодов, очевидно, работают вместе, какие-то повторяются, но что они делают?
Поэтому для начала приведём всё в порядок. Выясним, какие группы нодов за что отвечают, объединим их в рамочки, зададим им цвета по функциональному значению - это делается в N-панели, во вкладке Node. В графе Label зададим рамочкам названия по смыслу. Ниже, во вкладке Properties можно задать максимальный размер шрифта, чтобы названия рамочек можно было прочитать даже на удалении. Поскольку при приближении/удалении ноды могут начать перекрывать названия, я использую точки Reroute, чтобы закрепить углы рамочек чуть выше и шире, чем начинаются ноды в них - обычно одной-двух точек достаточно. Добавить их можно через Shift+A > Layout > Reroute
↑ Тут дел на 5-10 минут, но зато в таком виде достаточно одного взгляда, чтобы понять, какая секция за что отвечает.
ARCHIVE - архив; то, что непосредственно в шейдере не используется, но может использоваться в качестве примеров расчетов или во вспомогательных скриптах.
TC Coordinate - текстурные координаты, я постарался подобрать тот же сине-фиолетовый оттенок, которым в Блендер обозначаются векторы
GLOW - все элементы свечения
RAYS - лучи
BOKEH - боке
COLOR - цвет (вот сейчас вижу, что можно было его сделать другим цветом, потому что здесь ничего не генерируется, а просто раскрашиваются уже собранные до этого элементы)
Теперь можно легко найти нужную секцию, навестись на неё и прорабатывать независимо от остальных. И сегодня мы займёмся текстурными координатами ↓
Только что заметил, что вместо "Texture Coordinate" назвал рамку "TC Coordinates". "TC" я обычно использую как сокращение от Texture Coordinate. Получилось масло масляное. Ладно, главное, что понятно. 
Для начала реаранжируем все математические ноды, скроем лишний вход у Scale (Ctrl+H), потому что он просто умножает значение вращения камеры на -1, и не предполагается, что он будет в дальнейшем как-то меняться. Вынесем из рамочки (Alt+P) все входящие данные - Текстурные координаты камеры, вращение камеры и сдвиг текстурных координат. ↓
↑ Переименуем сами ноды в N-панели, во вкладке Node, в графе Label так, чтобы недвусмысленно было понятно, что именно они возвращают.
Свежий пример. У меня вращение камеры до этого называлось просто "Camera" - поленился когда-то впечатать полностью. В результате минут двадцать не мог понять, почему всё работает не так, как должно, потому что думал, что это позиция камеры, а не вращение. 
Разделим окно и откроем Geometry Node Editor
Убедимся, что в качестве активного объекта выбран Plane и в редакторе Геометрических Нодов нажмём New
↑ Если экран залит серым, и вы не можете ни на что нажать, проверьте, не включена ли у вас для этого окна "заколка", иконка с канцелярской кнопкой.
Если вы открыли Геометрические Ноды и создали новый блок данных, но он пустой, попробуйте нажать A (выделить всё) и после этого точку на нампаде (сфокусироваться на выделенном). Скорее всего ноды просто где-то вне поля видимости ↓ 
Чтобы понять принцип и потренироваться, сначала заменим в Shader Editor нод Combine XYZ, в который сейчас с помощью драйверов передаётся параметр вращения камеры, на атрибут, полученный с помощью Геометрических Нодов. Достаточно страшно и заумно звучит? 
В Геометрических Нодах трансформации любого объекта (Location, Rotation, Scale) можно получить с помощью нода Object Info. Найдём этот нод через поиск - Shift+A > Search...
Начинаем вбивать "object" - и нужный вариант будет, вероятно чуть ли не единственным в списке, в зависимости от версии ↓
Выберем в нём в качестве объекта объект Camera
Есть несколько способов вывести из Геометрических Нодов любой из параметров (например, с помощью нода Store Named Attribute, но мы пойдём другим путём). Предлагаю использовать наиболее простой способ, без дополнительных нодов - просто подключить параметр Rotation нода Object Info с выбранным объектом камеры к свободному выходу в Group Output ↓
↑ Теперь этот параметр появился в модификаторе Geometry Nodes (панель внизу справа, вкладка модификаторы, иконка с синим гаечным ключом), во вкладке Output Attributes.

Чтобы мы могли получить доступ к нему в Shader Editor, необходимо в настройках модификатора, во вкладке Output Attributes задать ему произвольное название. Оно может быть практически любым, главное, чтобы оно совпало здесь и позже в Shader Editor, и конечно желательно, чтобы оно отражало суть проводимого параметра, чтобы избежать путаницы. Я выбрал название camera_rotation. Таким образом мы создаем для объекта новый именованный атрибут, содержащий значение вращения объекта Camera
🛈 Если вам интересны Геометрические Ноды, то понимание концепции Атрибутов является одним из ключевых. Что такое атрибут? Атрибут - это некое свойство элементов одного типа, конкретные значения которого могут быть разными для каждого элемента. При этом само свойство, сам атрибут есть у всех элементов одного типа. Например, у каждого вертекса есть позиция в пространстве - это его атрибут; есть вектор нормали - это его атрибут; есть порядковый индекс - это его атрибут. Они там были всегда.
Мы же добавляем ещё один, новый атрибут, который теперь появляется у каждого элемента объекта. Если быть точнее, при таком способе добавления, у каждого вертекса объекта. Этот атрибут представляет из себя вектор, то есть 3 дробные числа. А в качестве конкретных значений этих чисел для каждого вертекса мы устанавливаем одни и те же значения - вращение камеры в радианах по осям X, Y и Z.
В дальнейшем, когда мы начнём использовать полученный атрибут в Shader Editor, Блендер будет определять, какой из вертексов оказывается ближайшим к тому пикселю, который в данный момент просчитывается, и при просчётах для этого пикселя будет использовать значение атрибута, полученное от ближайшего вертекса. Но поскольку для всех вертексов значение вращения камеры будет одинаковым, то получится, что атрибут будет использован одинаково для всей поверхности объекта.
Чтобы впоследствии мы могли изменять объект камеры, не заходя в сами ноды, можно подключить соккет Object в Object Info к свободному входу - тогда объект можно будет выбирать прямо в модификаторе ↓
Теперь проведём полученный атрибут в Shader Editor. Для этого в Shader Editor нам понадобится нод Shift+A > Input > Attribute
В нём мы указываем название атрибута, в точности, как назначили его в модификаторе Geometry Nodes, лучше для надёжности прямо скопировать оттуда ↓
Если всё было сделано правильно, то теперь, если подключить выход Vector полученного атрибута вместо Camera Rotation, то картинка не поменяется ↓
Это значит, что всё работает, и можно переходить к более сложным вещам. А именно к замене TC Offset, то есть сдвига текстурных координат, который сейчас высчитывается в драйверах с помощью специальной функции, написанной на пайтон в прошлых уроках. Чтобы держать расчёты перед глазами, откроем где-нибудь Text Editor, а в нём - текст скрипта, и перейдём в Геометрические Ноды ↓
Итак, нам нужны 3 объекта - источник света, камера и плэйн. Камера у нас уже есть, добавим таким же образом, с помощью Object Info, источник света и плэйн и сразу же подключим их в качестве входящих параметров, чтобы в случае необходимости определять сразу в модификаторе ↓
Чтобы избежать путаницы, сразу же назовём в N-панели, вкладка Group, все входы - Camera, Light Source, Plane
В скрипте мы определяли их в другом порядке - первым шёл источник света. Чтобы визуально соблюсти тот же порядок, поменяем местами Object Info с камерой и источником света и заодно изменим порядок входов, передвинув в N-панели Light Source вверх с помощью стрелочки  ↓
Также переназовём и сами ноды Object Info в N-панели, вкладка Node, графа Label, чтобы видеть, что к чему мы будем подключать. Это занимает совсем немного времени, но очень сильно поможет избежать ошибок. А их тут и так будет где наделать ↓ 
Для начала нам нужны два вектора: от камеры до источника света и от камеры до плэйна. Их мы получаем, вычитая координаты конечных точек из координат начальных точек с помощью Vector Math в режиме Subtract ↓
Дальше в скрипте мы вычисляли угол между векторами, для того, чтобы получить его косинус, который уже использовался дальше. Вычисления угла между векторами в Vector Math не предусмотрено, но нам его по большому счёту и не обязательно вычислять, потому что зная векторы, мы можем вычислить сразу косинус угла, не вычисляя сам угол. Для этого есть несколько формул на выбор, и на этот раз мы используем вот такую ↓
↑ Для таких же далёких от математики, как и я, людей поясню, что это скалярное произведение векторов, поделенное на произведение длин этих векторов. 
Скалярное произведение векторов в английском языке в целом и в ноде Vector Math в частности называется Dot Product, таким образом мы получаем верхнюю часть формулы ↓
Для нижней части формулы нам сначала нужно получить длины векторов - и для этого мы используем Vector Math в хорошо знакомом нам режиме Length - и потом перемножаем полученные длины с помощью обычного Math в режиме Multiply (умножение) ↓
Чтобы формула заработала, нам надо верхнюю часть поделить на нижнюю. Это мы делаем с помощью Math в режиме Divide (деление) ↓
Таким образом, мы получили косинус угла между векторами от камеры до плэйна и от камеры до источника света. Смотрим скрипт дальше. Чтобы получить длину гипотенузы прямоугольного треугольника между плэйном, камерой и проекцией источника света на плэйн, нам нужно разделить длину вектора от камеры до плэйна на этот косинус. Длина вектора b у нас - это самый нижний Vector Math в режиме Length. Его мы делим на полученный ранее косинус угла с помощью ещё одного Math в режиме Divide ↓ 
Это мы получили длину гипотенузы - расстояния от камеры до проекции источника света на плэйн. Теперь нам надо разделить её на длину вектора от камеры до источника света с помощью Math > Divide, чтобы получить отношение расстояния от камеры до проекции источника света на плэйне к расстояния от камеры до самого источника света. И на это отношение мы и умножим сам вектор от камеры до источника света с помощью Vector Math в режиме Scale
Подробно это всё объяснялось в одном из первых уроков по Lens Flares и потом повторялось во время написания скрипта. Мне кажется, что если всё внимательно проанализировать, то даже и без них всё должно быть понятно.
Система готова. Реорганизуем ноды так, чтобы они занимали минимум места, и было видно, что к чему подключено. Подключим получившийся вектор к свободному выходу, чтобы использовать его в качестве атрибута ↓
В настройках модификатора Geometry Nodes зададим название атрибуту. Например, tc_offset
Откроем Shader Editor, продублируем нод Attribute с помощью Shift+D
В качестве названия атрибута скопируем название, которые мы задавали в модификаторе геометрических нодов ↓
Теперь, если всё было сделано правильно, то при переподключении этого атрибута вместо TC Offset, в котором то же самое высчитывалось в драйверах с помощью скрипта, картинка должна остаться такой же ↓
А это значит, что ноды Camera Rotation и TC Offset с драйверами, можно удалить (или перенести в рамку с архивом), а ноды с атрибутами переименовать в те же Camera Rotation и TC Offset
Да кстати и Texture Coordinate можно переименовать в Camera TC, чтобы мы могли спокойно их все закрыть с помощью H и реаранжировать, чтобы они занимали меньше места ↓
Поскольку все они имеют отношения к текстурным координатам, можно снова поместить всю эту связку в рамочку TC Coordinates (эх, переименую её правильно в следующем уроке, если не забуду). И у нас получится очень аккуратная схема ↓
Также имеет смысл не лениться и переаранжировать и промаркировать ноды, входы и выходы и в Геометрических Нодах ↓
Если вы решите удалить, а не архивировать, ноды с драйверами, которые высчитывали сдвиг координат с помощью скрипта, то можно отключить и исполнение самого скрипта при каждом запуске файла. Это, напомню, делается в Text Editor, меню Text, галочка Register
Итого вот что мы имеем после реорганизации ↓
По-моему в таком виде всё стало более читаемым и управляемым, как считаете?
Вы видите эти уроки, благодаря тем, кто забирает их к себе на стенки, рассказывает друзьям, знакомым, в сообществах, пабликах, чатах, коммьюнити. Без их поддержки развитие проекта было бы невозможным, и я благодарен каждому.
Со своей стороны выражаю большую благодарность спонсорам. Вы даёте мне возможность продолжать.
avatar
Жаль что так мало лайков и комментариев. Обажаю все что связано с геометрическими нодами. Еще раз большое спасибо за уроки.

Subscription levels

1-й уровень

$ 2,27 per month
1-й уровень

2-й уровень

$ 5,7 per month
2-й уровень

3-й уровень

$ 11,4 per month
3-й уровень

4-й уровень

$ 22,7 per month
4-й уровень

5-й уровень

$ 57 per month
5-й уровень

Максимальная поддержка

$ 114 per month
Максимальная поддержка
Go up