Почему glBufferSubData для буфера элемента должен вызываться вне glBindVertexArray? - PullRequest
0 голосов
/ 17 ноября 2018

Я пытаюсь заменить содержимое буфера элементов в этом примере hello world https://github.com/jvm-graphics-labs/hello-triangle/blob/master/src/main/java/gl4/HelloTriangleSimple.java, и мне удалось сделать это с некоторыми незначительными изменениями, используя glBufferSubData, но мне любопытно, что есть одна особенность - в мой метод отображения мне нужно вызвать glBufferSubData, прежде чем я вызову glBindVertexArray:

gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));
elementBuffer.rewind();
elementBuffer.put(elementData).rewind();
gl.glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, elementBuffer.capacity() * Short.BYTES, elementBuffer);
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
gl.glBindVertexArray(vertexArrayName.get(0));

Если я сделаю это после glBindVertexArray, я получу только черное окно. Странно то, что GL_ARRAY_BUFFER можно обновить после glBindVertexArray. В чем разница между буфером вершин и буфером элементов за этим наблюдением?

1 Ответ

0 голосов
/ 17 ноября 2018

Объект GL_ELEMENT_ARRAY_BUFFER сохраняется в векторе состояний объектов массива вершин.

Если Vertex Array Object привязан буфер элемента может быть присоединен к нему с помощью

gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));

Но если вы сделаете

gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

тогда имя объекта буфера элемента заменяется на 0, и ссылка на элементы прерывается. Это приводит к тому, что gl.drawElements больше не будет работать для этого VAO, поскольку он не ссылается ни на один индексный список.


Кроме того, обратите внимание, что всегда существует объект массива вершин. Объект массива вершин 0 - это объект массива вершин по умолчанию, который действителен только при использовании контекста профиля совместимости (не ядра).

Это означает, что

gl.glBindVertexArray(0);
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));

свяжет буфер элемента с объектом массива вершин по умолчанию (0). Это совершенно верно в контексте профиля совместимости.


См. Спецификацию профиля совместимости API OpenGL 4.6; 10.3.1. Объекты Vertex Array; страница 393 :

Пространство имен для объектов массива вершин представляет собой целые числа без знака, с нулем зарезервировано GL для представления объекта массива вершин по умолчанию. Команда

void GenVertexArrays( sizei n, uint *arrays );

возвращает n предыдущих неиспользуемых имен объектов массива вершин в массивах.

...

Объект массива вершин создается путем связывания имени, возвращаемого GenVertexArray, с помощью команды

void BindVertexArray( uint array );

array - имя объекта массива вершин. Результирующий объект массива вершин представляет собой новый вектор состояний, включающий все состояния и с теми же начальными значениями, перечисленными в таблицах 23.3 и 23.4.
BindVertexArray также может использоваться для привязки существующего объекта массива вершин. Если связывание выполнено успешно, изменение состояния связанного объекта массива вершин не производится, и любое предыдущее связывание прерывается.

Таблица 23.4. Состояние объекта массива вершин
ELEMENT_ARRAY_BUFFER_BINDING, VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, VERTEX_ATTRIB_BINDING, VERTEX_ATTRIB_RELATIVE_OFFSET, VERTEX_BINDING_OFFSET, VERTEX_BINDING_STRIDE, VERTEX_BINDING_DIVISOR, VERTEX_BINDING_BUFFER.

...