我刚刚开始使用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();
}
答案 0 :(得分:12)
<强>解决方案:强>
似乎在渲染功能中使用Sleep(1)
的简单解决方案有效。你也问过为什么 - 我不确定我能否妥善解决这个问题,但这是我最好的猜测:
为什么它会起作用?
您的同学可以在其驱动程序中默认启用VSync。这导致他们的代码只能以屏幕刷新的速度运行,最可能是60 fps。它给你大约16毫秒来渲染帧,如果代码是有效的(比如2毫秒渲染),它会留出足够的时间让CPU做其他与操作系统相关的东西,比如移动你的窗口。
现在,如果禁用垂直同步,程序将尝试渲染尽可能多的帧,从而有效地阻塞所有其他进程。我建议你使用Sleep,因为它揭示了这个特殊问题。如果它是1或3毫秒并不重要,它真正做的是说“嘿,CPU,我现在没有做任何特别的事情,所以你可以做其他事情。”
但这不会减慢我的计划吗?
使用睡眠是一种常见技术。如果您担心每帧丢失1 ms,您也可以尝试放置Sleep(0)
,因为它应该完全相同 - 将剩余时间交给CPU。您也可以尝试启用垂直同步并验证我的猜测是否正确。
作为旁注,您还可以查看有和没有睡眠的CPU使用率图表。它应该是100%(或双核CPU上的50%)(尽可能快地运行),而且要低得多,具体取决于您的程序要求和CPU的速度。
关于睡眠(0)的补充说明
休眠间隔过后,线程就可以运行了。如果指定0毫秒,则线程将放弃其时间片的剩余部分但仍保持准备状态。请注意,不保证立即运行就绪线程。因此,线程可能在睡眠间隔过去一段时间后才会运行。 - 它来自here。
另请注意,在Linux系统上,行为可能略有不同;但我不是Linux专家;或许路人可以澄清。