问题 OpenGL GLUT窗口很慢,为什么?


问题

我刚刚开始使用GLUT处理OpenGL。下面的代码编译并显示两个线框立方体和一个球体。问题是,当我尝试拖动或调整窗口大小时,它会在跟踪鼠标之前产生明显的延迟。

我的同事的计算机上没有出现此问题,相同的代码。

我在Windows 7计算机上使用Visual Studio 2012 c ++ express。 我不是一个经验丰富的程序员。

代码

    // OpenGLHandin1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <GL/glut.h>

void initView(int argc, char * argv[]){
    //init here
    glutInit(&argc, argv);
    //Simple buffer
    glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,400);
    glutCreateWindow("Handin 2");
}
void draw(){

    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    //Background color

    glPushMatrix();
    glLoadIdentity();
    glTranslatef(0.6, 0, 0);

    glColor3f(0.8,0,0);
    glutWireCube(1.1); //Draw the cube
    glPopMatrix();

    glPushMatrix();
    glLoadIdentity();
    glTranslatef(-0.5, 0, -0.2);

    glColor3f(0,0.8,0);
    glutWireCube(1.1); //Draw the cube
    glPopMatrix();

    glPushMatrix();
    glLoadIdentity();
    glTranslatef(0, 1.2, 0);
    glRotatef(90, 1, 0, 0);

    glColor3f(1,1,1);
    glutWireSphere(0.6, 20, 20); //Draw the sphere
    glPopMatrix();

    //draw here
    //glutSwapBuffers();
    glutPostRedisplay();
    glFlush();

}
void reshape (int w, int h){
    glViewport(0,0,w ,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, (float)w/(float)h, 1.5, 10);
    gluLookAt(1.5, 2.5, 4, 
              0, 0.6, 0, 
              0, 1, 0); //Orient the camera
    glRotatef(5, 0, 0, 1);
    glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char * argv[])
{
    initView(argc,argv);
    glutDisplayFunc(draw);
    glutReshapeFunc(reshape);
    glutMainLoop();
}

4899
2017-09-27 10:18


起源

只是一个猜测,但也许尝试添加 Sleep(1) 在你的 draw 功能 - Bartek Banachewicz
这实际上有效!你知道这项工作的技术原因以及为什么我需要它而我的同学不这样做? - aPerfectMisterMan


答案:


解:

似乎使用简单的解决方案 Sleep(1) 在渲染功能中工作。你也问过为什么 - 我不确定我能否妥善解决这个问题,但这是我最好的猜测:

为什么它甚至有效?

您的同学可以在其驱动程序中默认启用VSync。这导致他们的代码只能以屏幕刷新的速度运行,最可能是60 fps。它给你大约16毫秒来渲染帧,如果代码是有效的(例如,2毫秒渲染),它会留出足够的时间让CPU执行其他与操作系统相关的操作,例如移动窗口。

现在,如果禁用垂直同步,程序将尝试渲染尽可能多的帧,从而有效地阻塞所有其他进程。我建议你使用Sleep,因为它揭示了这个特殊问题。如果它是1或3毫秒并不重要,它真正做的是说“嘿,CPU,我现在没有做任何特别的事情,所以你可以做其他事情”。

但这不是我的计划放慢了吗?

使用睡眠是一种常见的技术。如果你担心每帧丢失1毫秒,你也可以试试 Sleep(0),因为它应该完全相同 - 给CPU腾出空余时间。您也可以尝试启用垂直同步并验证我的猜测是否正确。

作为旁注,您还可以查看有和没有睡眠的CPU使用率图表。它应该是100%(或双核CPU上的50%)(尽可能快地运行),而且要低得多,具体取决于您的程序要求和CPU的速度。

关于睡眠的补充说明(0)

休眠间隔过后,线程就可以运行了。如果指定0毫秒,则线程将放弃其时间片的剩余部分但仍保持准备状态。请注意,不保证立即运行就绪线程。因此,线程可能在睡眠间隔过去一段时间后才运行。 - 来自于 这里

另请注意,在Linux系统上,行为可能略有不同;但我不是Linux专家;或许路人可以澄清一下。


11
2017-09-27 11:35



+1很好的解释。睡眠(0) 产量 线程执行,进行部分“协作”线程调度(a.o.t. 先发制人 线程调度)。 - sehe
关于Linux。放弃POSIX上的CPU时间的功能是 sched_yield。它不需要参数,与调用具有相同的效果 Sleep(0) 在Windows上。 - datenwolf