В чем разница между glVertexAttribDivisor и glVertexBindingDivisor? - PullRequest
0 голосов
/ 01 июня 2018

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

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

(выделено мной)

Что мне кажется, будто ответ утверждает, что я могу разделить на числовершин вместо количества экземпляров.Однако, когда я смотрю на документацию glVertexBindingDivisor и сравниваю ее с glVertexAttribDivisor, они оба, похоже, относятся к разделению, происходящему по экземплярам а не вершин .Например, в документации glVertexBindingDivisor говорится:

glVertexBindingDivisor и glVertexArrayBindingDivisor изменяют скорость, с которой улучшаются общие атрибуты вершин при рендеринге нескольких экземпляров примитивов в одной команде рисования,Если делитель равен нулю, атрибуты, использующие буфер, связанный с bindingindex, передвигаются один раз на вершину.Если делитель ненулевой, атрибуты продвигаются один раз на делитель экземпляров набора (-ов) визуализируемых вершин.Атрибут упоминается как instances , если соответствующее значение делителя не равно нулю.

(выделено мной)

Так какова фактическая разница между этимидве функции?

Ответы [ 2 ]

0 голосов
/ 02 июня 2018

ОК, сначала немного предыстории.

Начиная с OpenGL 4.3 / ARB_vertex_attrib_binding (AKA: откуда взято glVertexBindingDivisor, так что это актуально), VAO концептуально разделены на две части: массив вершинформаты, которые описывают ценность данных одного атрибута, и массив точек привязки буфера, которые описывают, как извлечь массивы данных (объект буфера, смещение, шаг и делитель).Формат вершины определяет, из какой точки привязки буфера поступают его данные, так что несколько атрибутов могут получать данные из одного массива (т. Е. Чередование).

Когда VAO были разделены на эти две части, более старые API были переопределены.определяется с точки зрения новой системы.Поэтому, если вы вызовете glVertexAttribPointer с индексом атрибута, эта функция установит данные формата вершины для формата с заданным значением index и установит состояние привязки буфера (объект буфера, смещение байта и т. Д.) Для того жеindex.Теперь это два отдельных массива данных о состоянии VAO (формат вершин и привязка буфера);эта функция просто использует один и тот же индекс в обоих массивах.

Но поскольку формат вершин и привязки к буферу теперь разделены , glVertexAttribPointer также эквивалентен утверждению, что формат вершин вindex index получает свои данные из привязки буфера по индексу index.Это важно, потому что это не автоматически;весь смысл vertex_attrib_binding в том, что формат вершины с одним индексом может использовать привязку буфера из другого индекса.Поэтому, когда вы используете старый API, он сбрасывает себя к старому поведению, связывая формат index с привязкой index.

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

glVertexAttribDivisor - это API старого стиля для установки делителя.Он принимает индекс атрибута, но воздействует на состояние, которое является частью точки привязки буфера (создание экземпляров является конструкцией для каждого массива, а не конструкцией для каждого атрибута).Это означает, что функция предполагает (в новой системе), что атрибут в index выбирает свои данные из точки привязки буфера в index.

И то, что я только что сказал, является ложью.Он обеспечивает это "предположение", напрямую устанавливая формат вершины для использования этой точки привязки буфера.То есть он выполняет тот же последний шаг, что и glVertexAttribPointer.

glVertexBindingDivisor - это современная функция.Не передается индекс атрибута;передается индекс привязки буфера.Таким образом, он не меняет индекс привязки буфера атрибута.

Так что glVertexAttribDivisor в точности эквивалентен этому:

void glVertexAttribDivisor(GLuint index, GLuint divisor)
{
  glVertexBindingDivisor(index, divisor);
  glVertexAttribBinding(index, index);
}

Очевидно, glVertexBindingDivisor не выполняет эту последнюю часть.

0 голосов
/ 01 июня 2018

Так в чем же разница между этими двумя функциями?

Современный OpenGL имеет два различных API для указания массивов атрибутов вершин и их свойств.Для традиционных glVertexAttribArray и друзей, где glVertexAttribDivisor также является частью.

с ARB_vertex_attrib_binding (в ядре, начиная с GL 4.3), был представлен новый API, который разделяетформат вершин из указателей.Ожидается, что переключение указателей данных будет быстрым, а переключение формата вершин может быть более дорогим.Новый API позволяет явно управлять обоими аспектами по отдельности, тогда как старый API всегда устанавливает оба сразу.

Для нового API был введен новый уровень введения: точки привязки буфера ,(Подробнее см. OpenGL wiki .) glVertexBindingDivisor задает делитель экземпляра атрибута для такой точки привязки, поэтому он является концептуальным эквивалентом функции glVertexAttribDivisor для нового API.

...