OpenGL 主循环绘制巨大的点矢量

OpenGL main loop drawing huge vector of points

我有一个 MFC 应用程序,它的主绘制循环必须绘制一组巨大的点。现在,这是按如下方式完成的:

void CmodguiView::OnDraw(CDC* /*pDC*/) {

  wglMakeCurrent(m_hDC, m_hRC);

  // Clear color and depth buffer bits
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  const std::vector<DensePoint> *pts;
  pts = getPts();

  if (pts) {
    glBegin(GL_POINTS);
    for (auto &&pt : *pts) {
        glColor3ub(pt.r, pt.g, pt.b);
        glVertex3f(pt.x, pt.y, pt.z);
    }
    glEnd();


    SwapBuffers(m_hDC);
  }

}

我该如何优化这个?我可以避免 for 循环吗? 例如,是否可以直接旋转点?

瓶颈是对glVertex的无数次调用。这称为立即模式,由 glBegin ... glEnd 块表示,它已被弃用超过 10 年。即时模式也随着 15 年前顶点数组的引入而过时。所以不要用它。

相反,您应该使用顶点数组。您可以将它们与缓冲区对象组合以进一步提高性能。

无论如何,假设DensePoint写成

struct DensePoint {
    GLubyte r,g,b;
    GLfloat x,y,z;
};

您可以将 glBegin…glEnd 块替换为

std::vector<DensePoint> const * const pts = getPts();
if(pts) {
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glColorPointer (3, GL_UNSIGNED_BYTE,
                    sizeof(DensePoint), &((*pts)[0].r));
    glVertexPointer(3, GL_FLOAT,
                    sizeof(DensePoint), &((*pts)[0].x));

    glDrawArrays(GL_POINTS, 0, pts->size());
}

请注意,这仍然使用旧的 OpenGL-1.1 固定功能管道并且点数据保留在 CPU/system 内存中,因此这将不会像基于现代 VBO 的绘图操作那样获得那么多的吞吐量。此外,使用现代 OpenGL,您可以通过着色器自由定义顶点属性。但是从上面的代码开始很容易。