如何在没有高CPU使用率的OpenGL游戏中正确渲染模型(纹理网格)?

时间:2017-04-19 19:36:13

标签: c++ opengl cpu

我有一个模型游戏,当我渲染它们时,我的CPU使用率很高(每个模型大约10%)。我使用glutMainLoop每秒调用DisplayFunc 60次。我将绘图功能称为

  • glPushMatrix
  • glTranslatef,glRotatef,glScalef
  • glMaterialfv所以纹理材质,我绑定我的纹理
  • glBegin for triangles
  • 然后循环for faces glNormal3f,glTexCoord2f,glVertex3f for triangles
  • glEnd
  • 和glPopMatrix

我不知道自己做错了什么,而且我没有任何立足点,这就是我在这里问的原因。

好的,所以我做了简单的修正,现在好吗?

    #include <GL/glut.h>
    #include <gl/glext.h>

    void Display();
    void Reshape(int width, int height);

    const int windowWidth = 480;
    const int windowHeight = 270;

    GLuint vertexbuffer;
    static const GLfloat g_vertex_buffer_data[] =
    {
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        0.0f,  1.0f, 0.0f,
    };

    int main(int argc, char* argv[])
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
        glutInitWindowPosition(100, 100);
        glutInitWindowSize(windowWidth, windowHeight);
        glutCreateWindow("Modern OpenGL");

        glutDisplayFunc(Display);
        glutReshapeFunc(Reshape);
        glutIdleFunc(Display);

        GLfloat reset_ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, reset_ambient);
        glEnable(GL_LIGHTING);
        glShadeModel(GL_SMOOTH);
        glEnable(GL_LIGHT0);

        glGenBuffers(1, &vertexbuffer);

        glutMainLoop();

        return 0;
    }

    void Display()
    {
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();

        gluLookAt(0,0,10,0,0,0,0,1,0);

        GLfloat light0amb[4] = { 1.0, 1.0, 1.0, 1.0 };
        glLightfv(GL_LIGHT0, GL_AMBIENT, light0amb);
        GLfloat light0dif[4] = { 1.0, 1.0, 1.0, 1.0 };
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light0dif);
        GLfloat light0spe[4] = { 1.0, 1.0, 1.0, 1.0 };
        glLightfv(GL_LIGHT0, GL_SPECULAR, light0spe);
        GLfloat light0pos[4] = { 0.0, 0.0, 0.0, 1.0 };
        glLightfv(GL_LIGHT0, GL_POSITION, light0pos);

        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            0,
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            (void*)0
        );
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(0);

        glFlush();
        glutSwapBuffers();
    }

    void Reshape(int width, int height)
    {
        glutReshapeWindow(windowWidth, windowHeight);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glViewport(0, 0, width, height);
        gluPerspective(45.0f, width / (double)height, 0.1f, 1000.0f);
        glMatrixMode(GL_MODELVIEW);
    }

2 个答案:

答案 0 :(得分:2)

VTT评论re:glBegin / glEnd是正确答案。为了进一步扩展,通过使用旧的,已弃用的API,您遇到了一个明确的问题和一个潜在的问题。

明确的问题是OpenGL无法利用现代GPU中的许多硬件加速功能,因为不是将所有三角形(即顶点)和材料(例如纹理)存储在GPU内存中,它可能需要每次渲染时,至少将其中一些从主内存复制到GPU内存。通过使用顶点缓冲区以及顶点着色器和片段着色器,您可以轻松避免这种非常重要的开销。

如果您搜索它们有很多例子,那么可能需要一些时间来重构您的代码,知道该怎么做不应该是一个问题。

潜在的问题是固定功能管道已被弃用了一段时间(并且非常不鼓励甚至更长时间),因此许多驱动程序可能更多地包含该功能以便与旧游戏和应用程序兼容,而不是作为优化的主动目标。换句话说,开发人员的时间用于优化现代API而不是20世纪90年代后期的API。

您最终以您的方式编写代码可能不是您的错。遗憾的是,网络和免费提供的旧书副本提供了许多基于旧的固定功能管道而不是现代可编程管道的示例。结合(最初)固定功能管道通常更容易理解和使用的事实,它会导致您所处的情况。但是,值得花时间学习现代API。它为你的图形效果提供了大量机会,使你的图形即使在低端&#34;系统

答案 1 :(得分:0)

所以现在你以新的方式做事,但你并没有充分利用你所能做的一切。您每次渲染时都会上传几何体。由于它没有更改(您使用GL_STATIC_DRAW),因此请不要多次上传。一旦它在视频内存中存在,它将保留在那里直到你删除它。与着色器的制服相同。您需要的唯一调用是清除颜色,绑定各种数组和属性,绘制数组,然后取消绑定各种数组和属性。可能是同花顺。 glBufferData()电话可能需要很长时间。

另外,我不得不说10%的CPU使用率是没有的。我不确定为什么会引起你的注意。实际上,各种新的渲染器(Metal,Vulkan,DX12)对于减少渲染的CPU组件基本上非常有用。如果它只有10%,那么几乎不需要它们!