В OpenGL должны ли VBO содержать данные с одинаковым расположением вершин?

#opengl #vbo

#opengl #vbo

Вопрос:

Раньше у меня было много VBO, но теперь я объединил их в один и просто индексировал его в зависимости от того, что я рисую. Проблема в том, что когда я загружаю вершины в VBO и сохраняю запись о том, сколько байтов в буфере, это не совпадает с аргументом в glDrawArrays, чей аргумент смещения является «первым», а не смещением в байтах. Если все вершины в VBO имеют одинаковый макет, должен ли я выполнять разделение? Например, sizeof(Vertex) == 12 и он помещается в VBO со смещением 48 байт, чтобы нарисовать четыре вершины, нужно ли мне выполнять glDrawArrays(GL_TRIANGLE_STRIP, 48 / sizeof(Vertex), 4) ???

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

Чтобы настроить вершины, которые я вызываю glVertexAttribPointer и glEnableVertexArray четыре или пять раз, я пытался избежать вызова их для каждого вызова draw.

Ответ №1:

Если формат вершин изменился, то это означает, что (используя старый API), вам нужно было бы выполнить некоторое количество glVertexAttribPointer вызовов (возможно, как часть нового VAO, который вы собираетесь привязать), чтобы изменить формат данных вершин. В любом случае, вызов этой функции дает вам возможность изменить смещение байта, с которого начинается каждый атрибут в буфере.

Итак, если ваш буфер содержит 256 байт данных в макете 1, за которыми следуют 256 байт данных в макете 2, то «указатель», который вы предоставляете в качестве смещения байта при настройке макета 2, должен быть смещен на 256: начальное смещение для новых данных вершины.

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

И, к вашему сведению, «первым» параметром glDrawArrays является индекс, а не смещение в байтах.

Я пытался избежать вызова их для каждого вызова draw.

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

Комментарии:

1. Допустим, у вас есть буфер в VBO, и вы знаете, какое у него смещение в байтах, и если вы знаете расположение вершин, выполнение деления намного лучше, чем сброс указателей glVertexAttrib, не так ли? Я имею в виду разделение для перехода от смещения байта к «первому» индексу вершины

2. @Zebrafish: В вашем вопросе конкретно говорится о наличии двух разных «макетов». По определению это означает, что вам нужно снова вызвать glVertexAttribPointer или привязать новый VAO.