OpenGL не может обновить буфер вершин с помощью процедуры VAO - PullRequest
1 голос
/ 21 июня 2020

Я пытаюсь переместить вершину, изменяя ее позиционный атрибут вершины. В качестве теста я добавил строку vertices[0] = 0.4f; как до, так и после создания моей процедуры VAO, чтобы увидеть, могу ли я изменить массив вершин после первоначального рендеринга. Когда я добавляю его перед созданием VAO, он изменяет местоположение вершины, а когда он добавляется впоследствии, это не так. Это заставляет меня поверить в мою процедуру рендеринга:

glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

glfwSwapBuffers(window);
glfwPollEvents();

Каким-то образом фактически не обновляется буфер с текущим float[] в памяти. Однако затем я могу заменить строку glBindVertexArray(VAO); всей процедурой рендеринга:

    // 2. copy our vertices array in a buffer for OpenGL to use
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    // 2. copy our vertex indices in a buffer for OpenGL to use
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
    // 3. then set our vertex attributes pointers:
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); // Pos vec3
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3* sizeof(float))); // Col vec4
    glEnableVertexAttribArray(1);

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

    // Generate a Vertex Array Object to store our rendering procedure.
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    // 1. bind Vertex Array Object, Element Buffer Object
    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    // 2. copy our vertices array in a buffer for OpenGL to use
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    // 2. copy our vertex indices in a buffer for OpenGL to use
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
    // 3. then set our vertex attributes pointers:
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); // Pos vec3
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3* sizeof(float))); // Col vec4
    glEnableVertexAttribArray(1);

Значит, он работает, когда я express явно выполняю процедуру рендеринга, но не когда я сохраняю его в VAO? Насколько я понимаю, VAO - это конструкция для хранения процедуры рендеринга, и когда мы затем запускаем glBindVertexArray(VAO);, эта процедура рендеринга выполняется. Я неправильно это понимаю? Есть ли еще одна строка, которая мне нужна при создании VAO или при рендеринге?

Вот полный исходный код на C ++: https://pastebin.com/DgZuZt4K

И то же самое написано в OpenTK, C#: https://pastebin.com/DHj9UN16

1 Ответ

2 голосов
/ 21 июня 2020

[...] Насколько я понимаю, VAO - это конструкция для хранения процедуры рендеринга, [...]

Нет, это не так. A Vertex Array Object хранит состояния.

Когда вызывается glBufferData / glBufferSubData, тогда хранилище данных буферного объекта инициализируется соответственно обновлено.

Когда вызывается glVertexAttribPointer, то состояния устанавливаются в векторе состояний VAO. Буферный объект, который в настоящее время привязан к цели GL_ARRAY_BUFFER, связан с указанным атрибутом вершины в привязанном в данный момент VAO. VAO хранит информацию о том, как интерпретировать информацию о вершинах и идентификатор VBO для каждого атрибута.

Но VAO не хранит процедуру или даже процесс. Когда вы изменили вершины, вам необходимо обновить Vertex Buffer Object либо glBufferSubData, либо сопоставлением буфера.

Связано: Как правильно изменить OpenGL буфер вершин?

Если вы хотите указать и включить атрибут вершины (glVertexAttribPointer / glEnableVertexAttribArray), вам необходимо связать VAO и VBO. VAO хранит спецификацию, а идентификатор VBO хранится в VAO.

Если вы хотите обновить координаты и атрибуты вершины (например, glBufferSubData), вам необходимо привязать VBO.

Если вы хотите нарисовать меня sh (например, glDrawArrays), то достаточно привязать VAO.

...