Разрывы/заикания изображения SDL

Прежде всего, позвольте мне прояснить некоторые вещи:

  1. у меня монитор 60 герц
  2. Я ограничиваю свой FPS до 60, и, похоже, он работает правильно.
  3. У меня активен флаг двойной буферизации
  4. Я сам сделал бэкбуфер и обязательно отрисовывал на него, а потом на экран
  5. Эта проблема возникает как в полноэкранном, так и в оконном режиме.

Это моя основная функция (в ней весь код):

SDL_Init(SDL_INIT_EVERYTHING);

SDL_Surface * backbuffer = NULL;
SDL_Surface * screen = NULL;
SDL_Surface * box = NULL;
SDL_Surface * background = NULL;

SDL_Rect * rect = new SDL_Rect();

double FPS = 60;
double next_time;
bool drawn = false;

rect->x = 0;
rect->y = 0;

screen = SDL_SetVideoMode(1920, 1080, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN);
if(screen == NULL) {
    return 0;
}
background = SDL_LoadBMP("background.bmp");
box = SDL_LoadBMP("box.bmp");
if((background == NULL) || (box == NULL)) {
    return 0;
}

background = SDL_DisplayFormat(background);
box = SDL_DisplayFormat(box);

backbuffer = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN,
    1920,
    1080,
    32,
    0,
    0,
    0,
    0);

if(backbuffer == NULL) {
    return 0;
}
next_time = (double)SDL_GetTicks() + (1000.0 / FPS);
while(true) {
    if(!drawn) {
        SDL_BlitSurface(background, NULL, backbuffer, NULL);
        SDL_BlitSurface(box, NULL, backbuffer, rect);
        rect->x += 3;
        drawn = true;
    }
    if((Uint32)next_time <= SDL_GetTicks()) {
        SDL_BlitSurface(backbuffer, NULL, screen, NULL);
        SDL_Flip(screen);
        next_time += 1000.0 / FPS;
        drawn = false;
    }
}

SDL_FreeSurface(backbuffer);
SDL_FreeSurface(background);
SDL_FreeSurface(box);
SDL_FreeSurface(screen);
SDL_Quit();
return 0;

Я знаю, что этот код выглядит не очень хорошо, это был просто тест, чтобы понять, почему это происходит со мной всякий раз, когда я пишу что-нибудь на SDL.

Пожалуйста, игнорируйте уродливый код и дайте мне знать, если у вас есть какие-либо идеи о том, что может быть причиной того, что изображение движущегося белого квадрата на черном фоне имеет странные артефакты и кажется, что оно разрывается / заикается.

Если вам нужна дополнительная информация, дайте мне знать, и я обновлю то, что необходимо.

РЕДАКТИРОВАТЬ:

  • Если я не ограничиваю свой FPS, он работает со скоростью 200-400 кадров в секунду, что, вероятно, означает, что SDL_Flip не ждет обновления экрана.

  • Я не знаю, используются ли флаги, которые я пишу, на самом деле.

  • Я проверил свои флаги и, кажется, не могу получить флаги SDL_HWSURFACE и SDL_DOUBLEBUF. Это может вызвать проблему?


person Roy Spector    schedule 17.12.2013    source источник
comment
как ограничить частоту кадров до 60?   -  person Raxvan    schedule 17.12.2013
comment
@Raxvan Это в исходном коде...   -  person Roy Spector    schedule 17.12.2013
comment
на самом деле я вижу это сейчас, какую частоту кадров вы получите, когда уберете ограничение fps? Мне интересно, потому что мой ответ будет основан на результате :)   -  person Raxvan    schedule 17.12.2013
comment
Откуда вы знаете, что запрошенные вами видеофлажки действительно использовались?   -  person this    schedule 17.12.2013
comment
200–400 кадров в секунду при снятом ограничении, поэтому, вероятно, он не ждет обновления экрана на SDL_Flip, и я не знаю, действительно ли используются флаги.   -  person Roy Spector    schedule 17.12.2013
comment
Ограничения частоты кадров недостаточно — вы можете отображать стабильные 60 кадров в секунду, но видеть разрывы на каждом кадре. Что вам нужно сделать, так это синхронизировать ваш рендеринг с обновлением - вам нужно включить vsync. (Я не знаю, как это сделать с помощью SDL, поэтому я прокомментировал, а не ответил).   -  person JoeG    schedule 17.12.2013
comment
Да, я почти уверен, что флаги SDL_HWSURFACE и SDL_DOUBLEBUF должны вызывать это. Но я не могу на самом деле получить ни один из этих флагов. Я проверил это с помощью SDL_GetVideoSurface.   -  person Roy Spector    schedule 17.12.2013


Ответы (1)


Двойная буферизация SDL на HW_SURFACE

Это решение моей проблемы. Все, что мне нужно было сделать, это добавить эту строку:

SDL_putenv("SDL_VIDEODRIVER=directx");

Спасибо за комментарии, они помогли мне найти решение. :D

Думаю, мне тоже стоит проверить SDL 2.0...

person Roy Spector    schedule 17.12.2013
comment
Обратите внимание, что это не гарантирует наличие HW_SURFACE в каждой системе. Если вам нужен реальный аппаратный контроль, используйте opengl. - person this; 18.12.2013