Какой хороший алгоритм подсчета кадров в секунду в игре? Я хочу показать это числом в углу экрана. Если я просто посмотрю, сколько времени потребовалось для рендеринга последнего кадра, число изменится слишком быстро.
Бонусные баллы, если ваш ответ обновляет каждый кадр и не сходится по-разному, когда частота кадров увеличивается или уменьшается.
last_frame
не означает (или, по крайней мере, не должно означать) продолжительность предыдущего кадра; это должно означать значение,time
которое вы рассчитали для последнего кадра. Таким образом, будут включены все предыдущие кадры, причем самые последние кадры будут иметь наибольший вес.Это то, что я использовал во многих играх.
источник
tickindex = (tickindex + 1) % MAXSAMPLES;
Ну конечно
Но, как вы указываете, время, необходимое для рендеринга одного кадра, сильно различается, и с точки зрения пользовательского интерфейса обновление значения fps с такой частотой кадров вообще неприменимо (если только число не очень стабильное).
Вероятно, вам нужно скользящее среднее или какой-то счетчик биннинга / сброса.
Например, вы можете поддерживать структуру данных очереди, в которой хранится время рендеринга для каждого из последних 30, 60, 100 или каких-то дополнительных кадров (вы даже можете спроектировать ее так, чтобы ограничение можно было регулировать во время выполнения). Чтобы определить приличное приближение fps, вы можете определить средний fps для всех времен рендеринга в очереди:
Когда вы заканчиваете рендеринг нового кадра, вы ставите в очередь новое время рендеринга и удаляете из очереди старое время рендеринга. В качестве альтернативы, вы могли исключить из очереди только тогда, когда общее время рендеринга превысило некоторое предустановленное значение (например, 1 секунду). Вы можете поддерживать «последнее значение частоты кадров в секунду» и последнюю обновленную метку времени, чтобы при желании можно было указать, когда следует обновлять число кадров в секунду. Хотя со скользящим средним, если у вас есть согласованное форматирование, печать «мгновенного среднего» fps для каждого кадра, вероятно, будет приемлемой.
Другой способ - установить счетчик сброса. Поддерживайте точную (миллисекундную) метку времени, счетчик кадров и значение fps. Когда вы закончите рендеринг кадра, увеличьте счетчик. Когда счетчик достигает заданного предела (например, 100 кадров) или когда время с момента отметки времени прошло некоторое заданное значение (например, 1 секунду), вычислите частоту кадров в секунду:
Затем сбросьте счетчик на 0 и установите метку времени на текущее время.
источник
Увеличивайте счетчик каждый раз, когда вы визуализируете экран, и сбрасывайте этот счетчик на некоторый интервал времени, в течение которого вы хотите измерить частоту кадров.
Т.е. Каждые 3 секунды снимайте счетчик / 3, а затем сбрасывайте счетчик.
источник
Сделать это можно как минимум двумя способами:
Первый - это тот, о котором говорили здесь до меня. Я считаю, что это самый простой и предпочтительный способ. Вы просто следите за
Вычислить частоту кадров в этом случае так же просто, как вычислить эту формулу:
Тогда есть отличный способ, которым вы, возможно, захотите когда-нибудь воспользоваться:
Допустим, у вас есть «i» -фреймы для рассмотрения. Я буду использовать следующие обозначения: f [0], f [1], ..., f [i-1], чтобы описать, сколько времени потребовалось для визуализации кадра 0, кадра 1, ..., кадра (i-1 ) соответственно.
Тогда математическое определение fps после i кадров будет
Формула та же, но только с учетом кадров i-1.
Хитрость заключается в том, чтобы изменить правую часть формулы (1) таким образом, чтобы она содержала правую часть формулы (2), и заменила ее левой частью.
Вот так (вы должны увидеть это более ясно, если напишете на бумаге):
Итак, согласно этой формуле (хотя мои навыки математического вывода немного устарели), чтобы вычислить новые кадры в секунду, вам нужно знать количество кадров в секунду из предыдущего кадра, продолжительность, затраченную на рендеринг последнего кадра, и количество кадров, которые вы получили. оказано.
источник
Это может быть излишним для большинства людей, поэтому я не опубликовал его, когда реализовал. Но он очень прочный и гибкий.
Он хранит очередь с последним временем кадра, поэтому он может точно рассчитать среднее значение FPS намного лучше, чем просто учитывать последний кадр.
Это также позволяет вам игнорировать один кадр, если вы делаете что-то, что, как вы знаете, искусственно испортит время этого кадра.
Он также позволяет вам изменять количество кадров, сохраняемых в очереди по мере ее выполнения, так что вы можете на лету проверить, что лучше всего подходит для вас.
источник
Здесь хорошие ответы. То, как вы его реализуете, зависит от того, для чего вам это нужно. Я предпочитаю скользящее среднее значение "time = time * 0.9 + last_frame * 0.1" автора выше.
однако мне лично нравится больше взвешивать свое среднее значение по отношению к новым данным, потому что в игре именно ШИПЫ сложнее всего раздавить, и поэтому они представляют для меня наибольший интерес. Поэтому я бы использовал что-то более похожее на разделение .7 \ .3, чтобы спайк проявился намного быстрее (хотя его эффект также исчезнет за пределами экрана ... см. Ниже)
Если вы сосредоточены на РЕНДЕРИРОВАНИИ времени, то разделение .9.1 работает довольно хорошо, потому что оно обычно более плавное. Хотя для игрового процесса / искусственного интеллекта / физики пики вызывают гораздо большее беспокойство, поскольку именно они обычно делают вашу игру нестабильной (что часто хуже, чем низкая частота кадров, если мы не опускаемся ниже 20 кадров в секунду)
Итак, я бы добавил что-то вроде этого:
(заполните 3.0f любой величиной, которую вы сочтете неприемлемой). Это позволит вам найти и, таким образом, решить проблемы FPS в конце кадра, которые они возникают.
источник
time = time * 0.9 + last_frame * 0.1
средний расчет, который позволяет плавно изменять отображение.Гораздо лучшая система, чем использование большого массива старых кадровых частот, - это просто сделать что-то вроде этого:
Этот метод использует гораздо меньше памяти, требует гораздо меньше кода и придает большее значение недавней частоте кадров, чем старой, но при этом сглаживает эффекты внезапных изменений частоты кадров.
источник
Вы можете сохранить счетчик, увеличивать его после рендеринга каждого кадра, а затем сбрасывать счетчик, когда вы находитесь на новой секунде (сохраняя предыдущее значение как количество визуализированных кадров за последнюю секунду)
источник
JavaScript:
источник
Вот полный пример, использующий Python (но легко адаптированный к любому языку). Он использует уравнение сглаживания в ответе Мартина, поэтому почти нет накладных расходов на память, и я выбрал значения, которые сработали для меня (не стесняйтесь поиграть с константами, чтобы адаптироваться к вашему варианту использования).
источник
Установите счетчик на ноль. Каждый раз, когда вы рисуете кадр, увеличивайте счетчик. Через каждую секунду выведите счетчик. вспенить, промыть, повторить. Если вам нужен дополнительный кредит, держите текущий счетчик и разделите его на общее количество секунд, чтобы получить среднее значение.
источник
В псевдокоде (похожем на C ++) эти два я использовал в промышленных приложениях для обработки изображений, которые должны были обрабатывать изображения с набора камер с внешним запуском. Изменения в «частоте кадров» имели другой источник (более медленное или быстрое воспроизведение на ленте), но проблема та же. (Я предполагаю, что у вас есть простой вызов timer.peek (), который дает вам что-то вроде номера msec (nsec?) С момента запуска приложения или последнего вызова)
Решение 1: быстро, но не обновляется каждый кадр
Решение 2: обновляется каждый кадр, требуется больше памяти и ЦП
источник
источник
Как я это делаю!
Проще говоря, тикающие часы отслеживают тиканье. Если это первый раз, он берет текущее время и помещает его в «тикстарт». После первого тика он делает переменную «fps» равной количеству тиков тикового таймера, разделенному на время минус время первого тика.
Fps - это целое число, поэтому "(int)".
источник
Вот как я это делаю (на Java):
источник
В Typescript я использую этот алгоритм для расчета средних значений частоты кадров и времени кадра:
использование:
Совет: Если выборка равна 1, результатом будет частота кадров и время кадра в реальном времени.
источник
Это основано на ответе KPexEA и дает простую скользящую среднюю. Приведено в порядок и преобразовано в TypeScript для легкого копирования и вставки:
Объявление переменной:
Функция:
Использование (может отличаться в вашем приложении):
источник
сохранить время начала и увеличивать счетчик кадров один раз за цикл? каждые несколько секунд вы можете просто печатать framecount / (сейчас - время начала), а затем повторно инициализировать их.
редактировать: упс. двойной ниндзя
источник