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,您可以通过着色器自由定义顶点属性。但是从上面的代码开始很容易。
我有一个 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,您可以通过着色器自由定义顶点属性。但是从上面的代码开始很容易。