Плавная анимация с синхронизацией (OpenGL) - PullRequest
2 голосов
/ 10 февраля 2012

Я программирую маленькую игру с opengl и C. Я столкнулся с проблемой: из-за отсечения ... моя анимация (фактически основанная на glutTimerFunc) не имеет постоянной частоты кадров. Переменная fps не проблема, но анимация затрагивается, поэтому она не соответствует времени, тогда: fps1, pos1; fps2, pos2; fps3, POS3 ... Но если fps не является регулярным, то анимация - нет. Я бы реализовал это так: fps1, pos1; (если fps1 не нарисован) fps2, pos1; (рисование fps1 закончилось, так что теперь, потому что я пропустил кадр) fps3, pos3.

как я могу это сделать? я бы использовал функцию clock (), но она всегда дает 0

ps: как заставить v-sync в opengl?

1 Ответ

1 голос
/ 10 февраля 2012

Будут ли обновления OpenGL синхронизированы с вертикальным возвратом, будет сообщаться в зависимости от платформы, поскольку это связано с тем, как ваша платформа привязала OpenGL к себе.Так что в конструкторе интерфейсов на Mac установлен флажок, есть расширение WGL под названием WGL_EXT_swap_control over в Windows и расширение GLX в X11.

Предполагается, что у вас есть некоторые средства для установки обратного вызова, который запускается при вертикальном возврате(например, через CVDisplayLink на Mac; к сожалению, я не знаком с Windows / Linux-эквивалентами), и вы хотите, чтобы ваша физика работала с постоянным числом шагов в секунду, вы могли бы написать что-то вроде:

void myRetraceFunction()
{
    static unsigned int timeError = 0;
    static unsigned int timeOfLastFrame = 0;

    unsigned int timeNow = getTimeNow(); // assume this returns in ms

    // Get time since last frame.
    // Since we ignore overflow here, we don't care that the result of
    // getTimeNow presumably overflows.
    unsigned int timeSinceLastFrame = timeNow - timeOfLastFrame;

    // Store this so that we get correct results next time around.
    timeOfLastFrame = timeNow;

    // Establish the number of times to update physics per second, as the
    // name says. So supposing it has been 0.5 of a second since we last
    // drew, we'd want to perform 0.5*200 physics updates
    const unsigned int numberOfTimesToUpdatePhysicsPerSecond = 200;

    // calculate updates as (updatesPerSecond * timeSinceLastFrame / 1000),
    // because we're assuming time is in milliseconds and there are 1000
    // of them in a second. What we'll do though is preserve any amount we'd
    // lose by dividing here, so that errors balance themselves.
    //
    // We assume that timeSinceLastFrame will be small enough that we won't
    // overflow here.
    unsigned int timeSinceLastFrameNumerator =
          timeSinceLastFrame * numberOfTimesToUpdatePhysicsPerSecond
          + timeError;

    // calculate how much of the numerator we're going to lose to
    // truncation, so that we add it next frame and don't lose time
    timeError = timeSinceLastFrameNumerator % 1000;

    // calculate how many physics updates to perform
    unsigned int physicsUpdatesToPerform = timeSinceLastFrameNumerator / 1000;

    // do the physics work...
    while(physicsUpdatesToPerform--)
       updatePhysics();

    // ... and draw a frame
    drawFrame();
}

То, что timeError, должно регулировать против проблем округления.Например, предположим, что вы работаете с постоянными 70 кадрами в секунду и хотите обновления физики 60 раз в секунду.Если вы игнорируете ошибку, которая накапливается, то вы фактически запускаете нулевые обновления физики в секунду, поскольку в каждый момент времени код приходит к выводу, что время, прошедшее с момента последнего отрисовки кадра, было недостаточно продолжительным для обновления физики.было необходимо.И в противном случае у вас возникнут проблемы с алиасами, если вы пойдете другим путем, с любой частотой кадров, которая не является целочисленным делителем частоты обновления физики.

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

Если у вас нет возможности вообще блокировать вертикальный обратный ход, вы можете установить таймер нацелевую частоту кадров и представьте, что это вертикальная синхронизация с возвратом.Вы можете просто выдвигать кадры настолько быстро, насколько это возможно, но, скорее всего, вы будете получать жалобы с кем-либо, у кого есть ноутбук или другая машина, и это довольно очевидно, когда появляются фанаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...