将 QGLWidget 与 Qt5 一起使用时出现性能问题
Performance Issue while using QGLWidget with Qt5
我正在尝试开发一个用于 3D 对象可视化及其模拟的应用程序。在这里,我必须绘制 'n' 个具有单独颜色 shades.For 的对象(可能是三角形、矩形或其他一些非凸多边形),我在 Qt5 中使用 QGLWidget(OS - Windows 7/8/10).
用于填充对象信息的结构:
typedef struct {
QList<float> r,g,b;
QList<double> x,y,z;
}objectData;
将从文件中读取对象的数量及其对应的坐标值。
paintGL函数:
void paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(25, GLWidget::width()/(float)GLWidget::height(), 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,5, 0,0,0, 0,1,0);
glRotatef(140, 0.0, 0.0, 1.0);
glRotatef(95, 0.0, 1.0, 0.0);
glRotatef(50, 1.0, 0.0, 0.0);
glTranslated(-1.0, 0.0, -0.6);
drawObjects(objData, 1000)
}
绘制对象函数:
void drawObjects(objectData objData,int objCnt) {
glPushMatrix();
glBegin(GL_POLYGON);
for(int i = 0; i < objCnt; i++) {
glColor3f(objData.r[i],objData.g[i],objData.b[i] );
glVertex3d(objData.x[i],objData.y[i],objData.z[i]);
}
glEnd();
glFlush();
glPopMatrix();
}
问题:
现在,当要绘制的对象数量超过某个最大值(例如 n = 5000)时,应用程序速度会逐渐降低。我无法使用 QThread,因为它已经继承了 QGLWidget。
请建议如何在对象数量较多时提高应用程序的性能。我不知道我哪里做错了。
该示例的屏幕截图:
在网格视图中包含多个对象的示例图像
您正在使用 OpenGL 立即模式,这对于大量顶点来说非常慢,而且几乎不应该使用。请改用 保留模式 。有关详细信息,请参阅此答案:
您使用的是固定管道而不是可编程管道,在可编程管道中,您告诉渲染过程的每个阶段应该做什么,仅此而已。我鼓励您研究其他明显的差异(研究 "modern opengl",这将引导您进行 OpenGL 3.3 及更高版本的工作)。
当计算机在渲染时必须针对每个几何图形与显卡通信时,旧的固定管道效率极低。相比之下,现代可编程管道允许您将要渲染的模型数据推送到 VRAM 中,在渲染过程中可以从那里直接访问数据(非常快速的内存访问)。
您还摆脱了 "doing stuff" 的通用方法,这些方法在机械上比自定义方法慢。
此外,我鼓励您使用 QOpenGLWidget 而不是以前的 QGLWidget class。如 http://doc.qt.io/qt-5/qglwidget.html 中所述,此 class 已过时。
现代 OpenGL 快速入门:
http://www.opengl-tutorial.org/
所以,你什么都没做"wrong"。你只是没有使用当前的技术。玩得开心!
谢谢@dave 和@Zedka9。当我开始在 openGL 中使用中间模式时,它对我来说很好用。我已经像这样修改了 drawObject 函数
绘制对象函数:
组织顶点和颜色并将其复制到这些缓冲区后
GLfloat 顶点[1024*1024],颜色[1024*1024];
int vertArrayCnt; // 顶点数
void drawObjects(void) {
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glPushMatrix();
glDrawArrays(GL_TRIANGLES, 0, vertArrayCnt);
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays
glDisableClientState(GL_COLOR_ARRAY);
}
我正在尝试开发一个用于 3D 对象可视化及其模拟的应用程序。在这里,我必须绘制 'n' 个具有单独颜色 shades.For 的对象(可能是三角形、矩形或其他一些非凸多边形),我在 Qt5 中使用 QGLWidget(OS - Windows 7/8/10).
用于填充对象信息的结构:
typedef struct {
QList<float> r,g,b;
QList<double> x,y,z;
}objectData;
将从文件中读取对象的数量及其对应的坐标值。
paintGL函数:
void paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(25, GLWidget::width()/(float)GLWidget::height(), 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,5, 0,0,0, 0,1,0);
glRotatef(140, 0.0, 0.0, 1.0);
glRotatef(95, 0.0, 1.0, 0.0);
glRotatef(50, 1.0, 0.0, 0.0);
glTranslated(-1.0, 0.0, -0.6);
drawObjects(objData, 1000)
}
绘制对象函数:
void drawObjects(objectData objData,int objCnt) {
glPushMatrix();
glBegin(GL_POLYGON);
for(int i = 0; i < objCnt; i++) {
glColor3f(objData.r[i],objData.g[i],objData.b[i] );
glVertex3d(objData.x[i],objData.y[i],objData.z[i]);
}
glEnd();
glFlush();
glPopMatrix();
}
问题: 现在,当要绘制的对象数量超过某个最大值(例如 n = 5000)时,应用程序速度会逐渐降低。我无法使用 QThread,因为它已经继承了 QGLWidget。
请建议如何在对象数量较多时提高应用程序的性能。我不知道我哪里做错了。
该示例的屏幕截图:
在网格视图中包含多个对象的示例图像
您正在使用 OpenGL 立即模式,这对于大量顶点来说非常慢,而且几乎不应该使用。请改用 保留模式 。有关详细信息,请参阅此答案:
您使用的是固定管道而不是可编程管道,在可编程管道中,您告诉渲染过程的每个阶段应该做什么,仅此而已。我鼓励您研究其他明显的差异(研究 "modern opengl",这将引导您进行 OpenGL 3.3 及更高版本的工作)。
当计算机在渲染时必须针对每个几何图形与显卡通信时,旧的固定管道效率极低。相比之下,现代可编程管道允许您将要渲染的模型数据推送到 VRAM 中,在渲染过程中可以从那里直接访问数据(非常快速的内存访问)。
您还摆脱了 "doing stuff" 的通用方法,这些方法在机械上比自定义方法慢。
此外,我鼓励您使用 QOpenGLWidget 而不是以前的 QGLWidget class。如 http://doc.qt.io/qt-5/qglwidget.html 中所述,此 class 已过时。
现代 OpenGL 快速入门:
http://www.opengl-tutorial.org/
所以,你什么都没做"wrong"。你只是没有使用当前的技术。玩得开心!
谢谢@dave 和@Zedka9。当我开始在 openGL 中使用中间模式时,它对我来说很好用。我已经像这样修改了 drawObject 函数
绘制对象函数:
组织顶点和颜色并将其复制到这些缓冲区后
GLfloat 顶点[1024*1024],颜色[1024*1024];
int vertArrayCnt; // 顶点数
void drawObjects(void) {
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glPushMatrix();
glDrawArrays(GL_TRIANGLES, 0, vertArrayCnt);
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays
glDisableClientState(GL_COLOR_ARRAY);
}