c++ - OpenGL 减慢 5k 点

标签 c++ opengl

我正在写一个 SLAM库并希望使用 OpenGL 可视化其工作。我需要绘制大约 10 万个点和几百个矩形,我希望 OpenGL 可以轻松处理它。但是,在点数达到 5k 后,我的程序变慢了。

我是 OpenGL 的新手,所以我想我做事的方式不对。我用了this tutorial用于学习。

随着程序的运行,它吐出某些事件,其中只有少数是相关的:

  • 创建的点 (size_t id, float x,y,z;)
  • 更新点 (szie_t id, float x,y,z;)
  • 位置估计(四元数 Q、Vector3D T)

可视化这些事件(简化)的程序部分的工作方式如下。

我们为每个点分配一个 GL_ARRAY_BUFFER。为了不在每次获得新点时都分配新的缓冲区,我决定保留一个缓冲区存储库。当一个新点到达时,我们从存储库中为其分配一个“空闲”缓冲区。仅当 repo 为空时,我们才使用 glGenBuffers 分配一个新缓冲区。

std::stack<GLuint> point_buffer_stack;
std::map<size_t, GLuint> active_points;

void OnPointCreated(size_t id,  float x, float y, float z ){
  GLuint point_buffer_id;
  if(point_buffer_stack.empty()){
    glGenBuffers(1, &point_buffer_id);
  }
  else {
    point_buffer_id = point_buffer_stack.top();
    point_buffer_stack.pop(); 
  }
  active_points[id] = point_buffer_id;

  OnPointUpdated(id, x, y, z);
     
}

void OnPointUpdated(size_t id, float x, float y, float z){
  GLuint point_buffer_id = active_points[id];
  float buffer[3] = {x,y,z};
  glBindBuffer(GL_ARRAY_BUFFER, point_buffer_id);
  glBufferData(GL_ARRAY_BUFFER, sizeof(buffer), buffer, GL_STATIC_DRAW); 
}

void OnPointDeleted(size_t id){
  GLuint point_buffer_id = active_points[id];
  point_buffer_stack.push(point_buffer_id);
  active_points.erase(id);
}
  

仅在位置更新时绘制边框:

void OnPositionUpdated (const glm::mat4 & projection){
  glm::mat4 model_view_projection;
  /* Compute  model_view_projection and set the corresponding UniformMatrix4fv for using in the  vertex shader */

  // Draw points 
  glEnableVertexAttribArray(0);
  for(const auto & id_vertex: active_points){
    glBindBuffer(GL_ARRAY_BUFFER, id_vertex.second);
    glVertexAttribPointer(
      0,                  // layout from vertex shader.
      3,                  // 3D
      GL_FLOAT,           // type
      GL_FALSE,           // normalized?
      0,                  // stride
      (void *) 0            // array buffer offset
      );
    glDrawArrays(GL_POINTS, 0, 1);
  }
  glDisableVertexAttribArray(0);

  /*Draw a rectangle that shows the current position by drawing two triangles */

  glfwSwapBuffers(window);
  glfwPollEvents();
}

在我的配备英特尔® Xe 显卡、Ubuntu 20.04 的华硕 Zenbook 上,OpenGL 开始落后于相机大约 5k 点。一段时间后,我从 OpenCV(使用 OpenGL 支持构建)收到内存不足错误。

这是预期的吗?我究竟做错了什么?如何解决这个问题?

供引用,OpenGL的初始化过程如下:

glfwInit();
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

window = glfwCreateWindow(1920, 1080, "SLAM 3D visualization", NULL, NULL);

最佳答案

We assign a GL_ARRAY_BUFFER to each point.

那是你的问题。这意味着您正在为所有 12 字节的内存分配一个完整的缓冲区对象。将每个点放入其自己的缓冲区意味着您必须使用单独的绘制调用来渲染每个点。

这些都不是性能的秘诀。

为您打算使用的所有点创建一个大缓冲区,并通过一次绘制调用渲染它们。如果您需要更改点之间的参数或其他内容,请将它们设为单独的顶点属性。或者做不到这一点,让它们统一到你的着色器并渲染所有使用一组参数的点,改变统一,然后渲染下一个使用新参数的点,等等。

关于c++ - OpenGL 减慢 5k 点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70230055/

相关文章:

c++ - 使用 glDrawElements 不绘制我的 .obj 文件

c++ - 为模板类重载友元运算符 <<

java - 捕获/导出 JOGL 动画到视频文件

c++ - 从 View 矩阵中清除比例组件。相机独立缩放

opengl - OpenGL Mipmapping:OpenGL如何确定 map 级别?

c++ - QXML - child 是否按顺序访问

C++ 静态初始化顺序

c++ - "struct"和结构成员前缺少 "struct"字有什么区别

c++ - 将两种方法结合在一起

java - LWJGL Opengl 着色器错误