Подтвердить что ты не робот

Когда должен вызываться glVertexAttribPointer?

Это не очевидно из документации при вызове glVertexAttribPointer. Это похоже на часть инициализации VBO, но я замечаю пример кода, вызывающего его во время рендеринга.

glVertexAttribPointer(vertexAttributeId, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), reinterpret_cast<const GLvoid*>(offsetof(Vertex2D, m_x)));

Должен ли glVertexAttribPointer вызываться во время инициализации GL_ARRAY_BUFFER или он должен быть вызван во время рендеринга (после вызова glBindBuffer)?

4b9b3361

Ответ 1

Функция glVertexAttribPointer определяет формат и исходный буфер (игнорируя устаревшее использование клиентских массивов) атрибута вершины, который используется при рендеринге (т.е. следующий вызов glDraw...).

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

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

Итак, в современном OpenGL с использованием VAO (который рекомендуется), он обычно похож на этот рабочий процесс:

//initialization
glGenVertexArrays
glBindVertexArray

glGenBuffers
glBindBuffer
glBufferData

glVertexAttribPointer
glEnableVertexAttribArray

glBindVertexArray(0)

glDeleteBuffers //you can already delete it after the VAO is unbound, since the
                //VAO still references it, keeping it alive (see comments below).

...

//rendering
glBindVertexArray
glDrawWhatever

Если не использовать VAO, это будет примерно так:

//initialization
glGenBuffers
glBindBuffer
glBufferData

...

//rendering
glBindBuffer
glVertexAttribPointer
glEnableVertexAttribArray
glDrawWhatever

Ответ 2

glVertexAttribPointer - это то, что на самом деле не принадлежит Buffer или программе, - скажем, клей между ними. (Функциональность этого разделена на Opengl 4.3 в разных функциях VertexAttrib*Format, VertexAttribBinding и BindVertexBuffer, доступных через ARB_vertex_attrib_binding)

Но если вы хотите сказать, что это часть чего-то, я бы сказал, что он является частью VAO, в котором хранится состояние связанных объектов буфера, какие атрибуты включены и как должны передаваться данные буфера к Программе.

Поэтому он принадлежит к той части, где вы настраиваете VAO s.

ИЗМЕНИТЬ Простая настройка, которая иллюстрирует порядок:

  • создание/настройка Buffer и создание программ
  • create VAO определить, какие атрибуты включены, какие буферы должны быть привязаны, когда используется VAO и как эти данные передаются программе (glVertexAttribPointer)

Ответ 3

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

Последний параметр особенно хорош в справочном руководстве:

Задает смещение первого компонента первой общей вершины атрибут в массиве в хранилище данных текущего буфера к цели GL_ARRAY_BUFFER. Начальное значение равно 0.

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

Короткий пример (извините мой псевдокод):

// Setup
CreateVAO(); BindVAO();
CreateVBO(); BindVBO();
VertexAttribPointer(/*id*/ 0, 3, GL_FLOAT, /*starting at offset*/ 0);

// We have specified Vertex attribute bound to location 0,
// with size of 3 floats, starting at offset 0 of VBO we've just created.        

//Draw
BindVAO();
Draw();

Ответ 4

Связь атрибута buffer, generic vertex и переменной атрибута shader довольно тонкая. glVertexAttribPointer устанавливает эту связь. Подробнее см. OpenGL-Terminology.

Кроме того, ссылка OpenGL-VBO, шейдер, VAO показывает рабочий пример с необходимой последовательностью вызовов API.