При использовании IBO/EBO программа работает только тогда, когда я вызываю glBindBuffer для привязки IBO/EBO ПОСЛЕ создания VAO

По какой-то причине эта программа работает только тогда, когда я снова привязываю IBO/EBO после создания VAO. Я читал в Интернете и несколько сообщений SO, что glBindBuffer привязывает только текущий буфер и что он не прикрепляет его к VAO. Я думал, что glVertexAttribPointer — это функция, которая прикрепляет данные к VAO.

float points[] = {

   -0.5f,  0.5f, 0.0f, // top left      = 0
    0.5f,  0.5f, 0.0f, // top right     = 1
    0.5f, -0.5f, 0.0f, // bottom right  = 2
   -0.5f, -0.5f, 0.0f, // bottom left   = 3

};

GLuint elements[] = {

    0, 1, 2,
    2, 3, 0,
};

// generate vbo (point buffer)
GLuint pb = 0;
glGenBuffers(1, &pb);
glBindBuffer(GL_ARRAY_BUFFER, pb);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

// generate element buffer object (ibo/ebo)
GLuint ebo = 0;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

// generate vao
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);


glBindBuffer(GL_ARRAY_BUFFER, pb);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);


glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); // when I bind buffer again, it works


glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

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

Pastebin (ПОЛНЫЙ КОД)


person Greg M    schedule 02.07.2015    source источник


Ответы (2)


Проблема заключается в порядке ваших первоначальных вызовов. Привязка GL_ELEMENT_ARRAY_BUFFER является частью состояния VAO. Посмотрите на эту последовательность:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

Поскольку привязка GL_ELEMENT_ARRAY_BUFFER является частью состояния VAO, вызов glBindVertexArray() в конце последовательности установит привязку буфера GL_ELEMENT_ARRAY_BUFFER, которая является частью привязываемого вами VAO vao. Что, поскольку вы только что создали vao, является 0. Таким образом, в конце этой последовательности у вас нет связанного буфера массива элементов.

Или, если посмотреть на это с другой стороны, когда вы делаете вызов glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo) в начале, VAO 0 привязан. Таким образом, эта привязка становится частью состояния VAO 0. Затем, когда вы связываете другой VAO vao, вы теряете привязку, и она заменяется привязкой, которая является частью состояния VAO vao.

Чтобы это работало так, как вы ожидали, вам нужно сделать начальную привязку GL_ELEMENT_ARRAY_BUFFER после привязки VAO. Затем он становится частью состояния VAO и будет устанавливаться снова каждый раз, когда вы позже связываете VAO:

GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
person Reto Koradi    schedule 02.07.2015

Если вы посмотрите на спецификацию, состояние Vertex Array Object не включает в себя Element Buffer Object.

Действительно, включение VAO не устанавливает точку привязки элемента.

person Luca    schedule 02.07.2015
comment
Извините за резкость, но это совершенно неправильно. Привязка буфера элемента является частью состояния VAO. - person Reto Koradi; 02.07.2015
comment
Может быть, мне нужно снова прочитать спецификацию OpenGL... В последнее время я не могу написать правильный ответ об OpenGL. Соб. - person Luca; 02.07.2015
comment
Если у вас есть, например, документ спецификации OpenGL 3.3, проверьте таблицу 6.5 на стр. 281. Эта таблица называется Vertex Array Object State и содержит ELEMENT_ARRAY_BUFFER_BINDING. - person Reto Koradi; 03.07.2015