C++ OpenGL 旧数据在使用 glMapBuffer() 修改后仍保留在 VBO 中

标签 c++ opengl

我不得不粘贴的代码太多了。我已经按照教程进行操作,但是,当我尝试自己实现它们时,似乎没有任何效果。我将在下面粘贴 glMapBuffer 例程。请注意,vertex_typerender_target 是允许用户自己设置这些枚举值的模板化参数。

正在发生的事情的图像是。

通过修改 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);
}

调用它的代码是:

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();
}

最佳答案

实际解决方案

在与 OP 交谈了一段时间后,查看代码,我发现问题是对他的 OpenGL 数据初始化代码的冗余调用。 OP 使用 Qt 的 QGLWidget,它提供了一个虚拟方法 QGLWidget::initializeGL,一旦 OpenGL 上下文准备好使用,Qt 就会隐式调用该方法。通过覆盖该方法,可以以一种可靠的方式初始化持久性 OpenGL 对象,如 VBO 等。

然而,在 OP 的代码中,此方法也被显式调用,因此用于顶点数据的客户端 std::vector 缓冲区被推送到顶点数据的另一个完整拷贝,随后未被修改,导致明显的“残留”数据。

将代码恢复为正确的 QGLWidget 语义形状解决了这个问题。

原始答案

在绘制之前您没有清除帧缓冲区,因此之前绘制的任何内容都将成为您过度绘制的“背景”。 OpenGL 不是场景图,它是一种绘图 API。如果您更改 VBO 中的数据,它不会“神奇地”更新屏幕内容。

关于C++ OpenGL 旧数据在使用 glMapBuffer() 修改后仍保留在 VBO 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16250216/

相关文章:

c++ - Source Insight 3.5 显示 .c 文件的 "Parse Too complex"

c - 在 openGL 中寻找聚光灯 vector

python - 程序 GL 纹理

python - 如何使用着色器、pygame 和 pyopengl 在多于 1 个轴上执行 OpenGL 旋转

c++ - 在其他函数中获取变量后创建数组

c++ - 将 AVPackets 混合到 mp4 文件中

c++ - 如何检查结构类型或字段是否存在

c++ - 当我们调用 C 函数时,为什么不抛出编译器时间错误

c++ - Visual Studio 2015 OpenGL freeglut.dll 链接器错误

c++ - freeglut 无法使用 valgrind 打开显示