Troika: Функция: добавление атрибутов индекса символов/слов/строк к геометрии текста.

Созданный на 11 февр. 2021  ·  18Комментарии  ·  Источник: protectwise/troika

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

Теоретически для этого можно использовать gl_InstanceID , так как мы используем создание экземпляров для четырехугольников глифов. И это своего рода работает: https://codesandbox.io/s/zealous-water-m8lzq?file=/src/index.js -- но gl_InstanceID доступно только в WebGL2, и, похоже, быть сломанным в реализациях ANGLE при использовании в функциях, отличных от void main . Так что это не реально использовать для этого прямо сейчас.

Вместо этого мы могли бы добавить наш собственный атрибут экземпляра, что-то вроде attribute float charIndex; , который просто содержит увеличивающийся индекс символа. Пользовательские шейдеры могли бы использовать это.

Я, вероятно, хотел бы сделать это функцией отказа, что-то вроде textmesh.includeCharIndexInShader = true , просто чтобы избежать создания этого дополнительного массива атрибутов, если он не нужен.

Самый полезный комментарий

У меня много работы по очистке, но у меня есть первоначальный POC из приведенных выше значений. Вот примеры использования различных пар index/total для изменения цвета во фрагментном шейдере:

charIndex / totalChars:
Screen Shot 2021-02-18 at 7 18 56 PM

charInWordIndex / totalCharsInWord:
Screen Shot 2021-02-18 at 7 19 01 PM

charInLineIndex / totalCharsInLine:
Screen Shot 2021-02-18 at 7 19 08 PM

wordIndex / totalWords: (выглядит очень похоже на charIndex/totalChars в этом примере, но есть небольшая разница)
Screen Shot 2021-02-18 at 7 19 16 PM

wordInLineIndex / totalWordsInLine:
Screen Shot 2021-02-18 at 7 19 22 PM

lineIndex / totalLines:
Screen Shot 2021-02-18 at 7 19 29 PM

Мне удалось получить все данные максимум из 3 униформ + 2 атрибута, что довольно хорошо. Я все еще хочу сделать их необязательными.

Все 18 Комментарий

Также возможно: wordIndex , lineIndex ...?

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

Правильно ли я предполагаю, что это также позволит изменять отдельные токены (символы, слова, строки) в шейдере фрагментов?

Правильно ли я предполагаю, что это также позволит изменять отдельные токены (символы, слова, строки) в шейдере фрагментов?

Вам придется передавать его от вершины к фрагменту как переменную, но да. :)

В кроличью нору мы идем ...

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

  • charIndex, totalChars
  • индекс слова, всего слов
  • lineIndex, totalLines
  • charInWordIndex, всегоCharsInWord
  • charInLineIndex, totalCharsInLine
  • wordInLineIndex, всегоWordsInLine

Мы хотели бы сделать все это добровольным и сделать некоторые умные упаковки, чтобы свести к минимуму количество новых атрибутов gsl, которые мы вводим. Мне нужно больше подумать об API для этого.

мы могли бы позволить пользователям выбирать ВСЕ из них с помощью флажков, поэтому

{
split: {слова: истина, символы: истина, строки: истина}
}

сделать умную упаковку

Не могли бы вы расширить это? мне интересно 👐

Мне нравится эта идея, позволяющая пользователям выбирать разделение(я).

Под упаковкой я просто подразумеваю, что мы не хотим добавлять 12 новых объявлений attribute float foo , иначе мы достигнем предела (я думаю, всего 16 атрибутов в webgl), но мы могли бы упаковать их максимум в 3 новых объявления attribute vec4 foo , а затем распаковать их в более привлекательные переменные float в шейдере.

О да, многое понятно, спасибо!

Должен ли charIndex включать пробелы при увеличении? Или просто увеличивать видимые глифы? Я склоняюсь к просто видимым глифам.

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

У меня много работы по очистке, но у меня есть первоначальный POC из приведенных выше значений. Вот примеры использования различных пар index/total для изменения цвета во фрагментном шейдере:

charIndex / totalChars:
Screen Shot 2021-02-18 at 7 18 56 PM

charInWordIndex / totalCharsInWord:
Screen Shot 2021-02-18 at 7 19 01 PM

charInLineIndex / totalCharsInLine:
Screen Shot 2021-02-18 at 7 19 08 PM

wordIndex / totalWords: (выглядит очень похоже на charIndex/totalChars в этом примере, но есть небольшая разница)
Screen Shot 2021-02-18 at 7 19 16 PM

wordInLineIndex / totalWordsInLine:
Screen Shot 2021-02-18 at 7 19 22 PM

lineIndex / totalLines:
Screen Shot 2021-02-18 at 7 19 29 PM

Мне удалось получить все данные максимум из 3 униформ + 2 атрибута, что довольно хорошо. Я все еще хочу сделать их необязательными.

Удивительно! Дайте мне знать, когда у вас будет готова тестовая версия 😄

Я искал функцию, к которой это могло бы обратиться. У меня есть куча 3-буквенных этикеток, чтобы наклеить на сферу. Я заставляю их всегда смотреть на зрителя и вношу коррективы, чтобы на экране они всегда были одинакового размера, независимо от масштабирования, применяемого в матрице просмотра или матрице моделирования.
Прямо сейчас я создаю один объект Text для каждой метки и применяю преобразование.
Я подумал, что мог бы добиться гораздо большей производительности, упаковав все метки в один текст и имея атрибут, указывающий положение на сфере каждой метки, чтобы выполнять правильные преобразования в вершинном шейдере.
@lojjic , ​​можете ли вы задокументировать, как создавать собственные шейдеры? Я думаю, что добавление атрибута не должно быть трудным, как и существующий метод setAttribute из BufferGeometry .

Другим вариантом, который я рассматривал, будет инстансный рендеринг, поскольку все мои метки состоят из трех букв. Но это наверняка потребует WebGL 2 и может быть слишком сложным, чтобы оно того стоило, по крайней мере, в начале.

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

  1. Перемещение логики вращения/масштабирования из JS на стороне ЦП в логику вершинного шейдера на стороне ГП.
  2. Этот _плюс_ объединяет несколько фрагментов текста в один вызов отрисовки

Во-первых, взгляните на этот комментарий , которого может быть уже достаточно для ваших нужд. Это также хорошая демонстрация того, как применять пользовательский шейдер, в основном просто назначая его как material . Я использовал для этого утилиту createDerivedMaterial от Troika, но вы можете аналогичным образом передать любой ShaderMaterial или материал с его собственными модификациями onBeforeCompile .

Что касается 2, я думаю, вы правы, вы можете отобразить один текст, а затем использовать атрибут _some_ для перемещения отдельных символов по вашей сфере. Новые атрибуты индекса char/word, описанные в этом выпуске, могут быть полезны, но я не уверен, что они вообще необходимы. Возможно, вы могли бы просто закодировать эти смещения в новый атрибут InstancedBufferAttribute, где каждый из его векторов содержит смещение для одного символа (геометрия текста представляет собой простой четырехугольник, экземпляр которого создается для каждого глифа, поэтому для каждого глифа будут выполняться дополнительные атрибуты InstancedBufferAttribute).

Мне интересно посмотреть, повезет ли вам это сделать!

@lojjic Вы правильно поняли. И код, который вы связали, делает 90% того, что мне нужно (1). Ваша демонстрация устрашающе соответствует моему варианту использования.
Если я могу попросить вас исправить мое понимание, вот как я вижу, что вы делаете:

  • mvPosition инициализируется положением опорной точки в пространстве модель-вид. Я предполагаю, что эта точка отсчета является точкой привязки. Это правильно?
  • position — это смещение от этой контрольной точки, и я предполагаю, что она имеет только ненулевые координаты x и y. (что заставляет меня думать, что вы можете пропустить вычисление z-компоненты шкалы?) (PS: Глядя на код вершинного шейдера рендеринга экземпляров, кажется, что можно повернуть текст, и в этом случае z-компонент не будет равен нулю)
  • Масштаб в каждом направлении восстанавливается в предположении, что блок 3x3 содержит только композицию масштабирования и поворотов.
  • Добавляется масштабированный position , и если z-компонента равна нулю, этот вклад сохраняет положение в плоскости, параллельной плоскости проекции.

Изменения для меня в этом коде для простого выполнения (1) будут в основном связаны с масштабированием и небольшим сдвигом координат, чтобы текст оставался за пределами сферы, которая у меня есть.

Вы тоже поняли 2. Однако я немного смущен при чтении кода. Я не понимал, что рендеринг текста уже является рендерингом экземпляра. Что меня смущает, так это то, что у вас есть GlyphsGeometry , производные от InstancedBufferAttribute , и все же Text является подклассом Mesh , а не InstancedMesh . Я думаю, мне нужно глубже покопаться в Three.js.
В противном случае, учитывая, что каждый символ является экземпляром, мне нужен был бы только атрибут с вектором для смещения position для каждого экземпляра глифа. Это правильно?

Мне пришлось немного отойти от этого, но вот краткое обновление статуса:

PR #109 выглядит довольно солидно с точки зрения сбора и демонстрации различных показателей. Я хочу, чтобы они согласились, но в остальном я доволен тем, что есть.

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

  • Четырехугольники текущего глифа
  • Общие границы блока
  • Информация о метрике шрифта, такая как базовая линия / восходящая / нисходящая линия, которую нельзя вывести из квадроцикла.
  • Другой?

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

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

@lojjic Просто хочу выразить свою заинтересованность в этой функции 😺

Я разрешил некоторые конфликты слияния с последним мастером здесь: https://github.com/canadaduane/troika/tree/char-indices .

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

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

Я думаю, что, как упомянул @lojjic , ​​мне понадобятся некоторые ограничения на слова. Или, по крайней мере, для меня, центр каждого слова.
Любое другое предложение о том, как сделать это иначе или о том, как получить этот центр?

https://flightlog-beta.vercel.app/circles?route=BRU-HER-ATH-IST-AMM-CAI-TUN-CMN-RAK-MAD-LIS-ZRH-GVA-NCE-CDG-DUS-FRA- MUC-LHR-LCY-LGW-DUB-HBA-SYD-MEL-CNS-KTM-DEL-BLR-COK-MAA-CMB-MLE-HKG-HND-NRT-KIX-ICN-GMP-MNL-DPS-JOG- CGK-SIN-KUL-PEN-LGK-BKK-SGN-HAN-LPQ-CNX-DOH-AUH-DXB-JNB-CPT-LVI-ZNZ-JRO-DAR-SSH-BUD-OTP-IPC-SCL-PMC- GRU-EZE-GIG-BSB-LIM-LPB-BOG-PTY-SJO-SJU-CUN-ACA-MEX-MTY-JFK-BOS-PHL-DCA-IAD-BWI-CLT-ATL-MSP-MIA-DFW- DTW-ORD-IAH-COS-DEN-PHX-SAN-LAX-SJC-SFO-SEA-PDX-YVR-YYZ-YUL-LGA-EWR-ASP-BNE-AKL-CHC-ZQN-VIE-SJJ-VCE- MXP-FCO-BCN-PEK-PVG-HNL-OGG-KOA-HIJ-RGN-PBH-TIP-AMS-CPH-SLC-CVG-GSP-TPE-ULN-PNH-VTE-ABQ-BUF-MCO-HKT- лей-

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

drcmda picture drcmda  ·  11Комментарии

arpu picture arpu  ·  43Комментарии

Ocelyn picture Ocelyn  ·  13Комментарии

asbjornlystrup picture asbjornlystrup  ·  7Комментарии

lojjic picture lojjic  ·  11Комментарии