Каков обычный способ управления частотой кадров?
Я новичок в графике, поэтому я не знаю, как люди обычно контролируют частоту кадров для рендеринга.
Я имею в виду, как вы можете настроить приложение для рендеринга, скажем, 30 кадров в секунду?
Там, вероятно, много API, которые предлагают такую вещь, но мне нужно закодировать ее с нуля.
Ответы
Ответ 1
Существует два "обычных" способа "управления" частотой кадров, и это не так просто.
Первым и более управляющим из двух, и что-то, что обычно является необязательным, является VSync. Это заставляет видеокарту только выталкивать новый кадр, когда монитор обновляется. Многие мониторы обновляются с частотой 60 Гц, поэтому вы получаете 60 FPS.
Это работает достаточно хорошо, чтобы ограничить частоту кадров, чтобы контролировать частоту обновления, но когда частота кадров падает ниже уровня обновления, она принудительно переходит к следующему краю. Таким образом, по мере того, как частота кадров начинает немного падать, вы теряете довольно много потенциального времени рендеринга, потому что оно принудительно составляет 60, затем 30, затем 20 и т.д.
(немного информации о vsync в DirectX и OpenGL)
Второй метод, обычно используемый (с добавлением vsync, необязательно добавленный), не ограничивает частоту кадров. Вместо этого настройте свой код для обработки различий. Это намного более гибко в долгосрочной перспективе и, как правило, лучшее кодирование, IMO и намного проще, чем попытка заставить определенный счет FPS.
Предполагая, что у вас есть простой цикл рендеринга, он начинает выглядеть примерно так:
while ( gameloop )
{
float framedelta = ( timeNow - timeLast )
timeLast = timeNow;
for each ( GameObject object in World )
{
object->Animate(framedelta);
object->Move(speed * framedelta)
}
render();
}
Вы хотите посмотреть разницу во времени/время, пройденное/дельта, и работать оттуда. Разрешить масштабирование кадров на основе аппаратного обеспечения и настроек (слишком много вариантов для прогнозирования или обработки даже половины), и заставить вашу игру работать с этим, а не контролировать его. Намного легче для вас и более гибким и стабильным на практике.
Ответ 2
Типичный способ получения прогнозируемой (если не постоянной) частоты кадров (с видео или 3D-графикой) описан в следующем псевдокоде.
Алгоритм
- Подготовьте следующий кадр (рендеринг в back-buffer);
- Сон на оставшуюся часть временного фрагмента;
- Запросить отображение кадра (своп переднего и заднего буферов).
Обратите внимание на положение операции сна. Он зажат между подготовкой и отображением того же кадра. Это основной ключ к постоянной частоте кадров! Вы хотите, чтобы кадр отсчитывался в общем временном фрагменте для отображения кадра.
Существует несколько вариантов реализации каждого из этих этапов (выбор операции сна на основе его разрешения, надежности и т.д.), но ядро есть.
Советы по дополнительной надежности
- Не вызывайте функцию сна один раз для всего интервала. Определите константу с максимальной ошибкой, которую вы готовы принять, и многократно спя себя на периоды этого интервала, пока оставшееся время не станет меньше или равно этой сумме.
- Не пугайтесь, чтобы иногда бросать кадр, когда вы знаете, что не сможете подготовить следующий кадр вовремя. Это визуально более привлекательно для пропуска кадра, чем для получения переменной частоты кадров.
- Если вы можете избежать фоновых потоков в однопроцессорной системе, избегайте их. Использование рабочих потоков действительно испортит надежность вашей функции сна. Лучший подход заключается в том, чтобы разделить фоновые работы на небольшие куски и выполнить эту работу вместо сна.
Первый легко реализовать и может быть скрыт в вспомогательной функции. Второй - немного более трогательный, поскольку он требует, чтобы вы, помимо прочего, сохраняли статистику средней скорости рендеринга. Третье трудно реализовать, так как часто трудно предсказать, сколько времени потребуются разные задачи. Он обычно реализуется только в системах реального времени с жесткими ограничениями.