¿Cuál es un buen algoritmo para calcular cuadros por segundo en un juego? Quiero mostrarlo como un número en la esquina de la pantalla. Si solo miro cuánto tiempo tomó renderizar el último cuadro, el número cambia demasiado rápido.
Puntos de bonificación si su respuesta actualiza cada cuadro y no converge de manera diferente cuando la velocidad de cuadros aumenta o disminuye.
last_frame
no significa (o al menos no debería significar) la duración del cuadro anterior; debería significar el valortime
que calculaste para el último fotograma. De esta manera, se incluirán todos los fotogramas anteriores, siendo los fotogramas más recientes los que se ponderan más.Esto es lo que he usado en muchos juegos.
fuente
tickindex = (tickindex + 1) % MAXSAMPLES;
Bueno, ciertamente
Pero, como señala, hay mucha variación en el tiempo que lleva renderizar un solo fotograma, y desde la perspectiva de la interfaz de usuario, actualizar el valor de fps a la velocidad de fotogramas no se puede utilizar en absoluto (a menos que el número sea muy estable).
Lo que desea es probablemente un promedio móvil o algún tipo de contador de binning / reset.
Por ejemplo, podría mantener una estructura de datos de cola que contenga los tiempos de representación para cada uno de los últimos 30, 60, 100 o lo que sea que tenga (incluso podría diseñarlo para que el límite fuera ajustable en tiempo de ejecución). Para determinar una aproximación de fps decente, puede determinar el promedio de fps de todos los tiempos de renderizado en la cola:
Cuando termina de renderizar un nuevo fotograma, pone en cola un nuevo tiempo de renderizado y retira de la cola un tiempo de renderizado antiguo. Alternativamente, puede retirar de la cola solo cuando el total de los tiempos de renderizado excediera algún valor preestablecido (por ejemplo, 1 segundo). Puede mantener el "último valor de fps" y una marca de tiempo actualizada para poder activar cuándo actualizar la cifra de fps, si así lo desea. Aunque con un promedio móvil si tiene un formato consistente, imprimir el "promedio instantáneo" fps en cada cuadro probablemente estaría bien.
Otro método sería tener un contador de puesta a cero. Mantenga una marca de tiempo precisa (milisegundos), un contador de fotogramas y un valor de fps. Cuando termine de renderizar un fotograma, incremente el contador. Cuando el contador alcanza un límite preestablecido (por ejemplo, 100 fotogramas) o cuando el tiempo transcurrido desde la marca de tiempo ha pasado algún valor preestablecido (por ejemplo, 1 segundo), calcule los fps:
Luego, restablezca el contador a 0 y establezca la marca de tiempo en la hora actual.
fuente
Incremente un contador cada vez que renderice una pantalla y borre ese contador durante algún intervalo de tiempo durante el cual desea medir la velocidad de fotogramas.
Es decir. Cada 3 segundos, obtenga el contador / 3 y luego borre el contador.
fuente
Hay al menos dos formas de hacerlo:
El primero es el que otros han mencionado aquí antes que yo. Creo que es la forma más sencilla y preferida. Tu solo para hacer un seguimiento de
Calcular los fps en este caso es tan simple como evaluar esta fórmula:
Luego está la forma súper genial que le gustaría usar algún día:
Digamos que tiene marcos en 'i' para considerar. Usaré esta notación: f [0], f [1], ..., f [i-1] para describir cuánto tiempo tomó renderizar el cuadro 0, el cuadro 1, ..., cuadro (i-1 ) respectivamente.
Entonces, la definición matemática de fps después de i cuadros sería
Y la misma fórmula pero solo considerando marcos i-1.
Ahora, el truco aquí es modificar el lado derecho de la fórmula (1) de tal manera que contenga el lado derecho de la fórmula (2) y sustituirlo por su lado izquierdo.
Así (deberías verlo más claramente si lo escribes en un papel):
Entonces, de acuerdo con esta fórmula (aunque mi habilidad de derivación matemática está un poco oxidada), para calcular los nuevos fps necesita conocer los fps del cuadro anterior, la duración que tardó en renderizar el último cuadro y la cantidad de cuadros que ha prestados.
fuente
Esto puede ser excesivo para la mayoría de las personas, por eso no lo había publicado cuando lo implementé. Pero es muy robusto y flexible.
Almacena una cola con los últimos tiempos de fotogramas, por lo que puede calcular con precisión un valor promedio de FPS mucho mejor que solo tener en cuenta el último fotograma.
También le permite ignorar un fotograma, si está haciendo algo que sabe que arruinará artificialmente el tiempo de ese fotograma.
También le permite cambiar la cantidad de fotogramas para almacenar en la cola mientras se ejecuta, para que pueda probar sobre la marcha cuál es el mejor valor para usted.
fuente
Buenas respuestas aquí. La forma en que lo implemente depende de para qué lo necesite. Yo mismo prefiero el promedio corriente "tiempo = tiempo * 0.9 + last_frame * 0.1" por el tipo de arriba.
sin embargo, personalmente me gusta ponderar mi promedio más hacia los datos más nuevos porque en un juego los SPIKES son los más difíciles de aplastar y, por lo tanto, de mayor interés para mí. Entonces, usaría algo más como una división de .7 \ .3 que hará que un pico se muestre mucho más rápido (aunque su efecto también desaparecerá de la pantalla más rápido ... ver más abajo)
Si su enfoque está en el tiempo de RENDERIZACIÓN, entonces la división .9.1 funciona bastante bien porque tiende a ser más suave. Aunque los picos de jugabilidad / IA / física son mucho más preocupantes, ya que ESO suele ser lo que hace que tu juego se vea entrecortado (que a menudo es peor que una velocidad de fotogramas baja asumiendo que no estamos por debajo de 20 fps)
Entonces, lo que haría también es agregar algo como esto:
(Complete 3.0f con cualquier magnitud que encuentre que es un pico inaceptable) Esto le permitirá encontrar y, por lo tanto, resolver los problemas de FPS al final del cuadro en el que ocurren.
fuente
time = time * 0.9 + last_frame * 0.1
cálculo promedio que hace que la pantalla cambie sin problemas.Un sistema mucho mejor que usar una gran variedad de framerates antiguos es simplemente hacer algo como esto:
Este método utiliza mucha menos memoria, requiere mucho menos código y da más importancia a las tasas de fotogramas recientes que a las antiguas, al mismo tiempo que suaviza los efectos de los cambios repentinos de velocidad de fotogramas.
fuente
Puede mantener un contador, incrementarlo después de que se procese cada fotograma y luego restablecer el contador cuando esté en un segundo nuevo (almacenando el valor anterior como el número de fotogramas renderizados del último segundo)
fuente
JavaScript:
fuente
Aquí hay un ejemplo completo, usando Python (pero fácilmente adaptado a cualquier idioma). Utiliza la ecuación de suavizado en la respuesta de Martin, por lo que casi no hay sobrecarga de memoria, y elegí valores que funcionaron para mí (siéntase libre de jugar con las constantes para adaptarse a su caso de uso).
fuente
Ponga el contador a cero. Cada vez que dibuje un cuadro, incremente el contador. Después de cada segundo imprima el contador. hacer espuma, enjuagar, repetir. Si desea crédito adicional, mantenga un contador activo y divida por el número total de segundos para un promedio móvil.
fuente
En pseudocódigo (como c ++), estos dos son los que usé en aplicaciones de procesamiento de imágenes industriales que tenían que procesar imágenes de un conjunto de cámaras activadas externamente. Las variaciones en la "velocidad de fotogramas" tuvieron una fuente diferente (producción más lenta o más rápida en la cinta) pero el problema es el mismo. (Supongo que tiene una llamada simple a timer.peek () que le da algo como el nr de msec (nsec?) Desde el inicio de la aplicación o la última llamada)
Solución 1: rápido pero no actualizado en cada fotograma
Solución 2: actualizado cada cuadro, requiere más memoria y CPU
fuente
fuente
¡Cómo lo hago!
En palabras, un reloj marca los pasos. Si es la primera vez, toma la hora actual y la pone en 'tickstart'. Después del primer tick, hace que la variable 'fps' sea igual al número de tics del reloj de tick dividido por el tiempo menos el tiempo del primer tick.
Fps es un número entero, por lo tanto, "(int)".
fuente
Así es como lo hago (en Java):
fuente
En TypeScript, uso este algoritmo para calcular los promedios de framerate y frametime:
uso:
Consejo: si samples es 1, el resultado es la velocidad de fotogramas y el tiempo de fotogramas en tiempo real.
fuente
Esto se basa en la respuesta de KPexEA y proporciona el promedio móvil simple. Ordenado y convertido a TypeScript para copiar y pegar fácilmente:
Declaración de variable:
Función:
Uso (puede variar en su aplicación):
fuente
almacenar una hora de inicio e incrementar su contador de fotogramas una vez por ciclo? cada pocos segundos puede imprimir framecount / (ahora - hora de inicio) y luego reinicializarlos.
editar: oops. doble ninja
fuente