Двойная буферизация не работает OpenGL

Я хотел сделать его двойным буфером, но он все равно мерцает. По сути, это модифицированная версия образца OpenNI UserTracker, который хорошо работает на моем компьютере, но я не думаю, что удалил или значительно изменил какие-либо важные команды OpenGL до такой степени, что они могли бы работать по-другому. Я использую Ubuntu 10.04 на своем компьютере.

#include <GL/glut.h>
#include <GL/glx.h>
void DrawRectangle(float topLeftX, float topLeftY, float bottomRightX, float bottomRightY){
    GLfloat verts[8] = { topLeftX, topLeftY,
        topLeftX, bottomRightY,
        bottomRightX, bottomRightY,
        bottomRightX, topLeftY };
    glVertexPointer(2, GL_FLOAT, 0, verts);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void DrawTexture(float topLeftX, float topLeftY, float bottomRightX, float bottomRightY){
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
    DrawRectangle(topLeftX, topLeftY, bottomRightX, bottomRightY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void DrawLimb(KinectUserData player, int a, int b){
    glBegin(GL_LINES);
        glVertex3d((player.joints[a].x/500), (player.joints[a].y/400), 0);
        glVertex3d((player.joints[b].x/500), (player.joints[b].y/400), 0);
    glEnd();
}
void Draw(KinectData kdata){
    glColor4f(0.75,0.75,0.75,1);
    glEnable(GL_TEXTURE_2D);
    DrawTexture(320,240,0,0);   
    glDisable(GL_TEXTURE_2D);
    for (uint i = 0; i < kdata.size(); i++){
        glColor4f(1-Colors[kdata[i].getID()%nColors][0], 1-Colors[kdata[i].getID()%nColors][1], 1-Colors[kdata[i].getID()%nColors][2], 1);
        DrawLimb(kdata[i], 0, 1);
        DrawLimb(kdata[i], 1, 3);
        DrawLimb(kdata[i], 3, 4);
        DrawLimb(kdata[i], 4, 5);
        DrawLimb(kdata[i], 1, 6);
        DrawLimb(kdata[i], 6, 7);
        DrawLimb(kdata[i], 7, 8);
        DrawLimb(kdata[i], 3, 2);
        DrawLimb(kdata[i], 6, 2);
        DrawLimb(kdata[i], 2, 9);
        DrawLimb(kdata[i], 9, 10);
        DrawLimb(kdata[i], 10, 11);
        DrawLimb(kdata[i], 2, 12);
        DrawLimb(kdata[i], 12, 13);
        DrawLimb(kdata[i], 13, 14);
        DrawLimb(kdata[i], 9, 12);
    }
}
void glutDisplay(void){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
    Draw(data); //data is correctly intialized in other functions
    glPopMatrix();
    glutSwapBuffers();
    glutPostRedisplay();
}
void glInit(int * pargc, char ** argv){
    glutInit(pargc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(GL_WIN_SIZE_X, GL_WIN_SIZE_Y);
    glutCreateWindow("Tracker");
    glutSetCursor(GLUT_CURSOR_NONE);
    glutDisplayFunc(glutDisplay);
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
}
int main(int argc, char** argv){
    glInit(&argc, argv);
    glutMainLoop();
}

person user1469474    schedule 31.07.2012    source источник
comment
Ваша функция glutDisplay, кажется, отключена, можете ли вы обновить свой пост полностью?   -  person vmpstr    schedule 31.07.2012
comment
Извини за это. Теперь это исправлено.   -  person user1469474    schedule 01.08.2012
comment
Я заменил функцию рисования просто треугольником, и он у меня работает... вообще не мерцает. Если я удалю вызовы GLUT_DOUBLE и swap buffers, он снова начнет мерцать, как сумасшедший...   -  person vmpstr    schedule 01.08.2012
comment
Почему вы используете glutDisplayFunc и glutPostRedisplay? Вы можете передать свою функцию glutDisplay glutIdleFunc и удалить glutPostRedisplay . Также избегайте написания собственных имен функций, начинающихся с glut! Это сбивает с толку.   -  person Shahbaz    schedule 01.08.2012
comment
@Shahbaz: я только что попробовал это сделать, и мерцание стало еще хуже. Кроме того, извините за имена; Я просто не удосужился изменить имена функций, когда модифицировал существующий код.   -  person user1469474    schedule 01.08.2012
comment
Вы пытались добавить сон в свою функцию? Что-то, чтобы изменить (возможно) скорость 1000 вызовов в секунду до 60? Кроме того, обновлен ли драйвер вашей видеокарты?   -  person Shahbaz    schedule 01.08.2012
comment
Как добавить функцию сна? У меня очень ограниченные знания об OpenGL. Будет ли ответ genpfault относиться к тому же самому? Кроме того, я не знаю, как узнать, обновлена ​​ли видеокарта, но я предполагаю, что это так.   -  person user1469474    schedule 01.08.2012
comment
Где соответствующий glPopMatrix() для glPushMatrix() в glutDisplay()? Матричный стек обычно имеет только 32 слота.   -  person genpfault    schedule 02.08.2012
comment
Я просто добавил это, но особого эффекта это не дало. Кроме того, исходный код, который я модифицировал, имел только glPushMatrix(), а не glPopMatrix, но все равно работал без сбоев.   -  person user1469474    schedule 02.08.2012
comment
В *nix в <unistd.h> есть функция usleep (в микросекундах). В Windows есть функция Sleep (в миллисекундах), которую вы сможете найти в MSDN. Glut имеет более точные таймеры, которые можно использовать (но, вероятно, сон здесь легче протестировать). Кроме того, вы можете выяснить марку/модель вашей видеокарты, перейти на ее веб-сайт и загрузить последнюю версию драйвера.   -  person Shahbaz    schedule 02.08.2012
comment
Добавление сна сделало мерцание менее заметным, но оно все еще присутствует (если только я не использую действительно большое число и не делаю его очень медленным). Это лучше, чем раньше, но есть ли у вас другие идеи?   -  person user1469474    schedule 02.08.2012
comment
На самом деле, сон, вероятно, достаточно хорош. Мерцание все равно есть, но не сильно мешает.   -  person user1469474    schedule 02.08.2012


Ответы (1)


Я хотел сделать его двойным буфером, но он все равно мерцает.

Это отдельные вопросы. Ваш код использует двойную буферизацию.

Мерцание скорее всего из-за отсутствия вертикальной синхронизации. К сожалению, включение/отключение вертикальной синхронизации очень зависит от платформы.

person genpfault    schedule 31.07.2012
comment
Я попытался добавить glXSwapInterval (или glXSwapIntervalSGI) в свой код, но компилятор не распознает эти функции. Что мне нужно включить? Я уже добавил #include ‹GL/glx.h›, но он все еще не распознает их. - person user1469474; 01.08.2012
comment
Хорошо, я включил glxew.h, и теперь я получаю сообщение об ошибке при вызове glXSwapIntervalSGI(1): неопределенная ссылка на __glewXSwapIntervalSGI. Я нашел строку extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; в glxew.h, но не знаю, как ее инициализировать, так как не знаю, что такое PFNGLXSWAPINTERVALSGIPROC. У тебя есть какой-нибудь совет? - person user1469474; 01.08.2012
comment
Я также могу просто создать неинициализированный __glewXSwapIntervalSGI, но тогда я просто получаю segfault, так как он вызывается glXSwapIntervalSGI. - person user1469474; 01.08.2012
comment
Вы собирали GLEW из исходников или используете версию из репозиториев Ubuntu? Если вы используете версию репо, просто дайте ссылку на GLEW через -lGLEW или, может быть, -lglew, не знаю, как это пишется с большой буквы. - person genpfault; 01.08.2012
comment
Кроме того, не забудьте инициализировать GLEW перед началом использования указателей функций. - person genpfault; 01.08.2012
comment
Извините, у меня нет огромного опыта в программировании, и я ничего не вижу из быстрого поиска в гугле. Против чего идет ссылка? И я использую версию репо. - person user1469474; 01.08.2012
comment
Связывание. Что-то вроде g++ main.cpp -o main -lGLEW -lGLU -lGL скажет ld связать GLEW, GLU и GL после завершения компиляции main.cpp. - person genpfault; 01.08.2012
comment
Спасибо, теперь у меня работает. Я ценю всю вашу помощь. - person user1469474; 01.08.2012
comment
На самом деле, я немного поторопился раньше. Теперь он работает, но все еще мерцает. Почему вы думаете, что это не проблема с двойной буферизацией? - person user1469474; 01.08.2012
comment
Если бы двойная буферизация была испорчена, вы бы не увидели ничего :) Вам нужно заставить ОС синхронизировать ваши буферные свопы с вертикальным повтором, чтобы они не происходили в середине сканирования. glXSwapIntervalSGI() соблюдается не всеми водителями. Какую видеокарту и драйвера используете? - person genpfault; 01.08.2012
comment
Я использую карту Radeon, и я использовал glXSwapIntervalMESA(), а не SGI. Однако я просматривал множество сайтов, и те, на которых упоминалась vsync, имели в виду исправление разрывов экрана, а не мерцание изображений. - person user1469474; 02.08.2012