Альфа-смешивание с целочисленной текстурой для выбора объектов - PullRequest
5 голосов
/ 21 апреля 2020

Описание проблемы

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

Подробности

Формы определены с помощью Подписанных функций расстояния . Каждую фигуру рисуют, применяя предварительно определенный фрагментный шейдер sdf к квадратному многоугольнику (2 треугольника). Каждой фигуре присваивается уникальный идентификатор (uint) на стороне Rust (здесь мы используем WASM). Идея состоит в том, чтобы визуализировать сцену дважды (в WebGL 1.0) или один раз для нескольких целей рендеринга (в WebGL 2.0), где одной из целей будет идентификатор, закодированный как цвет. Затем мы можем использовать readPixels, чтобы запросить цвет и получить идентификатор фигуры под мышью. К сожалению, у каждого решения, которое мы пробуем, есть свои недостатки.

Требования

  • Нам нужно кодировать 2 дюйма на форму (один, чтобы сказать нам, какая это была форма как если бы это была кнопка, или, может быть, ползунок), а во-вторых, чтобы сказать нам, какой это был объект (например, 5-й ползунок).
  • У нас будет много фигур (и экземпляров) на stage, поэтому для каждого типа int нам потребуется как минимум 24-битная, предпочтительно 32-битная точность.

То, что он пробовал до сих пор

  • Отображение идентификационной информации в RGBA32UI тип текстуры. В этом решении мы используем 32 бита на канал, поэтому мы можем использовать 2 канала для представления наших идентификаторов. К сожалению, смешивание применяется только в режиме RGBA и только в том случае, если цветовой буфер имеет формат с фиксированной или плавающей точкой. Нам нужна некоторая форма смешивания, потому что при рисовании фигур, таких как круги, некоторые части должны быть прозрачными. В случае вывода цвета идентификатора наша альфа всегда равна 0 или 1.
  • Отображение информации идентификатора в RGBA текстуру и преобразование uint в float в GLSL с использованием intBitsToFloat и затем обратно float до uint в Rust. К сожалению, это доступно в GLSL 330, и мы ограничены GLSL 300 в WebGL.
  • Отображение идентификационной информации в RGB32UI текстуру и использование discard для некоторых пикселей. Это будет работать, но может вызвать проблемы с производительностью, и мы бы не хотели использовать его.
  • Преобразование информации идентификатора на стороне Rust в float, использование ее вместо uint и рендеринг в RGBA текстуру и преобразование ее обратно в uint на стороне Rust. Проблема этого решения в том, что оно довольно сложное, мы не можем использовать все 32-битные (мы должны быть особенно осторожны с возможным NAN-кодированием), и мы считаем, что должен быть лучший способ сделать это.

1 Ответ

1 голос
/ 21 апреля 2020

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

С spe c В разделе 4.1 перечислены 9 операций, которые происходят с пикселем / фрагментами.

В разделе 4.1.7 Смешивание, которое является операцией 7 из 9 операций, говорит:

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

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

Вместо этого может просто discard фрагмент, если значение альфа ниже заданного порога.

if(alpha < 0.5) discard;
output_id = uvec4(input_symbol_id,input_instance_id,0,1);
...