Tutoriales

¿Cómo se generan los gráficos en una tarjeta gráfica?

Cómo se generan los gráficos, o mejor dicho, cómo funciona una tarjeta gráfica, es un misterio para muchos usuarios. Sin embargo, la GPU sigue una serie de pasos que desgranaré más adelante para generar los gráficos que puedes ver en pantalla. ¿Quieres conocerlos? Vamos allá.

Conocimiento previo necesario

Antes de nada, hay que conocer qué son algunos componentes fundamentales para el funcionamiento de los gráficos generados por la tarjeta gráfica o GPU. Y estos elementos son:

  • API gráfica (Application Programming Interface): es un conjunto de funciones y protocolos que permiten a los desarrolladores de software interactuar con la tarjeta gráfica (GPU) y crear gráficos, imágenes y animaciones en aplicaciones y juegos. La API gráfica proporciona una interfaz estandarizada para enviar comandos y datos a la GPU, lo que permite que los desarrolladores utilicen el hardware de gráficos para crear los gráficos necesarios. Algunos ejemplos de APIs gráficas son OpenGL, Vulkan y DirectX 3D.
  • Motor gráfico (Graphics Engine): es un software que utiliza una API gráfica para procesar y renderizar imágenes, gráficos y escenas en aplicaciones y juegos. El motor gráfico se encarga de realizar cálculos complejos, aplicar efectos visuales, gestionar la iluminación, la geometría y la física (p.e.: colisiones, reflejos, ondas,…), animación, scripting, sonidos, IA del juego, y generar el contenido visual final que se mostrará en la pantalla. Los motores gráficos son herramientas esenciales para los desarrolladores, ya que facilitan la creación de gráficos avanzados y complejos sin requerir un conocimiento detallado de las complejidades de las APIs gráficas subyacentes. Algunos ejemplos de motores conocidos son Source, Unity 3D, RockStar Advanced Engine, CryEngine, Unreal Engine, DOOM Engine, Godot, etc.
  • Driver de la GPU: es un software/firmware que actúa como intermediario entre el sistema operativo y la tarjeta gráfica. Los drivers permiten que el sistema operativo y las aplicaciones se comuniquen con la GPU y utilicen sus capacidades de procesamiento gráfico, en este caso, a través de la API gráfica. Dicho de otro modo, el driver permite traducir los comandos de la API gráfica en unas instrucciones que comprenda la GPU, según la ISA que tenga. Y es que la API es genérica, no depende de la GPU, por lo que se necesita del driver para realizar esta traducción como veremos más adelante.

Esto es desde el lado del software. Es decir, para que se genere un gráfico, se necesitan de todos estos elementos (excepto el motor gráfico, que es opcional y utilizado principalmente para videojuegos o simulaciones). Gracias a estos elementos, una app gráfica puede enviar una serie de comandos a la GPU para que sean procesados y se muestren los gráficos oportunos.

¿Cómo funciona la tarjeta gráfica para crear las imágenes?

Desde que se envían los comandos para dibujar un gráfico en pantalla hasta que el fotograma llega al framebuffer y pasa a verse en la pantalla o monitor, se suceden una serie de pasos básicos que deberías conocer. Y es que, todos los gráficos de la interfaz del sistema operativo, programas, o de los videojuegos, vídeos, etc., que puedes ver, no son más que datos de textura, color, iluminación, geométricos, etc. Todo eso se procesa por la GPU en fracciones de segundo para mostrar decenas de fotogramas por segundo (FPS). Y todo esto empieza de la manera más simple…

En las GPUs modernas, se han incorporado funciones adicionales para mejorar la calidad de las imágenes y que también requieren ser procesadas. Estas funciones incluyen el escalado de imágenes, técnicas de anti-aliasing para suavizar bordes, el trazado de rayos para mejorar la iluminación, entre otras. Sin embargo, en la descripción que sigue, he tratado de ser breve y conciso para que puedas comprender el proceso sin entrar en detalles técnicos complicados que puedan alterar la visión general de cómo se crea un gráfico o cómo funciona la tarjeta gráfica…

Primero: comandos enviados a la GPU

#include <GL/glut.h>

void display() {
    glClear(GL_COLOR_BUFFER_BIT);
    
    glBegin(GL_TRIANGLES);
    glVertex2f(-0.5f, -0.5f); // Vértice inferior izquierdo
    glVertex2f(0.5f, -0.5f);  // Vértice inferior derecho
    glVertex2f(0.0f, 0.5f);   // Vértice superior
    glEnd();
    
    glFlush();
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Triángulo en OpenGL");
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Fondo negro
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-1.0f, 1.0f, -1.0f, 1.0f); // Definir el sistema de coordenadas
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

Anteriormente mencioné este tema, pero para resumirlo, la CPU, mediante el software (aplicaciones, API y drivers), utilizará comandos u objetos a través de la API gráfica y los enviará a la GPU para su procesamiento. La GPU utilizará los shaders, que son esencialmente códigos de manipulación, los cuales serán procesados en las unidades de sombreado, como los núcleos CUDA de NVIDIA o las Compute Units de AMD.

Por ejemplo, en el código anterior se muestra cómo se puede dibujar un triángulo sencillo. Este código crea una ventana utilizando la biblioteca GLUT (OpenGL Utility Toolkit) y dibuja un triángulo equilátero en el centro de la ventana. La función glBegin(GL_TRIANGLES) indica que se van a especificar vértices para dibujar un triángulo. Luego, con glVertex2f(x, y) se especifican las coordenadas de los tres vértices del triángulo. Al finalizar, glEnd() indica que se ha terminado de definir el triángulo. La función glFlush() asegura que el triángulo se dibuje en la ventana… Una vez compilado este código, y ejecutado, permitirá enviar los comandos y datos necesarios a la GPU con ayuda del driver o controlador.

Segundo: pipeline de la representación

Una vez que los vértices han sido enviados a la GPU y están listos para ser mostrados, la API gráfica se encargará de administrar el llamado «Rendering pipeline» o «tubería de renderizado», que consta de 6 etapas:

  1. Operación por vértice o Per-Vertex Operation: esta es la fase inicial del proceso, donde los vértices de la imagen son procesados por un Vertex Shader, que es una unidad de sombreado en la GPU. Esta unidad de cómputo realiza operaciones matemáticas con números enteros y de punto flotante. Cada vértice es multiplicado por una matriz de transformación, lo que resulta en un cambio del sistema de coordenadas 3D a un sistema de coordenadas proyectivas, lo cual es esencial para su posterior procesamiento.
  2. Ensamblaje de primitiva o Primitive Assembly: después de que la unidad de sombreado ha generado las tres coordenadas de vértices necesarias para crear una imagen, se procede con el ensamblaje de primitivas, que consiste en conectar estos vértices en un orden específico.
  3. Procesamiento de primitiva o Primitive Processing:  antes de que la primitiva generada avance a la siguiente etapa del proceso, es necesario realizar el recorte o clipping. Esto implica que una imagen generada puede ser más grande que la pantalla, pero solo se mostrará lo que está dentro del área visible en la pantalla, conocido como el «View-Volume». Durante el proceso de clipping, todo lo que se encuentra fuera del área visible se recorta y se ignora para la siguiente etapa del proceso. En resumen, el clipping asegura que solo se muestre en la pantalla lo que está dentro del área visible, eliminando todo lo que se encuentra fuera de la vista.
  4. Rasterización o Rasterization: todo lo que se ha realizado anteriormente no puede ser mostrado en la pantalla directamente, ya que se requieren píxeles para formar el fotograma final de la imagen. Es en esta etapa de rasterización donde se generan esos píxeles. Solo los fragmentos que han pasado la etapa del clipping se procesarán en esta fase para convertirlos en píxeles individuales que serán utilizados para construir la imagen final. En resumen, la rasterización es el proceso que crea los píxeles necesarios para mostrar la imagen en pantalla, pero solo se procesan los fragmentos que han sido seleccionados en la etapa anterior de clipping.
  5. Procesamiento de fragmentos o Fragment Processing: en este punto, los fragmentos que han superado la etapa anterior avanzan a otro paso, donde son nuevamente procesados por un sombreador adicional. Este sombreador se denomina Fragment Shader y es el responsable de aplicar color y textura a los píxeles del fragmento. En esencia, el Fragment Shader es el encargado de determinar cómo se verán los píxeles individuales en la imagen final, al aplicarles los colores y texturas apropiados según las propiedades de la escena.
  6. Operación por fragmentos o Per-Fragment Operation: en esta fase, los píxeles del fragmento que ya han sido coloreados y texturizados se envían al framebuffer o buffer de fotogramas. En este buffer, los píxeles se agrupan en el Default-Framebuffer, que será la imagen final que se mostrará en la pantalla. Es decir, es en el Default-Framebuffer donde se compone la imagen completa con todos los píxeles procesados y listos para ser visualizados por el usuario.

Tercero: representación en pantalla

Finalmente, el frame o fotograma generado se transmitirá a través de la salida de la GPU, que está conectada a la pantalla, permitiendo que la imagen se visualice en la pantalla. La frecuencia de actualización de los fotogramas, también conocida como FPS (Frames Per Second), dependerá tanto de la capacidad de la GPU como de la pantalla. En función de estas capacidades, los fotogramas se actualizarán con mayor o menor velocidad, lo que determinará la fluidez y suavidad de la animación o contenido visual que se muestra en la pantalla.

Los píxeles se mapearán en la matriz o panel de la pantalla, apagando, encendiendo o conmutando los píxeles al color necesario para mostrar finalmente el triángulo y su textura…

Para aquellos que no estén familiarizados con el término «RAMDAC», es una abreviatura de «Random Access Memory Digital-to-Analog Converter», que significa «convertidor digital a analógico de memoria de acceso aleatorio». Básicamente, es un chip con una memoria RAM que se utiliza para transformar las señales digitales provenientes de la GPU en una señal analógica. Para realizar esta tarea, el RAMDAC requiere varios convertidores digital-analógico (DAC) y una memoria SRAM (memoria de acceso aleatorio estática) de alta velocidad. Este chip estaba presente en las tarjetas gráficas más antiguas, ya que necesitaban de él para realizar la conversión, dado que la señal que emitía la GPU era digital, mientras que las interfaces de conexión al monitor o pantalla eran analógicas, como es el caso de VGA, DVI-A, RGA, S-Video, vídeo compuesto, etc.

Te recomendamos las siguientes guías sobre GPU:

Ahora el gráfico o imagen estará presente en la pantalla, y la GPU volverá a repetir todos estos pasos una y otra vez con cada fotograma que sea necesario mostrar, así muchas veces por segundo, casi sin retrasos. ¿No es increíble? Comenta…

Recent Posts

  • Fuentes de alimentación

GALAX OMEGA: Nuevas serie de fuentes de alimentación ATX 3.0 de hasta 1200W

GALAX está presentando una nueva línea de fuentes de alimentación llamadas OMEGA, que están llegando…

10 mins atrás
  • Android

Instagram pone fin a los vídeos políticos con un nuevo filtro

Los contenidos políticos tienen los días contados en Instagram. La red social introduce un nuevo…

17 mins atrás
  • Memorias

Samsung y SK hynix abandonan la producción de memorias DDR3

Samsung y SK hynix abandonan la producción de las memorias DDR3. Hace unos dos años…

2 horas atrás