¿Alguna vez te has preguntado donde se almacenan las imágenes que ves en la pantalla de tu PC, consola o dispositivos PostPC? Pues en los búferes de imagen, pero, ¿Cuál es su naturaleza y en que consiste? ¿Cómo afecta al rendimiento de nuestros PCs , qué formas de renderizan una escena existen y cuales son sus diferencias?
Una GPU genera una cantidad ingente de información por segundo, en forma de múltiples imágenes que pasan rápidamente en nuestra retina desde el televisor, el tamaño de dichas imágenes y la información que se almacena y procesa es descomunal. Los búferes de imagen debido a que se almacenan en la VRAM son uno de los motivos por los cuales es necesario memoria de un alto ancho de banda.
¿Qué es el búfer de imagen?
El búfer de imagen es una parte de la VRAM donde se almacena la información de cada pixel en pantalla del siguiente fotograma, este búfer se almacena en la VRAM y es generado por la GPU cada x milisegundos.
Las GPUs actuales trabajan como mínimo con dos búferes de imagen, en el primero de ellos la GPU escribe el siguiente fotograma que se va a ver en pantalla, en el segundo se encuentra el fotograma anterior ya generado, el cual es enviado a pantalla.
Se le llama Backbuffer o búfer trasero a aquel que es generado por la GPU y Frontbuffer o búfer frontal a aquel que es leído por el controlador de pantalla y enviado a la salida de video. Mientras que el búfer frontal almacena por cada pixel el valor de los componentes rojo, verde y azul, en el búfer trasero puede almacenar un cuarto componente, alfa, que almacena el valor de transparencia o semi-transparencia de un pixel.
¿Qué es el controlador de pantalla?
El controlador de pantalla es una pieza de hardware que se encuentra en la GPU, es la encargada de leer el búfer de imagen en la VRAM y convertir los datos en una señal que la salida de vídeo, sea del tipo que sea, pueda entender.
En sistemas como NVIDIA G-SYNC, AMD FreeSync/Adaptative Sync y similares, el controlador de pantalla no solamente envía los datos al monitor o televisor sino que además controla cuando empieza y termina cada fotograma.
Búferes de imagen y renderizado 3D tradicional
Pese a que nuestras pantallas son en 2D, desde ya más de veinte años que se renderizan escenas en 3D a tiempo real en ellas. Para ello es necesario dividir el búfer trasero en dos búferes diferenciados:
- Búfer de Color: Donde se apunta el valor de los componentes de color y alfa de cada pixel.
- Búfer de profundidad: Donde se apunta el valor de profundidad de cada píxel.
Cuando se renderiza una escena en 3D nos podemos encontrar que varios píxeles tengan diferente valor en el búfer de profundidad pero se encuentren en el mismo lugar en las otras dos dimensiones, es aquí donde esos píxeles de más se han de descartar ya que no son visibles por el espectador, dicho descarte se hace comparando la posición de cada pixel en el búfer de profundidad, descartando con ellos a los más lejanos a la cámara.
El búfer de profundidad
El búfer de profundidad o más conocido como Z-Buffer almacena la distancia de cada pixel de una escena 3D respecto al punto de vista o cámara, este puede ser generado en uno de estos dos momentos.
- Después de la etapa de rasterizado y antes de la etapa de texturizado.
- Después de la etapa de texturizado.
Dado que la etapa más pesada computacionalmente hablando es la del Pixel/Fragment Shader, el hecho de generar el Z-Buffer justo después de texturizar la escena supone calcular el valor de color y por tanto el Pixel o Fragment Shader de cientos de miles e incluso millones de píxeles no visibles.
La contrapartida de hacerlo antes del texturizado es que al no tener los valores de color y transparencia, canal alfa, nos podemos encontrar que un pixel detrás de otro transparente sea descartado de antemano, haciendo que no sea visible a la escena final.
Para evitar esto, los desarrolladores suelen renderizar la escena en dos partes, en la primera no se renderizan los objetos que se encuentran detrás de un objeto transparente o semitransparente, mientras que en la segunda se renderizan dichos objetos en exclusiva.
Búfer de imagen y renderizado en diferido
Una de las novedades que se vieron a finales de la década de los 2000 a la hora de renderizar gráficos fue el renderizado en diferido o Deferred Rendering, el cual consistía en que primero se renderizaba la escena generando una serie de búferes adicionales llamados G-Buffer, para luego en un paso siguiente calcular la iluminación de la escena.
El hecho de necesitar varios búferes de imagen hace que las exigencias en cuanto a memoria se multipliquen y por tanto sea necesaria una cantidad de memoria más grande para su almacenamiento, así como una tasa de relleno y por tanto un ancho de banda más alto.
Pero, el renderizado por diferido se hizo para corregir uno de los problemas de rendimiento de la rasterización clásica en la que cada cambio de valor en un pixel, ya sea por luminancia o crominancia, supone una reescritura en el búfer de imagen, lo que se traduce en una cantidad enorme de datos a transmitir en la VRAM
Gracias al renderizado en diferido, el coste de la cantidad de luces en la escena pasa de ser exponencial a logarítmico, reduciendo así el coste computacional a la hora de renderizar escenas con múltiples fuentes de luz.
Búferes de imagen como mapa de sombras
Debido a que la rasterización no es muy buena calculando la iluminación indirecta se han de buscar trucos para generar los mapas de sombras en los mismos.
El método más simple es renderizar la escena tomando la fuente de luz o sombra como si fuera la cámara, pero en vez de renderizar una imagen completa se genera solamente el búfer de profundidad, el cual será utilizado más tarde como mapa de sombras.
Este sistema en los próximos años desaparecerá por el auge del Ray Tracing, el cual permite la creación de sombras en tiempo real de manera mucho más precisa, requiriendo menos potencia computacional y sin necesidad de generar un enorme mapa de sombras en la VRAM.