Наверняка каждый из нас слышал про NFT токены. Не буду тратить ваше время и повторять порядком надоевшие фразы, типа «NFT – это уникальный шанс войти в историю искусства навсегда», «NFT – это мыльный пузырь, и он уже лопнул», «NFT это возможность стать миллионером за секунду» и т.д.

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

1. Трейты

Итак, пока мы пытались продвинуть нашу NFT коллекцию VoxelCrazyHead в массы, мне довелось познакомиться и пообщаться с большим количеством других создателей. В основном это были коллекции в формате 2D изображений, но были и 3D. Меня интересовали именно генеративные коллекции, то есть те, которые создаются путем сочетания нескольких составных частей, которые могут принимать разные значения. Эти составные части называют «атрибуты» или «Traits» (Трейты).

С помощью трейтов мы создаём вариативность получаемого персонажа (картинки). Примеры трейтов из нашей коллекции:

Например, возьмем трейт «emotion». Этот трейт определяет, какая эмоция будет у головы (внимание на выражение лица):

То есть первым делом мы определились:

1)      Какие будут трейты и сколько
2)      Какие значения будут у трейтов и сколько

В сумме у нас получилось 12 трейтов с 324 возможными значениями, что в результате дало нам 40 778 090 496 000 возможных комбинаций голов.

После этого мы создали 3d модели трейтов: головы, шапки, цепочки, прически, очки и т.д. Можно заметить, что у кого-то есть цепочка или очки, головной убор или сережка, а у кого-то и то и другое. Именно с помощью распределения трейтов мы определяем, у кого будет тот или иной атрибут, а также насколько редким он будет. Дальше мы провели ряд визуальных тестов, чтобы понять, насколько хорошо сочетаются атрибуты, их формы и цвета. Затем приступили к распределению процентовки трейтов. На примере очков:

Общее количество NFT в коллекции – 10 000.
Трейт «glasses» распределяем следующим образом:

1)      Персонажей без очков («glasses» = «None»): 7000
2)      Всего очков: 3000
3)      Всего моделей очков: 11

Мы распределили 3000 очков между их возможными моделями и получили, что самые редкие очки «biglineGLD» и «biglineSLV», их всего по 50 штук. Соответственно, головы с такими очками будут редкие, а значит дорогие. Количество очков модели «wayfarer» – 550 штук, значит эти очки самые дешевые:

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

Последняя колонка «DNA» обозначает ДНК, о ней я расскажу в следующей статье про генерацию общей таблицы.
Последняя колонка «DNA» обозначает ДНК, о ней я расскажу в следующей статье про генерацию общей таблицы.

Благодаря большому количеству комбинаций трейтов, ни одной одинаковой пары NFT в коллекции нет.

На этом этапе у нас было самое главное:

1)      3d модели составляющих частей
2)      общая таблица с описанием каждой головы

Осталось собирать головы и отправлять на рендер.

2.Houdini

Мы подобрались к основной части моего рассказа. Как выяснилось, многие создатели коллекций используют Blender. Но почему-то все, с кем я общался, ни разу не слышали о Houdini (даже удивительно). Сразу скажу, я никогда не работал в Blender и не могу рассуждать о его эффективности применительно к данной задаче. Но я работаю в Houdini и могу с уверенностью сказать – это отличный выбор в этом случае. Я не смогу в рамках статьи научить пользоваться Houdini, но постараюсь наглядно показать, насколько замечательный это софт и как великолепно он подходит для таких целей. Возможно, для кого-то это станет стимулом изучить эту программу.

Итак, у нас есть таблица, в которой каждая строка содержит информацию о составных частях каждой головы. Дальше отправляемся в Houdini.

Справа мы видим, как из разных частей собирается наша голова. В каждой ноде хранится своя геометрия:

Cap

головной убор

Hair

прическа

Head

голова

Glasses

очки

Earning

сережка

Chain

цепочка

Base

подставка

BG

бэкграунд (фон)

У нас всего 8 нод из которых собирается вся голова, но должно быть 12 трейтов. Почему так? Потому что в ноде HEAD идет сборка по 5 атрибутам. Давайте зайдем в ноду HEAD:

Самая верхняя нода EMOTION (1) отвечает за геометрию самой головы, то есть какую эмоцию мы выбираем. Наша голова показывает язык, а значит трейт «EMOTION» = «TONGUE».

Нода EYES_COLOR (2) применяет цвет к материалу глаз
Нода SKIN_COLOR (3) применяет цвет к материалу головы
Нода TONGUE_COLOR (4) применяет цвет к материалу языка
Нода TEETH_COLOR (5) применяет цвет к материалу зубов

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

Давайте сначала разберемся, откуда вообще нода берет ту или иную геометрию головы. Естественно, мы заготовили эту геометрию заранее. Сначала мы собрали общий сетап для «вокселезации» геометрии. Он работает следующим образом – мы загружаем любую 3d модель, подключаем к нашему сетапу и через 2 секунды получаем воксельную модель
геометрии. Магия Houdini! Вот как это выглядит:

Пример 1. Исходная геометрия
Пример 1. Исходная геометрия
Пример 1. "Вокселезированная" геометрия
Пример 1. "Вокселезированная" геометрия

При этом у нас остается полный контроль любых параметров, например размер вокселей, а следовательно мы можем устанавливать уровень детализации:

Пример 2. Исходная геометрия
Пример 2. Исходная геометрия
Пример 2. "Вокселезированная" геометрия - уровень детализации = 5
Пример 2. "Вокселезированная" геометрия - уровень детализации = 5
Пример 2. "Вокселезированная" геометрия - уровень детализации = 2
Пример 2. "Вокселезированная" геометрия - уровень детализации = 2
Пример 2. "Вокселезированная" геометрия - уровень детализации = 1
Пример 2. "Вокселезированная" геометрия - уровень детализации = 1

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

Теперь возвращаемся к вопросу «как нода узнает из какой папки загрузить геометрию?». Вспоминаем про нашу таблицу с описанием всех голов:

Нам осталось:

1) Импортировать данные из таблицы в Houdini
2) Применить полученные данные

Первым делом переводим таблицу в CSV – формат. Затем отправляемся в Houdini, создаем волшебную ноду «csvimport» и указываем путь к таблице:

Теперь кликаем правой кнопкой по ноде и «запекаем» её (забираем данные с таблицы):

В результате нода забирает данные о всех 10 000 голов из таблицы:

Кликаем скроллом на первую точку и видим, что в ней хранятся данные о первой голове!

Что сделала нода: создала внутренние атрибуты (переменные), в которые записала полученные данные. Мы получили массив данных о всех частях голов в следующем виде:

Column_0 : Название головы
Column_1 : Описание
Column_2 : ссылка на метаданные NFT-токена
Column_3 : Номер головы
Column_4 : Дата создания
Column_5 : трейт «Emotion»
Column_6 : трейт «Skin»
Column_7 : трейт «Eyes»
Column_8 : трейт «Tongue»
Column_9 : трейт «Teeth»
Column_10 : трейт «Hair»
Column_11 : трейт «Hat»
Column_12 : трейт «BG»
Column_13 : трейт «Base»
Column_14 : трейт «Earring»
Column_15 : трейт «Glasses»
Column_16 : трейт «Chain»
Column_17 : трейт «DNA»

Теперь мы можем использовать эти переменные и собирать головы перед отправкой на рендер. Осталось только добавить переменные во все ноды и немного подкорректировать пути. Например, при сборке самой головы мы укажем в ноде «EMOTION» следующий путь:

То есть мы будем забирать данные из column_5 и в каждом кадре подставлять значение в путь загрузки геометрии. Будет получаться так:

Номер кадра

Column_5

Column_6

Column_7

Column_8

1

smile

ligth_violet

blue

yellow

2

tongue

ligth_violet

red

red

3

neutral

salmon

green

cian

..

..

..

..

..

10000

smile

green

GLD

yellow

Естественно, мы не заготавливали и не сохраняли одну и ту же геометрию, если у нее менялся только цвет. В таком случае мы просто меняли её цвет указывая нужные данные в материале.

Осталось вставить нужные переменные во всех нодах, настроить рендер и отправить на просчёт!

Мы рендерили в нашей маленькой студии на четырех машинах Ryzen 5, 32 GB, GTX 1650. Рендер Karma XPU. Весь процесс рендеринга занял примерно 7-10 дней. Получили вполне достойное качество. После рендера добавляли небольшой шумодав, но без фанатизма, чтобы не потерять детали.

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

Если эта тема будет интересна, я продолжу написание подобных статей.

В следующей хочу рассказать, как мы генерировали и раскидывали трейты для коллекции, как собирали это в удобную таблицу. Будет немножко Python’а :-)

Спасибо за прочтение и реакцию!

Комментарии (15)


  1. Lev3250
    25.12.2022 21:22
    +18

    ИМХО, если бы просто написали, как вокселизировать модели, без приплетения осточертевшего NFT, статью восприняли бы благосклонно


    1. GbrtR
      25.12.2022 21:42
      +4

      В статье главное это ссылочка на нфт, это же невооружённым глазом видно.


    1. Alexrook
      25.12.2022 23:13
      +2

      Это тоже не требует написания статьи. Делаете облако точек на основе модельки - нода Points from Volume, если я правильно помню. Давно Houdini не открывал. На каждую точку вешаете куб - Copy to Point или что-то в этом роде. Связываете размер куба с установленным интервалом в облаке точек. И все. Можно эту идею как-то развивать и усложнять. Но сама базовая вокселизация модели в Houdini не представляет особого труда.


      1. Lev3250
        25.12.2022 23:24
        +6

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


    1. Arrivvaa Автор
      26.12.2022 00:06
      -6

      Возможно. Но весь смысл был рассказать, как мы применили Houdini в этой задаче. Да и не совсем понятно, лично мне, что вызывает такой лютый негатив при слове NFT). То есть можно написать какую-то очень полезную статью, но поставить «осточертелое» слово и становится не важна суть? Так получается


      1. vindy123
        26.12.2022 13:21

        Именно так и получается, представляете? :) Это как статьи от криптоцыган об алгоритмах блокчейна, или, если ещё немного докрутить, гипотетическая статья от Мавроди о методах подсчёта налички путем взвешивания коробок с кэшем, ну или там математической модели конверсии количества роликов МММ на федеральных каналах в количество коробок с кэшем у них в офисе.


    1. Dmitrii_DAK
      26.12.2022 05:46
      -2

      А что людям не нравится в слове "NFT"? Круто ведь придумали зарабатывать деньги


  1. v1000
    26.12.2022 09:58
    +1

    «NFT – это уникальный шанс войти в историю искусства навсегда», «NFT – это мыльный пузырь, и он уже лопнул», «NFT это возможность стать миллионером за секунду»

    а как-же про "NFT - это отмывание денег"? при том, что крайним вполне могут сделать самого создателя NFT.


  1. El_mario_che
    26.12.2022 11:40
    +3

    Однажды я ехал в поезде из Самары в Казань. Спать не хотелось был iPad и стилус. Я обвел фото высадки на Луну (с переосмыслением). Теперь это тоже НФТ.


    1. oisee
      26.12.2022 14:42

      <место для картинки "shut up and take my money">


      1. El_mario_che
        26.12.2022 18:32

        Налетай-торопись. Всего 12 долларов.


  1. RetardedWolfy
    26.12.2022 17:52

    Хороший NFT, но кто победит?
    Ваш NFT или мой Виндоус Шифт Эс


  1. hi_ppl
    26.12.2022 17:52

    А я считаю, что зря так заминусили. Да, NTF. И что с того? Как триггер к минусам на людях сработало, что не совсем объективно, я считаю. Это не делает статью хуже, а старания автора - меньше.


    1. hi_ppl
      27.12.2022 02:16

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

      Зачем минусить то так? В чем идея?


      1. Arrivvaa Автор
        27.12.2022 11:45
        +2

        Я думаю, что добрая часть заминусивших меня людей делится на три категории:

        1. Те, кто знают, что кто-то сделал коллекцию NFT и заработал на этом состояние. Кто-то проходит долгий путь, меняет работы, учит кучу материала годами, но даже близко не приблизился к тому количеству денег, как какие-то создатели коллекций, заработавшие миллионы на "простых картиночках". Вывод - простая человеческая жаба. Ты можешь быть сколь угодно умен и рассудителен, но какой в этом толк,если у тебя нет пару тысяч эфиринок на кошельке)))

        2. Те, кто обжегся об нфт. Кто-то попробовал купить, в надежде поднять деньжат, но не зашло. Коллекция не взлетела, деньги потерялись

        3. Те, кто вообще не понимает что такое нфт, но старается поддакнуть "уважаемым людям", что "ДА НАДОЕЛО ВАШЕ ЭТО НФТИИИИ!!!!!"

        Триггеры у людей не берутся откуда ни возьмись, этому что-то предшествует. Какие-то события, победы, неудачи и т.д.
        Результат: мне понизили карму очень сильно, теперь я не могу публиковать новые посты.Комментировать могу один раз в день. К чему это ведет? Естественно, я никогда больше не буду писать статьи на хабр. Зачем мне стараться, если меня могут заминусить просто люди, у которых психологические травмы, связанные с нфт или ещё чем-то? Получается, это не совсем то место, где делятся смыслом и опытом. Это место, где ты должен угодить аудитории, отвоевать своё право существовать на ресурсе, чтоб тебе разрешили! Ребят, ну я себя уважаю, зачем мне это всё) Всех благ, как говорится