@EMaDeLoC y
@SuperPadLandNo sé si es que estoy espeso y os estáis refiriendo a otra cosa. Pero los "saltos bruscos" de fps de 60 a 30 a 20 a 15... (o 50 a 25 a 16,7 a 12,5 en PAL) se debe a que se usa doble buffer para pintar la pantalla y la tasa de fps va ligada al refresco de la pantalla. Me parece que ya se ha hablado de esto en el pasado y que incluso puse este vídeo que lo explica bastante bien (aunque está en inglés) :
https://www.youtube.com/watch?v=SyK8_9NPU6ELa explicación del doble buffer comienza en el 1:55. Básicamente tienes un buffer donde se construye la imagen y se manda al monitor para que la dibuje, pero mientras se está dibujando no se puede generar otra imagen en el buffer porque está ocupado. Entonces se crea un segundo buffer donde generar el siguiente frame mientras se dibuja el actual, y cuando se ha terminado de dibujar en el buffer 1, el monitor comienza a dibujar el buffer 2 y se borra lo que hay en el buffer 1 para volver a generar el siguiente frame. Como el monitor tiene un refresco de 60 Hz puede dibujar hasta 60 imágenes por segundo (una imagen cada 16 milisegundos). Esto sería el caso ideal.
¿Pero qué pasa cuando no hay potencia suficiente para generar la imagen en 16 ms? Pues que se vuelve a enviar la imagen del último buffer que está completo mientras se le da tiempo al otro buffer a terminar de construir su imagen. Si tarda menos de 33 milisegundos entonces puede empezar a dibujarse en el siguiente refresco del monitor. Cambiaría de imagen cada 2 refrescos de 60 Hz, por lo que percibiríamos 30 imágenes por segundo.
Si todavía se necesitase más tiempo (entre 33 y 50 ms), necesitaría un refresco más y se cambiaría de imagen cada 3 refrescos (20 fps). Si necesita repetir la imagen un refresco más bajaría a 15 fps (60/4). Y la tasa sigue bajando en fracciones de 60 cuanto más tiempo se necesite para terminar de dibujar el frame (12 fps para 5 refrescos, 10 fps para 6 refrescos...).
Hay una forma de evitar saltos tan bruscos y es tener un tercer buffer que permita ir generando una nueva imagen sin tener que esperar a los tiempos de refresco del monitor. Si por ejemplo se tardan 20 ms en generar los frames, hasta los 33 ms que hay que esperar para que el monitor dibuje la imagen hay un tiempo que con doble buffer no se está aprovechando para nada. Ahí es donde se empezaría a dibujar una tercera imagen para tenerla lista en el refresco más cercano. De este modo, el buffer 1 necesita dos refrescos para terminar y dibujar su imagen, pero el buffer 2 a los 21 ms ya se está generando, y a los 40 ms se está generando el buffer 3 que acabaría a los 60 ms. En el monitor veríamos los siguiente:
-Primer refresco a los 16 ms. No se dibuja nada porque no ha terminado de generar la imagen en el buffer 1.
-Segundo refresco a los 33 ms. Se dibuja el buffer 1.
-Tercer refresco a los 50 ms. Se dibuja el buffer 2.
-Cuarto refresco a los 67 ms. Se dibuja el frame 3.
-Quinto refresco a los 83 ms. Se dibuja el buffer 1 de nuevo (ha empezado a generar la imagen cuando el buffer 3 ha terminado a los 60 ms y ha terminado a los 80 ms).
-Sexto refresco a los 100 ms. Se dibuja el buffer 2 (ha empezado a generar la imagen cuando el buffer 1 ha terminado a los 80 ms y ha terminado justo a los 100 ms).
-Séptimo refresco a los 116 ms. Se repite la imagen del buffer 2 porque el buffer 3 no ha tenido tiempo de terminar (acabará a los 120 ms).
En el ejemplo de arriba con triple buffer estamos consiguiendo unos 50 fps (de cada 6 refrescos se repite 1) que es una mejora muy bestia que si se estuviera usando doble buffer. Pero hay muchos inconvenientes:
-Tener un buffer extra significa dedicar parte de la memoria RAM a este cometido. Y además de un buffer de imagen también hay que generar su correspondiente Z-buffer así que es un gasto importante.
-Se está introduciendo entre 1 y 2 fps de lag porque la lógica del juego sigue funcionando sin esperar a lo que se muestra en pantalla.
-Se introduce stuttering (tirones) cuando se repite algún frame. Si la carga gráfica es constante el tirón ocurre a intervalos regulares por lo que es todavía más notable y molesto.
Por eso, aunque la ganancia en rendimiento es considerable, con el tiempo me he vuelto más defensor de emplear doble buffer y controlar la carga gráfica para no saltar del framerate objetivo (sea 60 ,30 o 20) y tener una experiencia constante que experimentar esos tirones y el lag (que en este caso es de 2 fps como mucho, pero porque estamos rozando los 60 fps. Si rondáramos los 20 fps el lag podría ser de 6 o 7 frames).
Luego está el tema de desactivar el V-sync, que no sé si la N64 puede funcionar de esta manera. Lo que ocurre en este caso es que en lugar de dibujar las imágenes de arriba a abajo desde el principio hasta el final, se dibuja hasta donde de tiempo y el segundo buffer comienza a dibujar desde esa línea hasta lo que le de tiempo y se va mandando al monitor para que lo dibuje según le llega. El resultado es el "screen tearing" o cortes horizontales en la imagen que son molestísimos si hay un poco de movimiento, pero técnicamente el rendimiento sería de 60 fps y 0 lag todo el rato. Muy falso todo, porque si la potencia no da vas a ver muchos cortes en cada refresco del monitor (2 cortes si el juego fuese a 20 fps en doble buffer) y además los cortes seguramente van a ir variando de posición. Se ve en el vídeo que es puesto antes a partir del 6:00.
Los juego en N64 usan doble buffer por regla general. Pero Quake 2 cuando detecta el Expansion Pak cambia a triple buffer (y también aumenta la profundidad de color aprovechando la memoria extra) y con eso consigue un rendimiento medio más alto.
https://www.youtube.com/watch?v=SyK8_9NPU6E