2013-04-04 6 views
21

Я настраиваю буфера вершин в OpenGL, например:Каков правильный способ изменения вершинного буфера OpenGL?

int vboVertexHandle = glGenBuffers(); 
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle); 
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW); 

Позже, если я хочу, чтобы добавить или удалить вершины в «vertexData», что такое правильный способ сделать это? Возможно ли это? Я предполагаю, что не могу просто изменить массив напрямую, не пересылая его на GPU.

Если я изменить массив vertexData, то назвать это снова:

glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle); 
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW); 

... будет что перезаписать старый буфер с моими новыми данными? Или мне также нужно удалить старый? Есть ли способ лучше?

ответ

23

Размер любого объекта буфера OpenGL устанавливается при вызове glBufferData. То есть OpenGL будет выделять объем памяти, указанный во втором аргументе glBufferData (который не указан в OP). На самом деле, если вы вызываете, например, glBufferData(GL_ARRAY_BUFFER, bufferSize, NULL, GL_DYNAMIC_DRAW); OpenGL создаст буфер bufferSize байт неинициализированные данные.

Вы можете загрузить любое количество данных (вплоть до размера буфера), используя glBufferSubData, glMapBuffer или любую другую программу для передачи данных. Единственный способ изменить размер буфера - вызвать glBufferData с новым размером для того же идентификатора буфера (значение, возвращаемое с glGenBuffers).

Таким образом, вы всегда можете использовать подмножество данных в буфере (которое было бы сродни удалению вершин), а при рендеринге с использованием glDrawElements вы можете произвольно обращаться к элементам в буфере. Добавление вершин в буфер потребует выделения большего буфера, а затем вам потребуется перезагрузить все данные в буфере.

+0

Разве вы не хотели сказать «неинициализированные данные» в конце вашего первого абзаца? – Ancurio

+0

@ Ancurio Действительно, я сделал. Спасибо за исправление. – radical7

4

http://www.opengl.org/wiki/GLAPI/glBufferData

glBufferData создает новое хранилище данных для объекта буфера в настоящее время связаны цели. Любое ранее существующее хранилище данных удаляется.

Это объясняет, что вызов glBufferData будет «перераспределять» данные, буфер будет иметь новый размер. Все старые данные будут потеряны. Если вы хотите записать только часть буфера, вместо этого используйте glBufferSubData.

http://www.opengl.org/wiki/GLAPI/glBufferSubData

Edit: glBufferSubData только если вы хотите заменить данные; для изменения размера буфера, вы должны позвонить glBufferData.

Кроме того, вам не нужно сначала разрушать буфер и генерировать новый. Помните, что GLuint - это только «указатель» для OpenGL. Это не фактическое хранилище, поэтому вполне нормально повторно использовать один и тот же «указатель» (если вы еще не удалили его, конечно).