Matthew Hoggan
Matthew Hoggan

Reputation: 7604

C++ OpenGL Old Data Remains In VBO after Modifying it with glMapBuffer()

The code I would have to paste is too much. I have followed tutorials, however, when trying to implement them by myself nothing seems to work. I will paste the glMapBuffer routine below. Note that vertex_type and render_target are templeted parameters that allow users to set those enumerated values themselves.

An image of what is happening is.

Wich shows the square slowly being linearly translated towards the upper right corner of the screen by modifying the contents of the VBO.

bool modify_vertex_data(
  std::vector<vertex_2d_renderer_type<vertex_type> > &data,
  GLsizeiptr start_index) {

  if (!vertex_vbo_pointer_ || (start_index + data.size()) >
    static_cast<uint32_t>(vertex_count_)) {

    return false;
  }
  glBindBuffer(render_target, vertex_vbo_pointer_);
  vertex_2d_renderer_type<vertex_type> *vbo_data;
  vbo_data = reinterpret_cast<vertex_2d_renderer_type<vertex_type> *>(
    glMapBuffer(render_target, modify_access));

  memcpy(vbo_data, data.data(),
    data.size() * sizeof(vertex_2d_renderer_type<vertex_type>));

  return (glGetError() == GL_NO_ERROR) && glUnmapBuffer(render_target);
}

The code that calls into this is:

void QtRenderer::paintGL() {
  //makeCurrent();
  count_++;

  glMatrixMode(GL_PROJECTION);
  glEnable(GL_SCISSOR_TEST);
  glDisable(GL_DEPTH_TEST);
  glLoadIdentity();
  glViewport(0, 0, width(), height());
  glOrtho(0, width(), 0, height(), -1, 1);

  glMatrixMode(GL_MODELVIEW);
  glScissor(0, 0, width(), height());
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glLoadIdentity();

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  for (uint32_t i = 0; i < 6; ++i) {
    data_[i].vertex_.x_ += 0.1;
    data_[i].vertex_.y_ += 0.1;
  }

  if (!renderer_2d_.modify_vertex_data(data_, 0)) {
    throw std::runtime_error("ERROR: Data Modification Error");
  }

  renderer_2d_.draw_vertex_data();
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  swapBuffers();
}

Upvotes: 0

Views: 395

Answers (1)

datenwolf
datenwolf

Reputation: 162317

Actual Solution

After spending some time in chat with OP, looking at the code, I found the issue to be a redundant call to his OpenGL data initialization code. OP uses Qt's QGLWidget that provides a virtual method QGLWidget::initializeGL which is implicitly called by Qt as soon as the OpenGL context is ready to use. By overriding that method one can initialize persistent OpenGL objects like VBOs and such in a reliable way.

However in OP's code this method was also called explicitly, so the client side std::vector buffers for the vertex data got pushed another full copy of the vertex data, which then later got not modified, resulting in that apparent "residual" data.

Bringing the code back into proper QGLWidget semantics shape solved the issue.

Original Answer

You're not clearing the framebuffer before drawing, so whatever was drawn before becomes the "background" on which you overdraw. OpenGL is not a scenegraph it's a drawing API. If you change data in a VBO it will not "magically" update the screen contents.

Upvotes: 2

Related Questions