Зимой 2021 года мой старый коллега Тоби Эглсфилд (https://twitter.com/notyetmeasured) связался со мной и предложил сотрудничать в проекте NFT. Немного предыстории: раньше я был художником в компании по производству видеоигр, а Тоби был ведущим художником в моей команде. Много лет спустя я сменил карьеру на инженера-программиста, а Тоби эмигрировал в Новую Зеландию, где сейчас работает внештатным дизайнером/преподавателем. Мы поддерживали связь на протяжении многих лет, но счастливая случайность и растущий рынок NFT свели нас вместе. Тоби будет обеспечивать художественное вдохновение, а я позабочусь о кодировании.

Валютный хэш

Тоби был очень активен в различных сообществах NFT tezos, таких как hicetnunc (теперь OBJKT) и teia, и изучал новую платформу на основе tezos, FXHash. Сообщество FXHash в основном сосредоточено на процедурном/генеративном искусстве, но у Тоби было несколько интересных идей о создании проекта PFP (изображение профиля), в котором использовались некоторые возможности платформы.

Мы решили назвать проект Физзоги, сокращение от слова физиогномика. Тоби создал коллекцию активов с действительно отличительным стилем и палитрой. Вот пример одного из них ниже:

Настройка проекта

Первое, что мне нужно было сделать, это создать среду разработки. К счастью, у команды FXHash есть удобный шаблонный проект веб-пакета:



Тоби предоставил набор ресурсов SVG, которые можно использовать для создания изображений из слоев. Было по 18 ассетов для туловища, головы, волос, носа, бровей и рта. Кроме того, было 11 уникальных выражений лица, которые можно было переворачивать по горизонтали, а также 32 цветовые палитры.

Следующей задачей было выбрать эти элементы, чтобы составить из них лицо. Недостаточно было просто случайным образом выбрать изображения, так как это привело бы к недетерминированному результату, что нарушило бы контракт, требуемый FXHash. Шаблонный проект выше предоставляет утилиту — fxrand — для получения случайных значений. Это возвращает целое число с плавающей запятой от 0 до 1. В локальной среде это значение всегда является случайным, но когда проект развернут, значения, возвращаемые этой функцией, становятся детерминированными, гарантируя тот же результат в токене. Хитрость заключалась в том, чтобы использовать это плавающее целое число для выбора из приведенных выше вариантов. Первоначально я написал свой собственный метод, который квантовал бы это значение в диапазон для выбора, но опять же, сообщество FXHash решило эту проблему и предоставило библиотеку методов для выбора параметров или генерации значений:



Вы можете увидеть пример кода, который я написал с помощью этой библиотеки для выбора файлов svg ниже:

В приведенном выше фрагменте вы можете видеть, что я делаю различие между получением заблокированного или динамического варианта. Это было сделано для того, чтобы я мог заблокировать выбранный файл во время разработки, передав различные параметры отладки.

Рендеринг

Как только я смог выбрать активы и палитру, мне нужно было найти способ их рендеринга. Я просмотрел ряд библиотек SVG, включая paper.js, Snap.svg и SVG.js. В конце концов я решил использовать two.js, так как он был легким и имел активное сообщество. Two предоставляет простой метод загрузки ресурсов SVG в сцену — вот пример того, как я использовал его с параметрами, выбранными в предыдущем фрагменте:

Позиционирование и векторы

Когда все элементы лица размещены правильно, мне нужно было применить смещения к элементам, чтобы расположить их в соответствии с загруженным выражением. Одна из интересных вещей, которые я обнаружил при работе с SVG, заключается в том, что координатное пространство родителя не распространяется на его дочерние элементы. Например, возьмите SVG ниже.

Я масштабировал родительский элемент в процентах, чтобы он соответствовал размеру поля 800 x 800. Однако, когда позже мне понадобилось проникнуть внутрь этого, чтобы манипулировать одним из дочерних элементов, они вели себя так, как будто все еще находились внутри пространства 2048 x 2048.

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

Анимация

Когда все ресурсы загружены и расположены правильно, пришло время применить анимацию к элементам. Это был, безусловно, самый трудоемкий этап в создании этого проекта. Тоби создал соответствующую анимацию для каждого элемента, который нужно было закодировать вручную. Я решил использовать tween.js в качестве библиотеки анимации — так как на сайте two.js были рабочие примеры.

Это поставило передо мной следующую задачу при работе с SVG. Для многих анимаций требовалось, чтобы исходная точка SVG была смещена от центра. Некоторые из библиотек SVG ранее предоставляли средства для этого, но two.js, будучи настолько легким, требует, чтобы вы делали это вручную. Техника включала изменение положения вершин элементов в SVG, а затем перемещение всего SVG обратно в исходное положение. Для этого я написал утилиту, которая позволила мне указать точку компаса, чтобы зафиксировать исходную точку:

Обратите внимание, что мне нужно было получить ограничивающий клиентский прямоугольник svg перед вызовом el.center(). Это было сделано для предотвращения «повреждения» значений, возвращаемых этим методом.

Наконец, мне нужно было определить ключевые кадры в tween.js, что включало создание новых твинов и объединение их в цепочку. Я решил использовать проценты от глобального бюджета кадров, что означало, что мы могли настроить продолжительность анимации, чтобы сделать ее короче или быстрее, если нам нужно. Вы можете увидеть пример анимации для одной из голов ниже, которая вызывает утилиту репозиционирования выше:

По большому счету, анимация была довольно простой, но некоторые ее аспекты требовали от меня освежить в памяти мой триггер, чтобы определить траекторию или точку вращения элемента в сцене.

Функции

Последним штрихом было определение объекта «features» для токена. Это способ передачи метаданных о проекте в FXHash, чтобы он мог сказать, как часто использовалась конкретная функция проекта и, следовательно, ее редкость. Например, в нашем проекте у каждого из основных элементов было 18 вариаций — поэтому мне нужно было сообщить, какой из них был загружен в сгенерированном токене.

Мы могли бы просто объявить, какой пронумерованный вариант был загружен, но мы оба подумали, что это немного сухо. Поэтому вместо этого мы решили дать каждому отдельному элементу псевдоним, что добавило еще одну возможность для творчества. Мы также объявили мимику с уникальными «настроениями», такими как «Чиппер» или «Борьба».

Наконец, я создал псевдоцепочку ДНК для конкретной комбинации элементов, которые использовались для лица — «шипения», если хотите. Это включало выбор 1–18 из строки чередующихся согласных и гласных для создания строки. Таким образом, для туловища № 7, лица № 9 и волос № 12 вы получите цепочку ДНК «J-O-P».

Примечание по тестированию

Да, об этом. Для инженера-программиста выпускать что-то в производство без тестов — все равно, что прыгать с самолета без парашюта. Так что с тяжелым сердцем должен признаться, что ничего не писал. Не суди меня!

Однако, за исключением пары служебных функций, большая часть работы выполнялась библиотеками, поэтому тестирование в значительной степени включало бы много насмешек без особой пользы. Настоящая суть проблемы заключалась в вероятностной природе среды — как проверить то, что имеет встроенную случайность?

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

Вы можете увидеть скриншот вывода ниже.

Скриншот

Последней задачей перед завершением проекта было предоставление пользователям простого способа захвата изображений с монетного двора. Это относительно простая задача при использовании холста, поскольку вы можете просто вывести данные изображения с холста, но с SVG это не так просто. Two.js имеет режим рендеринга холста, который я пытался использовать, но, учитывая, что мы использовали режимы смешивания и смешивания в CSS, он был потерян при рендеринге. Затем я попытался применить режимы микширования непосредственно к холсту во время отрисовки, а не через CSS. Это почти сработало, но каждая последующая фигура в слое смешивалась сама с собой, создавая эффект перекрытия, а не сплошные цвета, которые вы можете видеть в существующей работе.

К счастью, NPM предоставляет — и я нашел _другую_ библиотеку, которую я подключил к нажатию клавиши, которая сделала свое дело: https://www.npmjs.com/package/dom-to-image

Отражение

В то время, когда мы начали этот проект, рынок NFT переживал что-то вроде золотой лихорадки, которая с тех пор рухнула вместе с остальным рынком криптовалют (на данный момент…). Однако ни у кого из нас не было реальной финансовой мотивации при создании этого проекта, иначе мы, вероятно, развернули бы проект на более заметной или прибыльной платформе, такой как Opensea. Мы сделали сознательный выбор, чтобы не использовать популярные платформы проверки работоспособности из-за их энергопотребления (учитывая мою повседневную работу в компании по устойчивой энергетике, это не отмывается!).

Сообщество tezos NFT отличается андерграундной атмосферой, мощной смесью людей из разных слоев общества. Это панк, аутсайдер, сырой. Тот факт, что искусство, которое они создают, находится на блокчейне, стал второстепенным по отношению к возникшему движению.

Настоящей мотивацией было создать что-то с использованием этой новой технологии и принять участие в растущем сообществе программистов и художников, работающих в этой области. Сфера генеративного искусства требует уникального сочетания навыков программирования и художественного самовыражения — и очень интересно наблюдать, как участники развиваются в своем использовании и понимании среды, сегодня делятся алгоритмами, а завтра — художественным вдохновением.

Лично это был отличный опыт, который потребовал от меня более глубокого изучения таких предметов, как тригонометрия, статистика и вероятность. В рамках проекта возможно около 28 миллиардов возможных уникальных комбинаций, но вероятность того, что вы увидите какой-либо заданный элемент в проекте, составляет 1 из 18. Мы думали добавить еще несколько пасхальных яиц, если вы выбрасывали уникальную комбинацию, но решили оставить некоторые из этих мыслей на другой день. Сам акт совместной работы создавал проблемы, учитывая, что мы находимся на противоположных сторонах планеты, что приводило к лихорадочным полуночным чатам или зевающим зум-звонкам на рассвете, чтобы сгладить ошибки и обсудить функции.

Это также была возможность лучше понять экосистему NFT/блокчейн и изучить различные движения и художников, которые заняты работой в глуши, создавая некоторые увлекательные цифровые артефакты.

Но самое главное, мне удалось создать крутой арт со старым другом.

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

Посмотреть проект Fizzogs можно здесь: https://www.fxhash.xyz/generative/14239

Вы можете найти наши профили в Твиттере здесь: strictequals и measureless.