Qual é um bom algoritmo para calcular quadros por segundo em um jogo? Quero mostrá-lo como um número no canto da tela. Se eu apenas olhar quanto tempo levou para renderizar o último quadro, o número muda muito rápido.
Pontos de bônus se sua resposta atualizar cada quadro e não convergir de maneira diferente quando a taxa de quadros está aumentando ou diminuindo.
fonte
last_frame
não significa (ou pelo menos não deveria significar) a duração do frame anterior; deve significar o valortime
que você calculou para o último quadro. Desta forma, todos os frames anteriores serão incluídos, com os frames mais recentes mais pesados.É o que tenho usado em muitos jogos.
fonte
tickindex = (tickindex + 1) % MAXSAMPLES;
Bem, certamente
Mas, como você apontou, há muita variação no tempo que leva para renderizar um único quadro e, de uma perspectiva da IU, atualizar o valor fps na taxa de quadros não pode ser usado (a menos que o número seja muito estável).
O que você quer provavelmente é uma média móvel ou algum tipo de contador de binning / reset.
Por exemplo, você poderia manter uma estrutura de dados de fila que continha os tempos de renderização para cada um dos últimos 30, 60, 100 ou o que quer que fosse (você poderia até mesmo projetá-la de forma que o limite fosse ajustável em tempo de execução). Para determinar uma aproximação de fps decente, você pode determinar a média de fps de todos os tempos de renderização na fila:
Ao terminar de renderizar um novo quadro, você enfileira um novo tempo de renderização e retira da fila um tempo de renderização antigo. Como alternativa, você pode retirar da fila apenas quando o total dos tempos de renderização exceder algum valor predefinido (por exemplo, 1 segundo). Você pode manter o "último valor fps" e um carimbo de data / hora da última atualização para que possa acionar quando atualizar a figura fps, se desejar. Embora com uma média móvel se você tiver uma formatação consistente, imprimir a "média instantânea" de fps em cada quadro provavelmente seria aceitável.
Outro método seria ter um contador de reinicialização. Mantenha um carimbo de data / hora preciso (milissegundo), um contador de quadros e um valor de fps. Ao terminar de renderizar um quadro, incremente o contador. Quando o contador atinge um limite predefinido (por exemplo, 100 quadros) ou quando o tempo desde o carimbo de data / hora passou algum valor predefinido (por exemplo, 1 segundo), calcule o fps:
Em seguida, redefina o contador para 0 e defina o carimbo de data / hora para a hora atual.
fonte
Aumente um contador toda vez que você renderizar uma tela e limpe esse contador por algum intervalo de tempo sobre o qual deseja medir a taxa de quadros.
Ie. A cada 3 segundos, obtenha o contador / 3 e zere o contador.
fonte
Existem pelo menos duas maneiras de fazer isso:
O primeiro é aquele que outros mencionaram aqui antes de mim. Acho que é a forma mais simples e preferida. Você apenas para acompanhar
Calcular o fps, neste caso, é tão simples quanto avaliar esta fórmula:
Depois, há a maneira super legal que você gostaria de usar algum dia:
Digamos que você tenha frames 'i' a considerar. Usarei esta notação: f [0], f [1], ..., f [i-1] para descrever quanto tempo levou para renderizar o quadro 0, quadro 1, ..., quadro (i-1 ), respectivamente.
Então, a definição matemática de fps após i frames seria
E a mesma fórmula, mas considerando apenas frames i-1.
Agora, o truque aqui é modificar o lado direito da fórmula (1) de modo que contenha o lado direito da fórmula (2) e substituí-lo por seu lado esquerdo.
Assim (você deve ver mais claramente se escrever em um papel):
Portanto, de acordo com esta fórmula (embora minha habilidade de derivar matemática esteja um pouco enferrujada), para calcular os novos fps você precisa saber o fps do quadro anterior, a duração que levou para renderizar o último quadro e o número de quadros que você renderizado.
fonte
Isso pode ser um exagero para a maioria das pessoas, é por isso que eu não postei quando o implementei. Mas é muito robusto e flexível.
Ele armazena uma fila com os tempos dos últimos quadros, para que possa calcular com precisão um valor médio de FPS muito melhor do que apenas levar o último quadro em consideração.
Também permite que você ignore um quadro, se estiver fazendo algo que sabe que vai atrapalhar artificialmente o tempo daquele quadro.
Ele também permite que você altere o número de quadros a serem armazenados na Fila à medida que ela é executada, para que você possa testar imediatamente qual é o melhor valor para você.
fonte
Boas respostas aqui. O modo como você o implementa depende do que você precisa. Eu prefiro a média de corrida para mim mesmo "tempo = tempo * 0,9 + último_frame * 0,1" pelo cara acima.
no entanto, eu pessoalmente gosto de pesar minha média mais fortemente em relação aos dados mais recentes porque em um jogo são os PONTOS que são mais difíceis de esmagar e, portanto, de maior interesse para mim. Então, eu usaria algo mais como uma divisão .7 \ .3 para fazer um pico aparecer muito mais rápido (embora seu efeito também caia da tela mais rápido .. veja abaixo)
Se o seu foco está no tempo de RENDIMENTO, então a divisão .9.1 funciona muito bem, mas tende a ser mais suave. Embora os picos de jogabilidade / IA / física sejam muito mais preocupantes, pois ISSO normalmente fará com que seu jogo pareça instável (o que costuma ser pior do que uma taxa de quadros baixa, supondo que não estamos caindo abaixo de 20 fps)
Então, o que eu faria é adicionar algo como isto:
(preencha 3.0f com qualquer magnitude que você achar um pico inaceitável) Isso permitirá que você encontre e, assim, resolva os problemas de FPS no final do quadro em que eles acontecem.
fonte
time = time * 0.9 + last_frame * 0.1
cálculo médio que faz com que a tela mude suavemente.Um sistema muito melhor do que usar uma grande variedade de taxas de quadros antigas é apenas fazer algo assim:
Este método usa muito menos memória, requer muito menos código e dá mais importância às taxas de quadros recentes do que às antigas, ao mesmo tempo em que suaviza os efeitos de mudanças repentinas na taxa de quadros.
fonte
Você pode manter um contador, incrementá-lo após cada quadro ser renderizado e, em seguida, zerar o contador quando estiver em um novo segundo (armazenando o valor anterior como o número do último segundo de quadros renderizados)
fonte
JavaScript:
fonte
Aqui está um exemplo completo, usando Python (mas facilmente adaptado para qualquer linguagem). Ele usa a equação de suavização na resposta de Martin, então quase nenhuma sobrecarga de memória, e eu escolhi valores que funcionaram para mim (sinta-se à vontade para brincar com as constantes para se adaptar ao seu caso de uso).
fonte
Defina o contador para zero. Cada vez que você desenha um quadro, incremente o contador. Após cada segundo, imprima o contador. ensaboe, enxágue, repita. Se você quiser crédito extra, mantenha um contador contínuo e divida pelo número total de segundos para obter uma média contínua.
fonte
No pseudocódigo (tipo c ++), esses dois são o que eu usei em aplicativos de processamento de imagem industrial que tinham que processar imagens de um conjunto de câmeras acionadas externamente. As variações na "taxa de quadros" tinham uma origem diferente (produção mais lenta ou mais rápida na esteira), mas o problema é o mesmo. (Presumo que você tenha uma chamada timer.peek () simples que fornece algo como o número de msec (nsec?) Desde o início do aplicativo ou a última chamada)
Solução 1: rápido, mas não atualizado a cada quadro
Solução 2: atualizado a cada quadro, requer mais memória e CPU
fonte
fonte
Como eu faço isso!
Em palavras, um tique-taque rastreia os tiques Se for a primeira vez, ele pega a hora atual e a coloca em 'tickstart'. Após o primeiro tique, torna a variável 'fps' igual a quantos tiques do relógio de tique dividido pelo tempo menos o tempo do primeiro tique.
Fps é um número inteiro, portanto, "(int)".
fonte
Veja como eu faço (em Java):
fonte
No Typescript, eu uso este algoritmo para calcular as médias de framerate e frametime:
uso:
Dica: Se samples for 1, o resultado será a taxa de quadros e o tempo de quadros em tempo real.
fonte
Isso é baseado na resposta do KPexEA e fornece a média móvel simples. Arrumado e convertido para TypeScript para fácil copiar e colar:
Declaração de variável:
Função:
Uso (pode variar em seu aplicativo):
fonte
armazenar uma hora de início e incrementar seu framecounter uma vez por loop? a cada poucos segundos, você pode apenas imprimir framecount / (Now - starttime) e reinicializá-los.
editar: oops. duplo ninja
fonte