return (c1,c2,c3)[c]
Функция hexagon (шестиугольник) во многих отношениях похожа на функцию triangle (в конце концов шестиугольник - шесть треугольников, склеенных вместе). Следовательно, в ней применяется та же хитрость с вращением, но, вместо выбора цвета с использованием простой формулы, здесь всё несколько сложнее, и, следовательно, мы используем цветовую карту (выделено в предыдущем фрагменте кода). В основном, мы делим экран на горизонтальные и вертикальные полосы, и выбираем цвет, основываясь на том, в какую полосу мы попали.
Последняя часть магии - на последней строке нашего скрипта:
__node__ = Tilings
В текущей реализации Pynodes, Блендеру нужно это присвоение, чтобы идентифицировать класс в качестве нода. Наш нод появится в выпадающем меню скриптовых нодов как Tilings. Полный код доступен как tilings.py в файле tilings.blend вместе с примером нодовой сети. Некоторые возможные узоры показаны на следующем скриншоте:
Соответствующая нодовая сеть показана на следующем скриншоте. Заметьте, что мы не подключили никаких нодов к цветовым входам, но можно создать даже более сложные узоры, если мы это сделаем.
Если вы посмотрите внимательно на диагональные границы шестиугольного или треугольного узора, вы должны обратить внимание на некоторые артефакты наподобие лестницы, даже если oversampling был установлен на большое значение.
Сам Блендер достаточно умён, чтобы прилагать выбранный уровень anti-aliasing, например, к границам объектов, но в большинстве случаев текстуры на поверхности должны самостоятельно заботиться о наложении anti-aliasing. Встроенные текстуры Блендера, конечно, разработаны именно таким образом, но наши собственные текстуры, произведенные с помощью Pynodes, должны заниматься этим явно.
Существуют многочисленные математические методы, позволяющие уменьшить aliasing в сгенерированных текстурах, но большинство из них не так просто осуществить, или они требуют специфических знаний о способе генерации узора. К счастью, Блендер предоставляет нам опцию Full OSA (окно Кнопок | контекст Затенения | кнопки Материала | панель Links and pipeline). Если мы включим эту опцию, Блендер будет вынужден производить oversample с каждым пикселем в нашей текстуре в количестве, выбранном в кнопках рендера. Это дорогой вариант, но он позволит отделаться от эффектов aliasing без необходимости осуществлять специфические параметры фильтрации в нашем текстурном Pynode.
На нашем плиточном узоре мы ограничили цвета в минимальное число, которое нужно для различения каждой из соседних плиток. Но возможно ли нам назначать произвольные цвета, основанные на некоторой шумовой текстуре? Таким образом мы могли бы раскрасить рыбью чешую общим произвольным узором, раскрашивая каждую отдельную чешуйку однотонно.
Мы не можем просто подключить цветную текстуру к цветовым входам, так как это приведёт, может быть, к интересной модели, но каждая плитка не будет иметь однородной окраски. Решением будет модифицировать наш Pynode, чтобы производить уникальный вектор, который станет однородным в пределах любой данной плитки. Этот вектор затем может быть подключен к любой шумовой текстуре, которая принимает вектор на входе, так же, как делают все текстуры Блендера. Этот вектор используется нодом текстуры шума, чтобы указывать на единственную точку в произвольной текстуре, и таким способом мы можем произвести произвольно окрашенные, но однородные элементы.
Чтобы обеспечить такую функциональность, мы модифицируем наш код, удалив цветовые входы, и заменяя цветовой выход векторным выходом (не показано). Код в функции __call__() теперь должен будет производить вектор вместо цвета. Здесь мы покажем модифицированную функцию triangle (полный код доступен как tilingsv.py в файле tilingsv.blend):
def triangle(self,x,y):
y *= self.stretch
x,y = self.cos45*x - self.sin45*y,
self.sin45*x + self.cos45*y
if int(floor(x%2)) înt(floor(y%2)) ^ \
int(y%2>x%2) :
return [floor(x),floor(y),0.0]
return [floor(x)+0.5,floor(y),0.0]
Логика в основном та же, но, как показано на выделенной строке, мы возвращаем вектор, который зависит от позиции. Тем не менее, из-за операции floor(), он постоянен в пределах треугольника. Заметьте, что для альтернативного треугольника мы добавляем незначительное смещение; не имеет значения какое именно смещение мы выберем до тех пор, пока оно постоянно и производит вектор, отличающийся от других треугольников.