glVertexAttribPointer перезаписать

Я не совсем понимаю, как правильно переключаться между разными программами. Я сузил проблему до следующего: если я запускаю с NO_HDR, он работает нормально; Я получаю несколько линий, космический корабль и несколько сфер, отрисованных в таком порядке. Если я бегу с HDR, я получаю в основном то же самое, но вместо сфер я получаю 2d квадраты.

Я думаю, что атрибут вершины четырехугольника из части hdr перезаписывает последние элементы, отображаемые в разделе forwardRender(). Если я изменю порядок в forwardRender(), то, что будет отображено последним в forwardRender(), будет каким-то образом испорчено. Чего мне не хватает, это позволяет вершинам четырехугольника перезаписывать мои другие объекты?

#if NO_HDR
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
forwardRender();

#else

//set to render to custom frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, rt.FramebufferName);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
forwardRender();

//now switch to render to screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, rt.renderedTexture);

glUseProgram(hdr.shaderProgram);
glUniform1i(texID, 0);

glBindBuffer(GL_ARRAY_BUFFER, hdr.quad_vertexbuffer);
glEnableVertexAttribArray(hdr.quad_vertexPosition_modelspace);
glVertexAttribPointer(
                      hdr.quad_vertexPosition_modelspace, // attribute
                      3,                              // size
                      GL_FLOAT,                       // type
                      GL_FALSE,                       // normalized?
                      0,                              // stride
                      (void*)0                        // array buffer offset
                      );
// Draw the triangles !
glBindVertexArray(hdr.vao);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles

#endif

Еще одна подсказка: если я отключу vertexAttribArray после glDrawArrays в конце, мои сферы / квадраты исчезнут!

Для справки вот как я отображаю сферы в forwardRender():

glUseProgram(globe.shaderProgram);
glm::mat4 mvp = camera * world * position * size * orientation;
GLint uTransform = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(uTransform, 1, GL_FALSE, glm::value_ptr(mvp));
glBindVertexArray(globe.vao);
glDrawArrays(drawType, 0, globe.drawCount);

1 ответ

Решение

Размещенный код предлагает возможное недопонимание того, как работают объекты Vertex Array Objects (VAO). А ВАО это собрание гос. Он содержит состояние, заданное следующими вызовами:

  • glVertexAttribPointer(...)
  • glEnableVertexAttribArray(...), glDisableVertexAttribArray()
  • glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)

Каждый раз, когда вы делаете один из этих вызовов, соответствующее состояние сохраняется в текущем связанном VAO. И когда вы позже связываете VAO снова, состояние восстанавливается.

Например, в этой последовательности из размещенного кода:

glEnableVertexAttribArray(hdr.quad_vertexPosition_modelspace);
glVertexAttribPointer(hdr.quad_vertexPosition_modelspace, ...);
// Draw the triangles !
glBindVertexArray(hdr.vao);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles

glDrawArrays() Вызов не будет использовать состояние, которое вы установили для первых двух вызовов в последовательности. Это состояние будет применяться к тому, что VAO связано в то время. Затем glBindVertexArray(hdr.vao) вызов восстанавливает состояние, сохраненное в hdr.vao, который является самым последним состоянием, установленным, когда тот VAO был ранее связан.

Также обратите внимание, что это не имеет никакого отношения к переключению программ. Состояние вершины не является частью состояния программы.

Для эффективного использования VAO структура вашей программы обычно выглядит следующим образом:

  1. Один раз, во время настройки, вы создаете VAO для каждого объекта. Например, один для вашего земного шара, один для четырехугольника и т. Д. Затем свяжите каждую VAO и выполните вызовы из приведенного выше списка, чтобы установить состояние вершины для объекта.
  2. Во время рендеринга, для каждого объекта, при необходимости измените программу, свяжите VAO объекта и сделайте вызов draw. Вам не понадобятся никакие другие вызовы состояния вершины, поскольку состояние хранится в VAO каждого объекта.

Я не думаю, что у вас есть проблемы с этим в вашем коде, но просто для того, чтобы подчеркнуть один связанный элемент, который иногда вызывает путаницу: правильный GL_ARRAY_BUFFER привязка должна быть на месте во время glVertexAttribPointer() называется. Там нет необходимости устанавливать GL_ARRAY_BUFFER привязки для розыгрышей.

Другие вопросы по тегам