2015-11-23 2 views
2

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

//Vertices of the rectangle 
std::vector<GLfloat> vertices 
{ 
    0.5f, 0.5f, 0.0f, // Top Right 
    0.5f, -0.5f, 0.0f, // Bottom Right 
    -0.5f, 0.5f, 0.0f, // Top Left 
    -0.5f, -0.5f, 0.0f, // Bottom Left 
}; 

//Indices of the triangle 
std::vector<GLuint> indices 
{ 
    0, 1, 3, 
    0, 3, 2 
}; 


GLuint VAO, VBO, EBO; 
glGenVertexArrays(1, &VAO); 
glGenBuffers(1, &VBO); 
glGenBuffers(1, &EBO); 

glBindVertexArray(VAO); //Bind the VAO 

//Bind the buffers 
glBindBuffer(GL_ARRAY_BUFFER, VBO); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 

glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW); 

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); 
glEnableVertexAttribArray(0); 

glBindVertexArray(0); //Unbind the VAO 

//Supply Index Buffer information 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW); 

glBindBuffer(GL_ARRAY_BUFFER, 0); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

//Custom shader class that stores the program to be used at render time 
Shader shader("..path_to_shader\\shaders\\vertexshader.vert", "..path_to_shader\\shaders\\fragmentshader.frag"); 

while (!glfwWindowShouldClose(window)) 
{ 
    glUseProgram(shader.Program()); 
    glBindVertexArray(VAO); //Bind the VAO to draw. 
    glClearBufferfv(GL_COLOR, 0, &color[0]); 

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); 

    glfwPollEvents(); 
    glfwSwapBuffers(window); 

    glBindVertexArray(0); 
    glUseProgram(0); 
} 
+1

У вас нет привязки буфера элемента, когда вы вызываете 'glBufferData()' для индексов. Поскольку привязка является частью состояния VAO, она не привязана после того, как вы отвязали VAO. –

+0

Так что, в отличие от VBO, чтобы модифицировать буфер массива элементов, VAO должен быть связан? – Jeffrey

+0

Не VAO, а буфер, который вы хотите изменить. Поскольку ваши привязки сохраняются в вас VAO, в вашем случае привязка VAO или привязка вашего GL_ELEMENT_ARRAY_BUFFER одинакова для glBufferData. Однако иногда это не так. Дело в том, что вы вызываете glBufferData (GL_ELEMENT_ARRAY_BUFFER, ....), тогда GL_ELEMENT_ARRAY_BUFFER, который вы хотите изменить, должен быть связан. То же самое верно для других целей, таких как GL_ARRAY_BUFFER. – plasmacel

ответ

4

От opengl.org:

вершина массив объект (ВАО) является OpenGL объекта, который хранит все состояния, необходимого для обеспечения вершинных данных (с одним небольшим исключением отмечено ниже). Он хранит формат данных вершин, а также объекты буфера (см. Ниже), предоставляя массивы данных вершин.

below, at Index Buffers

Индекс буфера связывания сохраняется в ВАО.

Для GL_ARRAY_BUFFER ВАО сохранит привязку, когда вы позвоните glVertexAttribPointer. Это связано с тем, что привязка GL_ARRAY_BUFFER не является частью состояния VAO. Поэтому вызов glBindBuffer(GL_ARRAY_BUFFER, vertexBufferHandle) ничего не сделает с состоянием VAO.

Для GL_ELEMENT_ARRAY_BUFFER это не тот случай: VAO (если привязано) сохранит привязку вашего индексного буфера к его состоянию, когда вы вызываете glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferHandle).

Есть отличные уроки по OpenGL indexed buffering и еще один базовый материал на opengl-tutorial.org.

+0

Еще один вопрос, на opengl.org: «Обратите внимание, что VAO не копируют, не замораживают или не хранят содержимое ссылочных буферов - если вы меняете какие-либо данные в буферах, на которые ссылается существующий VAO, эти изменения будут видны пользователями ВАО ». Я вижу это, поставляя данные (с glBufferData) для GL_ARRAY_BUFFER после развязывания VAO. Когда я свяжу его снова, он отображает данные, как ожидалось. Но когда я пытаюсь сделать это с GL_ELEMENT_ARRAY_BUFFER, это не сработает. Это предполагаемое поведение? – Jeffrey

+0

Нет, VAO не касаются состояния или содержимого буферов. Они просто сохраняют привязки и спецификации атрибутов вершин. Вы можете без каких-либо проблем обновлять свои индексы в GL_ELEMENT_ARRAY_BUFFER. – plasmacel

+0

Что может быть моей проблемой? Когда я передаю данные в GL_ELEMENT_ARRAY_BUFFER после развязывания VAO, я ничего не получаю на экране (я пытаюсь нарисовать прямоугольник). – Jeffrey

6

GL_ELEMENT_ARRAY_BUFFER связывание становится частью государства ВАО, когда вы связать его с:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...); 

а VAO связан.

Обратите внимание, что также законно связывать буфер массива элементов без привязки VAO. Это действительно полезно для заполнения его данными, используя glBufferData() или аналогичные вызовы. Поскольку в основном профиле вам нужна привязка VAO для любых вызовов вызова, вам необходимо привязать буфер массива элементов, который вы хотите использовать для рендеринга, в то время как VAO привязан.

Что касается вашего кода, то последовательность вызовов, которые вы используете, не даст желаемого результата. Вот критические вызовы у вас есть, с комментариями, объясняя результат:

glBindVertexArray(VAO); 
// VAO is now bound. If this is the first time, it will have the default VAO state. 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 
// The element array buffer is bound, and this binding becomes part of the VAO state. 

glBindVertexArray(0); 
// The VAO is unbound. Since the element array buffer binding was part of the 
// VAO state, the element array buffer is also unbound. 

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), 
      &indices[0], GL_STATIC_DRAW); 
// This will not work, since you do not have an element array buffer bound. 

Чтобы получить эту работу, самое простое решение, что вы изменить порядок двух последних звонков:

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), 
      &indices[0], GL_STATIC_DRAW); 
// The currently bound element array buffer is filled with data. 

glBindVertexArray(0); 
// The VAO is unbound. Since the element array buffer binding was part of the 
// VAO state, the element array buffer is also unbound. 

Только для изучить это еще немного, следующая последовательность будет также работать:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 
// The element array buffer is bound, Since no VAO is bound, the binding becomes 
// part of the global state (or more precisely, of the default VAO 0). 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), 
      &indices[0], GL_STATIC_DRAW); 
// The currently bound element array buffer is filled with data. 

glBindVertexArray(VAO); 
// VAO is now bound. If this is the first time, it will have the default VAO state. 
// Since the element array binding is part of the VAO state, the previously bound 
// element array buffer is not bound anymore. 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 
// The element array buffer is bound, and this binding becomes part of the VAO state. 
glBindVertexArray(0); 
// The VAO is unbound. Since the element array buffer binding was part of the 
// VAO state, the element array buffer binding is restored to the binding that 
// was current before the VAO was bound. 

Обратите внимание, что в этой последовательности, вы должны связать буфер элемента массива снова после связывания ВАО, так как эль привязка буфера массива в состоянии VAO будет отменять текущую привязку, как только вы свяжете VAO.

+0

Большое спасибо, что все ясно! – Jeffrey