Визуализация списка женщин-лауреатов Нобелевской премии в виде кристаллов в 3d с использованием Vue, WebGL, three.js

в 19:11, , рубрики: Generative Art, geometry shader, glsl, javascript, scraping, shaders, vue, vuejs, WebGL, wikimedia api, визуализация данных, Работа с 3D-графикой

image

Год 1 | вдохновение

В этом месяце я очень долго пыталась определиться с датасетом и идеей для его обработки. Хотя я начала думать о нем еще в мае, по факту законить удалось только через 8 месяцев (черт, я плоха), а описать проект мне удалось еще спустя месяц (оу, я чертовски плоха).

Идея проекта пришла ко мне после просмотра фильма Безумно богатые азиаты. Мне очень понравилась актриса Мишель Йео, но идея оформилась только после того, как я прочитала больше о ней и узнала, насколько она была выдающейся и крутой. Это заставило меня задуматься выдающихся женщинах, о которых я понятия не имею. И вот — возникла идея как-то это визуализировать.

1 неделя | данные

После формирования концепции, возник следующий вопрос — как собрать необходимые данные? Я быстро пришла к идее использовать Википедию, попытаться спарсить “лучших” женщин оттуда. Я понятия не имела, как определить «лучших» (просмотры страницы? длина страницы? ссылки на страницу?). Хотя я посмотрела статью на The Pudding про визуализацию на основе данных википедии, я все еще не была уверена, что хочу двигаться в эту сторону. А еще мне очень не хватало свободного времени.

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

image

С этого момента я начала изучать разные методы использования API Википедии. Разобраться было непросто (я не была уверена, нужно ли мне использовать Wikidata или MediaWiki, — это те варианты, которые возникали при поиске «Wikipedia API» в Google), но, к счастью, уже упомянутая выше статья на Pudding помогла мне закрыть эти вопросы. Быстрый просмотр их репозитория wiki-billboard-data привел меня к выбору одного из скриптов с wikijs, и я могла просто воспользоваться этим пакетом.

Все, что мне нужно было сделать, это скопировать и вставить список знатных женщин-лауреатов в электронную таблицу и выполнить небольшое форматирование/чистку.

Один из самых важных уроков, которые я узнала о сборе данных — электронные таблицы отлично подходят для их очистки. Раньше я пыталась писать код для очистки данных, и это занимало у меня намного больше времени. Когда я собирала данные для проекта по Гамильтону, я буквально набирала запятые между каждой ячейкой в ​​строке в моем CSV — настолько я была глупа.

Затем я экспортировала электронную таблицу как CSV, потом использовала онлайн-конвертер, чтобы получить данные в формате JSON.

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

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

неделя 2 | скетч

Не буду врать, я так долго думала об этом проекте, что даже не могу вспомнить все идеи, которые у меня возникали в процессе. Все, что я помню, — это то, что я просматривала номинантов премии Information is Beautiful, когда решила, что мне нужно как-то выделить те записи, которые мне действительно нравятся в моих сохранениях. Это заставило меня осознать, что я должна лучше организовать свою доску на Pinterest, так как раньше я сваливала все мои идеи и видение на одну доску. В процессе чистки, я наткнулась на эту великолепную картину с кристаллами художника Ребекки Шаперон, которую я сохранила на будущее несколько лет назад. Почти сразу я поняла, что я хочу программно воссоздать их. Ведь было бы прекрасно визуализировать этих выдающихся женщин в качестве ярких разноцветных кристаллов?

image

Возможно, у меня были другие идеи до этого момента (да, очень возможно), но я не могу их вспомнить — идея с кристаллами подходила идеально.

После этого я продумала другие детали: размер кристаллов должен отражать влияние женщины — количество ссылок на ее страницу в Википедии. Число граней на кристалле будет сопоставлено с количеством источников в нижней части ее страницы (поскольку она «многогранна»), а цвет будет определяться категорией премии. Единственное, что мне пока было непонятно, — это как расположить кристаллы. Я долго думала, что мне надо просто выложить их в 2-х измерениях по x / y и заставить читателя прокручивать их.

А потом я приняла участие в семинаре Мэтта ДесЛориерса по креативному кодингу, где он преподавал canvas, three.js и WebGL. Семинар открыл мне концепт третьего измерения, и я сразу поняла, что собираюсь использовать год получения награды в качестве оси z. Далее один мой друг предложил сделать потоки-нити, связывающие тех, кто сотрудничал друг с другом таким образом, чтобы их положение тоже менялось в зависимости от этого (но в итоге у меня не было времени на реализацию этой идеи).

Вся концепция пришла ко мне так быстро и естественно, что я не сделала ни одного наброска в процессе. Я просмотрела свой блокнот, но там вообще ничего нет.

неделя 3 & 4 | кодинг

Это был отличный месяц для кодинга.

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

И вот однажды меня осенило (я не уверена, что послужило причиной), что я не умею думать в трехмерном физическом пространстве, как раз потому, что я постоянно работаю в плоском диджитальном формате. Если бы я смогла научиться работать с 3D в цифре, то смогла бы мыслить в объеме и в физическом мире. Я добавила three.js и WebGL вверх своего списка для изучения.

В конце октября я прошла семинар Мэтта по креативному кодингу и изучила основы three.js, введение в фрагментированные и вершинные шейдеры. Я выучила правило буравчика: используйте большой палец для оси X (увеличивается вправо), указательный палец для оси Y (увеличивается вверх, что противоположно SVG и canvas) и средний палец для оси Z (для увеличения экрана и приближения его). Я узнала, что WebGL работает не в пикселях, а в единицах (похожая ассоциация — футы или метры).

Затем в ноябре я вписалась в один конкурс по WebGL. Хотя я раньше не имела с ним дела, я надеялась, что дедлайн даст мне мотивацию, необходимую для завершения проекта. Я начала 1-го декабря и поставила себе цель делать чуть-чуть каждый будний день, пока не смогу дойти до чего-то презентабельного 23-го декабря (финал конкурса).

Сперва я прочла первые две главы Руководства по программированию на WebGL, в котором рассказывалось, как настроить WebGL. Затем я повторила свои знания по three.js. После я запустила блокнот из Observable, чтобы понять минимально-необходимые настройки для рисования чего-либо в three.js (рендерер, камера и сцена, а затем вызвать renderer.render(scene, camera) для отображения ). Мне всегда нравилось понимать самые основы работы кода, так что это было очень полезно.

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

image

А во второй день — кристалл (на который потребовалось две попытки, потому что в первый раз я налажала с математикой).

image

А потом, в конце концов, форма кристалла, который был у меня в голове.

image

Позже я поняла, что есть лучшие способы делать то, что я хотела (и на самом деле PolyhedronGeometry — это довольно утомительный способ делать это), но я была очень рада возможности попрактиковаться в координатах x / y / z в WebGL.

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

image

Следующей задачей стало научиться использовать фрагментный шейдер для окрашивания кристалла. Здесь мне пришлось немного отклониться от плана, потому что я не могла понять, как использовать glslify (узловая модульная система для GLSL, на которой написаны шейдеры, которые я взяла в качестве образца). Вместо этого я начала изучать различные инструменты компоновки/сборки, чтобы в конечном итоге развернуть свой код в Интернете. В конце концов, я решила использовать Parcel (вместо Vue CLI, который я регулярно использую последние полгода), потому что он имеет встроенную поддержку как Vue, так и GLSL.

Вот такой кристалл с наложением того же паттерна шума у меня получился.

image

Результат мне не нравился, поэтому я решила, что мне нужно больше узнать о шейдерах и использовании цветов в шейдерах. Именно в этот момент я обратилась к Books of Shaders Патрисио Гонсалеса Виво и, в частности, к главе «Shaping Functions». Я узнала о синусах, косинусах, полиномах и экспонентах — функциях, которые могут брать число (или набор чисел) и выводить на их основе другие. Я также узнала о смешивании цветов и о том, как мы можем взять два цвета, и не только получить новый цвет посередине между этими двумя, но также смешивать цвета в формате RGB и создавать совершенно новые на их основе. Если мы объединим это с функциями формы, то сможем получить градиенты и формы:

image
Эти были получены путем смешивания синего и желтого, а также изменения значений RGB в каждой позиции с помощью степеней, синусов, абсолютных значений, шагов и сглаживаний

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

image

Но результат мне не понравился по двум причинам:

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

Примерно в это же время я наткнулась на демо Bloom (эффект постобработки для создания свечения), и в нем были круглые, похожие на драгоценные камни объекты, которые выглядели довольно похоже на кристаллы, которые я и хотела получить:

image

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

Поэтому я заменила PolyhedronGeometry на SphereGeometry, установила высоту на 4 и ширину на свои данные, растянула фигуру, установив вертикальный масштаб в два раза больше по горизонтали, добавила jitter (дрожание) для каждой вершины, и у меня получились гораздо более интересные формы:

image

Теперь, когда я определилась с формами, настало время вернуться к цвету. На этот раз я использовала два цвета и смешивала их с функциями формы:

image
image
Мне нравится первый вариант — выглядит как картофель

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

image
Код для добавления нормалей сторон.

После этого я поигралась с двумя наборами градиентов: один для «гуманитарных наук» (мир, литература, экономические науки), а другой для «естественных наук» (физика, химия, медицина).

image

Затем занялась фоном. Я создала «пол» с помощью PlaneGeometry и случайного дрожания y-позиции каждой вершины (вдохновленной этой статьей из codrops), а также «небо», создав огромную сферу вокруг сцены. Я экспериментировала с тремя различными типами источников света: полусферой, рассеянным (чтобы создать для«неба» ощущение заката/восхода солнца), и направленным (чтобы отбрасывать тени от кристаллов на «пол»).

image

В конце я добавила «звездочки», которые визуализируют всех мужчин, которые выиграли премию за тот же период времени, а также аннотации для каждого кристалла и для десятилетий. Это было сложно, потому что с тем текстом, который у меня был, использовать TextGeometry было практически бесполезно. Решение, которое я нашла после поиска в интернете, — визуализировать текст в HTML5 Canvas, создать PlaneGeometry и использовать этот Canvas в качестве текстуры для заполнения PlaneGeometry. Очень интересный подход.

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

image

Вот ссылка на финальный результат на GitHub

И видео c демонстрацией результата:

Если вы хотите попробовать еще что-то или начать с более простых проектов:

Автор: degenerative.art

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js