Есть ли предел вершин в WebGL?
Three.js говорит, что не может быть загружено более 65 тыс. вершин.
В моем чистом webgl-приложении он ничего не говорит, но при попытке больших объектов не показывать весь объект.
Я выясняю, как разделить мои объекты на меньшие буферы, но мне было грустно. Есть ли лучшее решение? Действительно ли 65k предельное количество вершин?
Ответы
Ответ 1
Да, буферы индекса вершин WebGL ограничены до 16 бит прямо сейчас. Это связано с тем, что они нацелены на то, чтобы сделать версию 1.0 максимально возможной кросс-платформенной, так что существует тенденция к тому, чтобы сделать объект наименьшим общим знаменателем - в таких случаях, как мобильные платформы с ограниченным графическим оборудованием.
После того, как 1.0 вышел, и начальная лихорадка закончилась, они, вероятно, ослабят эти ограничения с помощью расширений - приложение сможет спросить, поддерживается ли данное расширение реализацией, и использовать это если это так - как в обычном настольном OpenGL. Есть уже несколько расширений, но опять же они разрешили только те, у которых очень широкая аппаратная поддержка, поэтому ничего, что могло бы помочь вам увеличить количество вершин. Однако, как только они ослабили кросс-платформенное требование, они, вероятно, будут поддерживать что-то вроде расширения GL_OES_element_index_uint, которое допускает 32-битные индексы вершин.
Вы можете прочитать некоторое обсуждение этих проблем в списке рассылки Public WebGL.
Ответ 2
Как правило, другие ответы верны, но я решил, что добавлю немного разъяснений:
Единственными типами данных, принятыми WebGL (и OpenGL ES 2.0) для индексов, являются неподписанные байты и неподписанные шорты. Поскольку число без знака имеет диапазон 0-65535, это означает, что если вы используете gl.DrawElements(что делает большинство фреймворков), вы можете ссылаться только на 65k вершин на призыв на призыв. Это почти наверняка связано с ограничением three.js. Обратите внимание, что вы можете иметь более чем 65k треугольников в один призыв к призыву, если они имеют только 65 тысяч вершин.
Если вы используете неиндексированную геометрию (gl.DrawArrays), у вас может быть намного больше вершин за звонок, но имейте в виду, что почти всегда приходится повторять некоторые из них. Я думаю, что в большинстве случаев сокращение использования памяти GPU будет оправдывать разделение вызовов обратного вызова.
Ответ 3
На данный момент вы можете разделить ваш большой объект на несколько сегментов 65K элементов каждый и переиндексировать каждый сегмент, чтобы все сегменты имели индексы от 0 до 65K. Я тестировал его, и WebGL позволяет это.
Теперь вам нужно будет размонтировать те вершины, которые разделены между сегментами. В этом случае самой простой альтернативой является дублирование этой вершины, так что больше нет разделенных вершин. Но есть больше альтернатив, связанных с памятью.
У меня есть небольшая демонстрация этой рабочей (мозговой модели с вершинами приблизительно 350 К, разделенной на 5 сегментов) http://youtu.be/AXZiNHkMpZs#t=2m33s
Я надеюсь, что это поможет; -)
Ответ 4
Поскольку я не могу комментировать Giles, я помещаю этот комментарий здесь:
OES_element_index_uint добавлен в "Обновленные WebGL-расширения сообщества"!
Расширение уже включено в хром канарейке.
http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/
Ответ 5
Вы можете нарисовать вершины, используя drawElements
(который пересекает массив индексов в массив вершин) или drawArrays
, который напрямую пересекает массив вершин.
Кажется, нет никакого ограничения на количество вершин в буфере атрибутов при использовании drawArrays
. Использование drawArrays
возможно менее желательно, потому что для типичной сетки вам нужно указывать каждую вершину каждый раз, когда она появляется в примитиве. С другой стороны, в зависимости от вашей сцены это может быть простым способом сокращения количества вызовов WebGL.
Я упоминаю это только потому, что после прочтения этого вопроса и его принятого ответа я долгое время предполагал, что число вершин в drawArrays
также ограничено 65K. Случайно я обнаружил, что это не так, и закончил тем, что получил большое ускорение, объединив объекты с общими материалами в одиночные вершинные массивы (таким образом, обойти накладные расходы на каждый буфер, которые в настоящее время несут нагрузку на реализации ANGLE).
Ответ 6
Насколько я знаю, это обычно ограничивается аппаратным и/или программным обеспечением драйвера (аппаратное обеспечение использует 16-разрядные индексы или такие). Возможно, Three.js просто играет в безопасности и пытается убедиться, что ваше webgl-приложение работает на всех карточках. Вероятно, лучший способ - разбить ваши модели на более мелкие куски, это позволит убедиться, что ваше приложение поддерживает большинство, если не все графические процессоры, используемые сегодня.
- Используя instantiatemode (glBegin... glEnd), нет никаких ограничений в количестве вершин, которые вы можете пропустить, но это будет медленным с множеством вершин.
- Вы можете попробовать с помощью glGetIntegerv() с GL_INDEX_BITS, GL_MAX_ELEMENTS_VERTICES и GL_MAX_ELEMENTS_INDICES запросить количество индексных битов, максимальных вершин и максимальных индексов, поддерживаемых картой/драйвером.
- Если я правильно помню, массивы Vertex и VBOs (Vertex Buffer Object) имеют одинаковые ограничения (на одной и той же карте/драйвере), поэтому переключение между ними, вероятно, не поможет (не на 100% уверен в этом)