Я рисую много прямоугольников, поэтому использую для этого WebGL2RenderingContext.drawArraysInstanced(). Я также использую множество буферов для управления шейдерами в каждом экземпляре (содержащими такие данные, как положение, цвета, состояние и т. д.). Теперь я хочу повлиять на порядок, в котором отрисовываются мои экземпляры (например, вывести на передний план экземпляр, на который нажал пользователь), и я ищу что-то вроде INSTANCE_ARRAY_BUFFER
, что-то похожее на ELEMENT_ARRAY_BUFFER
, но для экземпляров вместо вершины. Что-то, что позволило бы мне сказать «рисовать экземпляры в следующем порядке: 3,1,2,0,…». Есть ли какой-либо API, который позволил бы мне контролировать порядок отрисовываемых экземпляров, не изменяя порядок элементов всех буферов данных?
Основываясь на моих исследованиях, я подозреваю, что ответ будет «нет», но, возможно, я пропустил какой-то скрытый API WebGL. Кроме того, в качестве бонуса вопрос — было ли что-то подобное введено, возможно, в последних версиях OpenGL или WebGPU?
С GL_DEPTH_TEST вам не нужно заботиться о порядке рендеринга. Для каждого прямоугольника у вас должен быть параметр глубины. Затем вы можете манипулировать этим параметром, чтобы вывести прямоугольник на передний план.
@МатвейВислоух, который будет работать с фигурами, созданными только с помощью геометрии, но мы визуализируем фигуры с помощью шейдеров на основе SDF, применяемых к четырехъядерным спрайтам. Такие шейдеры позволяют нам иметь сверхгладкие кривые и плавное масштабирование всего. В таком случае использование буфера глубины нарушит наше сглаживание.
Ваш единственный актуальный вопрос
Есть ли какой-либо API, который позволил бы мне контролировать порядок отрисовываемых экземпляров, не изменяя порядок элементов всех буферов данных?
Да, поместите свои данные в текстуры, передайте массив идентификаторов в буфере
Несколько примеров, не только четверные здесь и здесь
Я понятия не имею, насколько быстрее или медленнее это будет. Моя интуиция подсказывает, что это будет медленнее, но я не проверял.
Мне было бы странно, что единственное, что вы оптимизируете, это порядок прорисовки, и что вам не нужно позиционировать все четырехугольники и изменять их UV. Если вам нужно расположить все четырехугольники и изменить их UV, то просто сначала запишите их в правильном порядке.
Другие комментарии на основе комментариев
Являются ли экземпляры лучшим способом рисовать много квадов?
Я думаю, что вердикт здесь не так однозначен. 10 лет назад по моему опыту создание экземпляров было на 30% медленнее, чем просто создание данных для всех квадроциклов. Мои тесты показывают, что это уже не так, по крайней мере, ни на одном из моих графических процессоров, ни в WebGL.
Является ли запись 4 или 6 вершин в буферы на квадрат хорошим решением?
Для пользовательского интерфейса обычно просто записывают все данные в буферы в каждом кадре. См. почти все библиотеки ImGUI
Спасибо за удивительный ответ, как всегда! Что касается позиционирования и UV-развертки — я вычисляю их в вершинном шейдере, но наша структура графического интерфейса изменчива, и поэтому мы изменяем только подмножество компонентов при взаимодействии с пользователем. Ваше решение с текстурами потрясающее. Однако, если я правильно понимаю, это потребует от меня перераспределения новой текстуры со всеми параметрами (и удаления старой) при каждом создании нового компонента, верно? (поскольку текстура будет содержать значения для всех «экземпляров»). (Конечно, я могу перераспределить немного больше для оптимизации)
Я недостаточно знаю о том, что вы делаете, но вы можете выделить текстуру большего размера, чем вам нужно, и управлять пространством внутри (аналогично тому, как std::vector в C++ выделяет больше памяти, фактически используемой массивом)
О, я не знал об этом! Я был уверен, что распределение текстур просто слепо занимает место в памяти GPU. Удивительно знать это, спасибо!
@httpdigest спасибо за ссылку. Я использую квадроциклы для отображения элементов пользовательского интерфейса и часто меняю атрибуты для каждого экземпляра. Судя по вашей ссылке, я вижу 3 арки: (1) То, что у меня есть сейчас (экземпляры рендеринга). (2) Нет экземпляров, проиндексировано гео, но требуется установка атрибута 4 раза для каждого «экземпляра». (3) Нет экземпляров, нет индексированного гео, но требуется установка атрибута 6 раз для каждого «экземпляра». Арка 3 могла бы решить мою проблему, так как тогда мы могли бы использовать
ELEMENT_ARRAY_BUFFER
для сортировки, но тогда установка атрибутов была бы очень медленной. Конечно, мне нужно их скамейке. Тем не менее, я не был бы рад замедлить настройку attr.