Я изучаю OpenGL с X11 на Linux, и у меня возникла проблема, я не понимаю, что не так.
Когда я рисую объект, занимающий большое место на экране, он быстро рендерится и обновляется до X11 с высокой частотой кадров. Но когда я отодвигаю камеру от объекта или рисую маленький объект таким образом, чтобы он занимал небольшое пространство на экране (скажем, в области пикселей), обновление происходит очень медленно. Чем меньше он рисует, тем медленнее он обновляет кадр.
Когда я нахожусь на расстоянии 100 единиц от плоскости 1×1, она достигает около 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);
};
и функция ClearScreen:
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("\n\tCannot Connect to X server\n\n");
exit(0);
}
root = DefaultRootWindow(dpy);
vi = glXChooseVisual(dpy, 0, att);
if(vi == NULL){
printf("\n\tno appropriate visual found\n\n");
exit(0);
} else {
printf("\nvisual %p selected\n", (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);
}
};
Ну, как я вижу, это не проблема производительности, а проблема с очередью обновления (или что-то в этом роде). Причина, когда объект находится рядом с камерой, скажем, он использует большое пространство на экране, он рисует быстрее, чем должен, но когда он становится меньше в пространстве на экране, он линейно замедляет обновления экрана. Я печатаю события для выставления, нажатия клавиш и освобождения клавиш, все эти события проходят быстро, как и должно быть, только обновления области экрана не следуют за скоростью системы.
О, я нашел ошибку, и я задаю свой вопрос для этого. Мне стыдно об этом говорить, потому что это было так глупо, как и ожидал действительно новичок в графике: /
Проблема в том, что я работаю с небольшим экраном на мониторе с низким разрешением. Кроме того, форма на экране является идеальным квадратом (он не рисует диагональные края на пикселях), поэтому, когда объект маленький, требуется много времени, чтобы перекрасить пиксели границы. Компьютерная графика использует некоторый эффект сглаживания, чтобы сгладить этот эффект, а необработанный opengl — нет, поэтому он вызывает эффект, отличный от того, что я привык видеть. Мне потребовалось много времени, чтобы понять, что это всего лишь проблема деталей пикселя …
Спасибо всем за любую помощь.
Здесь есть кое-что, что не похоже на «оптимизированную» правильно. Например, вы используете gluPerspective. Это устарело в течение 10 лет! Мы этого не хотим! Почему бы просто не создать собственную матрицу просмотра в своем классе камеры? 🙂
Кроме того, я не уверен, что это проблема. Но, похоже, вы вызываете glClearColor внутри цикла RENDER. Что, конечно, не хорошо. Поместите это в вашу функцию инициализации. Это возможно его проблема.