Икота в OpenGL ES. Какова правильная реализация?

Я использую OpenGL ES для создания игры на iPhone. К сожалению, я вижу небольшую (и нерегулярную) икоту.

Я использую таймер со сном, вызывая функцию отрисовки каждые 60 секунд, чтобы гарантировать стабильную частоту кадров. Я попытался изменить момент времени, когда мой таймер пробуждается от сна, давая функции рисования больше времени для выполнения. Икоты становятся меньше, когда функции рисования уделяется больше времени. С 8 миллисекундами анимация почти плавная. Мои выводы:

  1. По-видимому, предоставление графическому процессору большего времени для выполнения фактического рисования приводит к (почти) идеальной плавной анимации.
  2. Рисование точно в конце моего кадра приводит к заиканию, икоте и тому подобному.

Теперь, когда я это знаю, я не знаю, что делать дальше. У меня есть две противоречивые идеи о причине такого поведения:

  1. Во-первых, могут ли команды OpenGL мешать отрисовке предыдущего кадра? Насколько я понимаю, этого не может быть, поскольку команды сохраняются и будут выполняться только тогда, когда команда рисования дано.
  2. Во-вторых, может ли колебание времени команд рисования привести к тому, что таймер пропустит такт?

Так какое же объяснение более вероятно? Или ни то, ни другое? Конечно, я мог бы просто попытаться поместить функцию рисования в отдельный поток и посмотреть, решит ли это мою проблему. Но я надеюсь понять больше OpenGL.

Это вызываемая функция и объясняет, о чем я говорю:

- (void) drawView
{
    // measure time with mach_absolute_time

    // gameEngine update    
    // OpenGL commands (translate, rotate, drawArrays etc.) 

    // end measure time with mach_absolute_time
    // usleep(animationInterval - duration  - constant) 
    // constant is the time to start executing

    // draw
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];    
}

person Kriem    schedule 07.05.2009    source источник


Ответы (1)


Вы можете прочитать эту статью об игровых циклах, которая многое объясняет. Обычно лучшим решением является вызов процедуры рисования в бесконечном цикле внутри отдельного потока (см. этот вопрос) и обновить базовую игровую модель в соответствии со временем, прошедшим с момента последнего обновления. Это обеспечит плавность движений.

Редактировать: Что касается источника «икоты», то он, вероятно, не имеет ничего общего с OpenGL. При 60 кадрах в секунду мы говорим о 1/60 секунды ≈ 17 мс на кадр. Это плотный график, который легко пропустить, потому что на устройстве запущены другие процессы. Safari или Mail.app просыпаются в фоновом режиме, устройство какое-то время думает и теперь ваш кадр занимает 30 мс, а то и намного больше. Это очень легко заметить, если ваша модель ожидает совершенно стабильную частоту кадров. Решение состоит в том, чтобы обновить модель в соответствии с прошедшим реальным временем, как я написал выше. Связанная статья объясняет все это подробно.

person zoul    schedule 07.05.2009
comment
Пожалуйста. Есть также хорошие идеи в движке Cocos2D для iPhone (tinyurl.com/5hpjba), особенно если вы делаете 2D. - person zoul; 07.05.2009
comment
Я. Проверим это. Еще раз спасибо! - person Kriem; 07.05.2009