Blender 3: шестиугольные структуры из камня с помощью geometry nodes
Автор: wayerrВесьма простая задача, чтобы разобраться в geometry nodes Blender 3. Эту же технику можно применить для моделирования сот, если убрать искажение. Если заменить шестиугольники на кирпичи, то можно сгенерировать стену и т.п.
Вся цель блендеровских нод (здесь и далее я буду называть geometry nodes просто "ноды"), в том чтобы автоматизировать многие рутинные операции. Сегодня мы простую поверхность автоматизируем в нечто сродни вот этому:
Это я делал раньше подобным описанному, но чуть более сложным и кривым способом.
Итак, для начала нужен blender версии 3.1 он пока в бета статусе (вероятно, сгодится и 3.0). Замечу, что ноды весьма коварны в том плане, что могут выжрать всю оперативку (у меня оной 32гб) и затем уронить блендер или весь комп. Происходит это не из-за ошибок, а потому что, крутя какие-нибудь параметры, где-то один не очень большой размер разделился на другой околонулевой размер, и как следствие сгенерировалось несколько миллиардов объектов... точнее попыталось. Потому не забывайте регулярно сохранять проект, делать резервные копии и всё прочее.
Итак, создаём простенькую поверхность, разбиваем её на полигоны, потом вручную задаём базовый рельеф (не будем же мы плоский пейзаж делать?).
Затем добавляем модификатор нод, а в нём добавляем ноды как на скриншоте ниже. Получается что-то такое:
Базовая поверхность здесь серая - на неё добавлен модификатор нод. А всё что создают ноды для наглядности отображено зелёным (это делается специальным материалом и нодой "set material" ).
Здесь мы вычисляем размеры исходной поверхности и генерируем новую (зелёным) поверхность с заданным числом вершин. Это нужно потому что в дальнейшем по вершинам зеленки мы будем расставлять столбы-шестиугольники (далее просто "столбы") - и нам надо чтобы вершины у неё были точно на одинаковом расстоянии (в исходной поверхности вершин стоят как угодно), иначе столбы будут перехлёстываться или стоять с щелями.
Отмечу, что min и max надо поменять местами, т.е. от max отнимать min, оно пока и работает, но местами будет неожиданно.
Следующим этапом к группе стоит добавить входные параметры (указанный интерфейс вызывается клавишей N в редакторе нод), в данном случае высоту и ширину столба. Тут неплохо бы указать минимальную границу отличную от нуля. Как показала практика 0.001 - всё же маловато и столбов оказывается многовато, потому лучше указать 0.1
Теперь добавляем столбов:
Зелёным фоном обведены добавленные ноды. Тут пока всё просто, как в большинстве туториалов по нодам. Единственно, что стоит заметить, не точки размещаются случайно по поверхности, а вершины поверхности превращаются в точки - это штатный способ создать сетку объектов.
На этом этапе я объединил ноды, вычисляющие размеры, в подгруппу (у неё название 'get-size', далее на скринах она будет под ним). Обратите внимание, тут уже min и max указанны в верном порядке:
Потом творилась некоторая магия, итогом которой стала ещё одна группа нод (название 'calc-grid'):
Здесь берётся один размер плоскости и один размер столба и вычисляется сколько целых (потому и нужна 'ceil') столбов в этот размер поместится. Так как размеров два (ширина и глубина - x, y) то эту штуку придётся вызывать два раза. Единичка прибавляется, так как считаются промежутки между вершинами (по ширине, к примеру), а вершин (по ширине) на одну больше.
Потом полученные группы надо соединить хитрым образом:
Добавленные ноды (в данном случае вышеупомянутые группы) на зелёном фоне. Мы вычисляем размеры (ширину и глубину, высота нам пока не интересна) входной поверхности и нашего столба. У столба мы задали изначально задавали радиус, так вот, он может не равняться ни высоте ни ширине шестигранника (лень проверять), потому надёжнее взять его размеры.
Как видно, поверхность успешно замостило столбиками, но они же должны стоять со смещенеим на половину ширины. Это просто:
Добавляем set position, который "включается" (параметр selection) через один. Для наглядности я смещаю по высоте, а не как надо.
Замечу, так как тут сделано (index/2) работает только для чётного числа столбов в ряду. По хорошему надо index делить на число столбцов в ряду (ещё надо выяснить по X идёт ряд или по Y) и от него считать чётность. Но мне было лень разбираться 8).
Однако, есть проблема важнее. Сместить то мы сместили, но вдоль плоской грани, а надо чтобы смещали ребристой. Тут опять таки либо надо искать другой способ, либо лениво повернуть столбец по Z на 90°:
Для этого достаточно добавить transform сразу после cylinder.
Теперь смещаем ряд на половину ширины:
Здесь добавленные элементы выделены. В том числе X размер столбца, который делится напополам и т.п.
Чтобы убрать промежуток между столбцами, надо сократить их вычисленный размер на четверть:
Это требует всего пары нод между выходом Y размер столбца и входом вычислениея размера сетки.
Собственно вот уже есть шестиугольная сетка, для каких-то задач этого может хватить. Но нам надо повторить заданный поверхностью рельеф. То бишь, Z координата нужна. Делаем set postion для точек, пред тем как подавать их на вход instance on points:
Для этого на вход geometry proximity ноды подаётся исходная плоскость, которую мы вручную искажали для рельефа. Считается расстояние до точки и этим заменяется исходная позиция точки (про то, почему нода position здесь именно позиция точки, а не какая-то иная - стоит прочитать документацию блендера, т.к. это долго объяснять). Иными словами, X и Y у нас берутся от сгенерированной сетки, а Z от исходной.
Чтобы не колдовать с separate/combine XYZ нодами, я лентяйски совмещал координаты простыми векторными операциям.
Так как рельеф немного торчит через столбы, то стоит вспомнить, что они размещаются серединой в точке. Т.е. там снизу ещё половина высоты. Значит стоит немного скорректировать положение столбов:
Используется для этого всё та же нода transform которой мы поворачивали столб. Только теперь используется ещё и вход translation.
Почти всё готово. Осталось теперь ввести шума, столбы же каменные, вроде как природные, а не штампованные:
Тут начинается пара магических нюансов.
Во первых мы используем realize instance. Это "тяжёлая" нода. До того у нас был один столб, пусть и в разных местах. Его можно было покрутить, но искажать его бесполезно (точнее эффект будет не тот что надо), потому чтобы каждый столб искажать уникальным образом придётся их все "реализовать". А это сильно увеличивает размер сцены. Так как теперь у нас будёт куча реальных столбов, а не виртуальных копий. Короче, стоит проверить, сохранён ли проект, и сделать бэкап.
Во вторых мы беспардонно преобразуем цветной шум в координаты. Что тут такого? Ничего особенного. Только цвает всегда имеет положительное значение, а шуму координат неплохо бы болтаться от -1 до +1 Потому здесь используется map range. Ну и -1 да +1 может нас не устраивать, потому затем нужен scale.
Парочка оставшихся нод просто сглаживают шум через subdivision (параметр crease влияет на гладкость), и внешний вид нормалей.
Так как исходная фигура называется cylinder, то она и сглаживается в цилиндр. (О чём я традиционно вспомнил уже в конце.) А нам этого совсем не надо. Чтобы придать фигуре шестигранности, её можно чуть subdivide в самом начале (обратите внимание, что тут разные ноды с похожим названием):
Осторожнее с параметрами level - большие значения могут сделать грустно даже не слабому компьютеру.
Ну и итог:
Это с включённым microdisplacement, если что.