【问题标题】:Performance Issue while using QGLWidget with Qt5将 QGLWidget 与 Qt5 一起使用时的性能问题
【发布时间】:2018-11-20 15:17:45
【问题描述】:

我正在尝试开发一个应用程序,该应用程序将用于 3D 对象的可视化及其模拟。在此我必须绘制具有单独颜色阴影的“n”个对象(可能是三角形、矩形或其他一些非凸多边形)。为此,我在 Qt5 中使用 QGLWidget(操作系统 - 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。

请建议在对象数较高时如何提高应用程序的性能。我不知道我在哪里做错了。

该示例的屏幕截图:

包含网格视图中对象数量的示例图像

【问题讨论】:

    标签: qt opengl qglwidget


    【解决方案1】:

    您使用的是固定管道而不是可编程管道,您可以在其中告诉渲染过程的每个阶段,应该做什么,仅此而已。在我鼓励您研究的其他显着差异中(研究“现代 opengl”,它将引导您进行 OpenGL 3.3 及以上类型的工作)。

    旧的固定管线效率非常低,当计算机在渲染时必须为每个几何图形与显卡通信时。相比之下,现代可编程管道允许您将要渲染的模型数据推送到 VRAM 中,在渲染期间将直接从 VRAM 访问它(非常快速的内存访问)。

    您还摆脱了“做事”的通用方式,这些方式在机械上比定制方式慢。

    另外,我鼓励您使用 QOpenGLWidget 而不是以前的 QGLWidget 类。如http://doc.qt.io/qt-5/qglwidget.html 中所述,此类已过时。

    现代 OpenGL 快速入门:

    http://www.opengl-tutorial.org/

    所以,你没有做任何“错误”的事情。您只是没有使用当前的技术。玩得开心!

    【讨论】:

      【解决方案2】:

      您正在使用 OpenGL 即时模式,这对于大量顶点来说非常慢,几乎不应该使用。请改用保留模式。有关详细信息,请参阅此答案:https://stackoverflow.com/a/6734071

      【讨论】:

        【解决方案3】:

        谢谢@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);
        }
        

        【讨论】:

        • 感谢您的反馈。我很高兴你找到了这个方法。只要知道这是一个短期解决方案,我强烈建议您切换到使用核心 OpenGL 上下文 :)
        • @Zedka29 核心 OpenGL 上下文(如顶点和片段着色器或其他)是什么意思?您能否简要解释一下或分享内容的链接?
        • 我的意思是,你不应该使用任何被标记为弃用的东西,即只使用 OpenGL 3.3 及更高版本的 API。不再有 glEnableClientState,不再有 glPushMatrix、glPopMatrix。当涉及到线性代数和矩阵堆栈时,这会导致您靠自己。用于此目的的已知数学库是 glm。看看我给你的链接(教程)。它只是教你当前的做事方式。您会看到 GLSL 的语法也发生了一些变化。
        猜你喜欢
        • 2017-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-01
        • 2016-11-10
        • 2020-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多