我正在Linux上使用X11学习OpenGL,遇到了一个问题,我没有意识到出了什么问题。
当我在屏幕上绘制一个覆盖大空间的对象时,它会快速渲染并以高帧率更新到 X11。但是当我将相机远离物体或绘制一个小物体时,它会覆盖屏幕上的小空间(例如,像素区域),它的更新速度真的很慢。它绘制得越小,更新帧的速度越慢。
当我离 1x1 平面 100 个单位时,它达到每秒 1 帧左右。
这是代码:
XGetWindowAttributes(dpy, win, &gwa);
glViewport(0, 0, Width, Height);
SetupViewMatrix();
Camera * cam = mainCamera.GetComponent<Camera>();
if(cam != NULL){
CamPose(cam->eyePose, cam->pivotPoint, cam->upDirection);
} else {
CamPose(Vector3::back(), Vector3::forward(), Vector3::up());
}
//glViewport(0, 0, gwa.width, gwa.height);
ClearScreen();
GLfloat cube[] = {
-0.05f, -0.05f, -0.05f,
-0.05f, 0.05f, -0.05f,
0.05f, 0.05f, -0.05f,
-0.05f, -0.05f, -0.05f,
0.05f, 0.05f, -0.05f,
0.05f, -0.05f, -0.05f,
};//*/
GLfloat colors[] = {
0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
};//*/
glVertexPointer(3, GL_FLOAT, 0, cube);
glColorPointer(4, GL_FLOAT, 0, colors);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glXSwapBuffers(dpy, win);
glFlush();
和 SetupViewMatrix 函数:
void WindowDrawer::SetupViewMatrix(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65, (float)Width/Height, 0.1, 1000);
};
和清除屏幕功能:
void WindowDrawer::ClearScreen(){
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
编辑: 我正在添加更多代码来提供帮助。 这是我用来创建窗口的 Init 函数:
void WindowDrawer::InitX11OpenGL(){
dpy = XOpenDisplay(NULL);
if(dpy == NULL){
printf("ntCannot Connect to X servernn");
exit(0);
}
root = DefaultRootWindow(dpy);
vi = glXChooseVisual(dpy, 0, att);
if(vi == NULL){
printf("ntno appropriate visual foundnn");
exit(0);
} else {
printf("nvisual %p selectedn", (void *)vi->visualid);
}
cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
swa.colormap = cmap;
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask;
win = XCreateWindow(dpy, root, 0, 0, 720, 480, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
XMapWindow(dpy, win);
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
glXMakeCurrent(dpy, win, glc);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
我用来创建事件循环的这个:
void WindowObject::DealWithEvents(){
if(XEventsQueued(windowDrawer.dpy, QueuedAlready)){
XNextEvent(windowDrawer.dpy, &xev);
eventHandler.RouteXEvents(&xev, windowDrawer.dpy);
} else {
memset(&redrawEvent, 0, sizeof(redrawEvent));
redrawEvent.type = Expose;
redrawEvent.xexpose.window = windowDrawer.win;
XSendEvent(windowDrawer.dpy, windowDrawer.win, False, ExposureMask, &redrawEvent);
XFlush(windowDrawer.dpy);
eventHandler.RouteXEvents((XEvent *)&redrawEvent, windowDrawer.dpy);
}
};
好吧,正如我所看到的,这不是性能问题,而是更新队列(或类似)问题。因为当物体靠近相机时,比如说,它使用大的屏幕空间,它应该画得更快,但是当它在屏幕空间变小时,它会线性减慢屏幕更新速度。我正在打印事件以进行曝光,按键和按键释放,所有这些事件都运行得很快,就像它应该的那样,只有屏幕区域更新不遵循系统的速度。
哦,我发现了错误,我正在为此提出自己的问题。我很惭愧地告诉这个,因为它是如此愚蠢,正如一个真正的图形新手所期望的那样:/
问题是我正在使用小屏幕,在低 ppi 显示器上工作。此外,屏幕上的形状是一个完美的正方形(它不会在像素上绘制对角线边缘),因此当对象很小时,需要很长时间才能重新绘制边框像素。计算机图形学使用一些抗锯齿效果来平滑这种效果,而原始 opengl 则没有,因此它会导致与我过去看到的效果完全不同的效果。我花了很长时间才意识到这只是像素细节问题......
谢谢大家的任何帮助。
这里有一些东西看起来不像是"优化"正确。例如,您使用gluPerspective。这已被弃用了 10 年!!我们不希望这样!为什么不在你的相机类中制作自己的视图矩阵呢?:)
另外,我不确定这是否是问题所在。但似乎你在RENDER循环中调用glClearColor。这当然不好。把它放在你的初始化函数中。这可能是问题所在。