2010-07-20 19 views
7

¿Hay alguna manera de calcular la cantidad de actualizaciones que se deben realizar para alcanzar la velocidad de fotogramas deseada, NO específica del sistema? Lo encontré para Windows, pero me gustaría saber si algo así existe en OpenGL. Debería ser algún tipo de temporizador.configuración de fotogramas máximos por segundo en OpenGL

¿O de qué otra manera puedo evitar que el FPS caiga o suba dramáticamente? Por esta vez lo estoy probando al dibujar un gran número de vértices en línea, y al usar fraps puedo ver la velocidad de fotogramas para ir de 400 a 200 fps con una ralentización evidente al dibujarlo.

Respuesta

9

Tienes dos maneras diferentes para resolver este problema:

  1. suponga que tiene una variable llamada maximum_fps, que contiene el número máximo de fotogramas que desee mostrar.

    A continuación, se mide la cantidad de tiempo invertido en el último cuadro (un temporizador hará)

    Ahora supongamos que usted ha dicho que quería un máximo de 60 fps en su aplicación. Entonces desea que el tiempo medido no sea inferior a 1/60. Si el tiempo medido es más bajo, entonces llama al sleep() para alcanzar la cantidad de tiempo que queda para un cuadro.

  2. O puede tener una variable llamada tick, que contiene el "tiempo de juego" actual de la aplicación. Con el mismo temporizador, lo incrementará en cada bucle principal de su aplicación. Luego, en sus rutinas de dibujo, calcula las posiciones basadas en la var tick, ya que contiene la hora actual de la aplicación.

    La gran ventaja de la opción 2 es que su aplicación será mucho más fácil de depurar, ya que puede jugar con la variable tick, avanzar y retroceder en el tiempo siempre que lo desee. Este es un grande plus.

+6

El primero es solo para ralentizar el FPS y es peligroso confiar en la precisión del intervalo de sueño. – young

+0

En algunos casos simples (y el actual) es la primera solución lo suficientemente buena, porque solo necesito unir FPS mientras ejecuto la aplicación, sabiendo que mi velocidad de cuadros nunca disminuyó por debajo de 200 será eficiente. Entonces, tal vez sea peligroso pero simple ingresar a su código sin muchos cambios, es tan bueno como el segundo ... – Raven

+0

"Luego mides la cantidad de tiempo que pasaste en el último fotograma" ¿cómo sabes que el último fotograma está terminado y es hora para medir el retraso? – Allahjane

2

¿Hay alguna manera de calcular la cantidad de actualizaciones se debe hacer para alcanzar la velocidad de fotogramas deseada, NO sistema específico?

No hay manera de calcular con precisión cuántos cambios debe ser llamado para llegar a deseao.

Sin embargo, puede medir cuánto tiempo ha pasado desde el último cuadro, calcular el framerate actual según él, compararlo con el framerate deseado, luego introducir un bit de Sleep ing para reducir el framerate actual al valor deseado. No es una solución precisa, pero funcionará.

Encontré eso para Windows, pero me gustaría saber si algo como esto existe en OpenGL. Debería ser algún tipo de temporizador.

OpenGL solo se preocupa por el procesamiento de elementos y no tiene nada que ver con los temporizadores. Además, usar temporizadores de Windows no es una buena idea. Utilice QueryPerformanceCounter, GetTickCount o SDL_GetTicks para medir cuánto tiempo ha transcurrido y para obtener la frecuencia de fotogramas deseada.

¿O de qué otra manera puedo evitar que los FPS caigan o suban drásticamente?

Evita que se levante el FPS durmiendo.

En cuanto a la prevención de la caída de FPS ...

Es increíblemente amplio tema. Veamos. Es algo como esto: use objetos de búfer Vertex o listas de visualización, profile application, no use texturas increiblemente grandes, no use demasiada mezcla alfa, evite OpenGL (sin formato) (glVertex3f), no renderice objetos invisibles (incluso si no se dibujan polígonos, procesarlos lleva tiempo), considere aprender sobre BSP u OCTrees para representar escenas complejas, en superficies y curvas paramétricas, no use innecesariamente muchas primitivas (si hace un círculo con un millón de polígonos, nadie lo hará) notar la diferencia), deshabilitar vsync. En resumen: reduzca al número mínimo absoluto de llamadas de renderizado, número de polígonos renderizados, número de píxeles renderizados, número de mensajes leídos, lea todas las documentaciones de rendimiento disponibles de NVidia, y debería obtener un aumento de rendimiento.

+0

He encontrado que incluso OGL tiene su propio temporizador como este: glutTimerFunc (40, Timer, 0); De todos modos, cuando estaba hablando de Windows One, pensé que QueryPerformanceCounter y QueryPerformanceFrequency solo están disponibles en Windows. – Raven

+3

@Raven: "glutTimerFunc" Esta no es una función OpenGL: el exceso no es parte de OpenGL. "están disponibles solo en Windows" Sí, solo son ventanas. Si quieres una solución multiplataforma, usa SDL_GetTicks. – SigTerm

+0

Pero si está utilizando un exceso (freeglut en mi caso), todavía tiene una solución multiplataforma ¿verdad? Por supuesto, existe la necesidad de una biblioteca freeglut, pero el exceso proporciona funciones valiosas (como ese temporizador) en ese fragmento de archivo ... – Raven

0

Hace la pregunta incorrecta. Su monitor solo se mostrará a 60 fps (50 fps en Europa, o posiblemente 75 fps si es un jugador profesional).

En su lugar, debe intentar bloquear su fps en 60 o 30. Hay extensiones de OpenGL que le permiten hacer eso. Sin embargo, las extensiones no son multiplataforma (afortunadamente no son específicas de una tarjeta de video o se pondrían realmente de miedo).

Estas extensiones están estrechamente relacionadas con el v-sync de su monitor. Una vez habilitadas las llamadas para intercambiar, el back-buffer OpenGL se bloqueará hasta que el monitor esté listo para ello. Esto es como poner un sueño en su código para aplicar 60 fps (o 30, o 15, o algún otro número si no está usando un monitor que se muestra a 60 Hz). La diferencia es que el "dormir" siempre está perfectamente sincronizado en lugar de una conjetura basada en la duración del último fotograma.

+0

"Hace la pregunta incorrecta". Es una pregunta de desarrollo de juegos bastante razonable. "Su monitor solo mostrará" Sí, pero una aplicación puede producir fácilmente 600 fotogramas por segundo. Además, una tasa de fotogramas muy alta es útil para capturar video y ralentizarlo luego. – SigTerm

+1

"En su lugar, debe intentar bloquear sus fps a 60 o 30.". Definitivamente no deberías hacer eso; si lo haces, ese juego no funcionará si el hardware no es lo suficientemente poderoso. El juego bien hecho debería poder ejecutarse con cualquier framerate (de 5 a 1000). "wglSwapIntervalEXT" Tiene muy poco que ver con la velocidad de fotogramas. – SigTerm

+0

Estaba un poco vago. Por supuesto, deberías degradar con gracia si el sistema no puede presionar 30 fps. Sin embargo, para una mejor experiencia de usuario, es mejor "bloquear" la velocidad de fotogramas en algo constante en lugar de saltar de 20 a 200 en todas partes. –

9

Regla # 1. No haga que las funciones de actualización() o de bucle() dependan de la frecuencia con la que se llama.

Realmente no puede obtener su FPS deseado. Podría tratar de aumentarlo omitiendo algunas operaciones caras o desacelerar llamando al tipo de funciones sleep(). Sin embargo, incluso con esas técnicas, FPS casi siempre será diferente del FPS exacto que desee.

La forma común de resolver este problema es utilizar el tiempo transcurrido desde la actualización anterior. Por ejemplo,

// Bad 
void enemy::update() 
{ 
    position.x += 10; // this enemy moving speed is totally up to FPS and you can't control it. 
} 

// Good 
void enemy::update(elapsedTime) 
{ 
    position.x += speedX * elapsedTime; // Now, you can control its speedX and it doesn't matter how often it gets called. 
} 
+0

, en pocas palabras, usted está diciendo lo mismo que Edison, pero esta demostración de código deja en claro para todos ahora, creo. Gracias – Raven

+0

De nada ~ :) y yeap, el mío es el mismo que el segundo en la respuesta de Edison. solo quería señalar la debilidad de la primera. – young

1

a pesar de todo wa no estrangular a su velocidad de fotogramas que todo depende de lo que tienes pasando en ese bucle de representación y lo que su aplicación hace. Especialmente con relacionado con la física/red. O si está haciendo cualquier tipo de procesamiento de gráficos con un kit de herramientas externo (Cairo, QPainter, Skia, AGG, ...) a menos que desee resultados desincronizados o 100% de uso de la CPU.

0

Here is a similar question, with my answer and worked example

también me gusta la respuesta de deft_code, y se busca en la adición de lo que sugiere que mi solución.

La parte crucial de mi respuesta es:

Si usted está pensando en reducir la velocidad y la aceleración de los marcos, usted tiene que pensar cuidadosamente acerca de si nos referimos a la representación o cuadros de animación en cada caso. En este ejemplo, la aceleración del render para animaciones simples se combina con la aceleración de animación, para cualquier caso en que los fotogramas se eliminen en una animación potencialmente lenta.

El ejemplo es para el código de animación que se reproduce a la misma velocidad independientemente de si el modo de evaluación comparativa o el modo FPS fijo está activo. Una animación activada antes del cambio incluso mantiene una velocidad constante después del cambio.

0

Este código puede hacer el trabajo, más o menos.

static int redisplay_interval; 

void timer(int) { 
    glutPostRedisplay(); 
    glutTimerFunc(redisplay_interval, timer, 0); 
} 

void setFPS(int fps) 
{ 
    redisplay_interval = 1000/fps; 
    glutTimerFunc(redisplay_interval, timer, 0); 
} 
Cuestiones relacionadas