我有一个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
循环吗?
例如,是否可以直接旋转点?
答案 0 :(得分:3)
瓶颈是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 /系统内存中,因此这将获得的吞吐量不如现代基于VBO的绘图操作。使用现代OpenGL,您还可以通过着色器自由定义顶点属性。但是从上面的代码开始就很容易就可以了。