Representación de juegos en 3D: introducción


Juegas al nuevo Call of Mario: Deathduty Battleyard en tu PC de juegos perfecta. Mire el hermoso monitor 4K súper ancho, admire el magnífico paisaje y los intrincados detalles. ¿Alguna vez te has preguntado cómo llegan los gráficos a la pantalla? ¿Te has preguntado cómo el juego hace que la computadora te muestre todo esto?

Bienvenido a nuestro recorrido por la representación de juegos en 3D: un viaje para principiantes, desde el cual aprenderá a crear un marco básico en la pantalla.



Cada año, se lanzan cientos de juegos nuevos para teléfonos inteligentes, consolas y PC. La variedad de formatos y géneros es muy grande, pero uno de ellos, tal vez, se domina mejor: estos son juegos en 3D. Qué juego fue el primero: una pregunta discutible, y un vistazo rápido a la base del Libro Guinness de los récords dio varios resultados. Puede considerarse el primer juego de Ultimate Knight Lore, lanzado en 1984, pero estrictamente hablando, las imágenes en este juego eran bidimensionales: no se utilizó información en tres dimensiones completas.

Entonces, si realmente queremos entender cómo los juegos 3D modernos forman una imagen, entonces tenemos que comenzar con otro ejemplo: Winning RunNamco, lanzado en 1988. Quizás este fue el primer juego completamente tridimensional que utiliza tecnologías que no son muy diferentes de las modernas. Por supuesto, cualquier juego cuya edad haya excedido los 30 años no es lo mismo que, por ejemplo, Codemasters F1, lanzado en 2018. Pero los diagramas de circuito son similares.


En este artículo, veremos el proceso de generación de una imagen básica para un monitor o TV usando un juego en 3D. Comencemos con el resultado final y preguntémonos: "¿Qué estoy mirando?"

Luego analizamos cada etapa de la formación de la imagen que vemos. En el curso de la acción, consideraremos conceptos tales como vértices y píxeles, texturas y pasadas, buffers y sombreados, software e instrucciones. Descubriremos cómo participa la tarjeta de video en el proceso y por qué es necesaria. Después de eso, puede ver sus juegos y PC bajo una nueva luz y comenzar a apreciar más los gráficos de video.

Opciones de marco: píxeles y colores.


Comencemos el juego 3D, como muestra tomaremos la compañía Crytek lanzada en 2007 Crysis . A continuación se muestra una fotografía de la pantalla en la que se muestra el juego:


Esta imagen generalmente se llama un marco . Pero, ¿qué estamos viendo exactamente? Usamos una lente macro:


Desafortunadamente, el resplandor y la retroiluminación externa del monitor estropean la foto, pero si la mejoramos un poco, obtenemos


Vemos que el marco en el monitor consiste en una cuadrícula de elementos de colores separados, y si los incrementamos aún más, notaremos que cada elemento es un bloque de tres piezas. Tal bloque se llama píxel (píxel, abreviatura de elemento de imagen). En la mayoría de los monitores, los píxeles se pintan con tres colores: rojo, verde y azul (RGB, rojo-verde-azul). Para mostrar un nuevo cuadro, debe procesar una lista de miles, si no millones, de valores RGB y guardarlos en una memoria a la que tenga acceso el monitor. Dichos fragmentos de memoria se denominan memorias intermedias , es decir, el monitor recibe el contenido de la memoria intermedia de trama .

Este es el punto final de todo el proceso, por lo que ahora nos moveremos en la dirección opuesta a su comienzo. El proceso a menudo se describe mediante el término representación (representación), pero en realidad es una secuencia de pasos separados conectados entre sí, que en esencia difieren mucho. Imagine que es un chef en un restaurante con estrella Michelin: el resultado final es un plato de comida deliciosa, pero cuánto se necesita hacer para lograrlo. Al igual que con la cocina, se necesitan ingredientes básicos para el renderizado.

Elementos de construcción necesarios: modelos y texturas.


Los bloques de construcción principales de cualquier juego en 3D son recursos visuales que llenan el mundo que se dibujará. Las películas, los programas de televisión y los teatros necesitan actores, disfraces, accesorios, escenografía, iluminación: la lista es bastante larga. Lo mismo con los juegos en 3D. Todo lo que ves en el marco generado fue desarrollado por artistas y expertos en modelado. Para que quede más claro, pasemos a la vieja escuela y echemos un vistazo al modelo Quake II de la compañía id Software:


El juego salió hace más de 20 años. En ese momento, Quake II era una obra maestra tecnológica, aunque, como en cualquier juego de esos años, los modelos aquí se ven muy primitivos. Pero es fácil demostrar en qué consisten.


En la imagen anterior, vemos un tipo angular que consiste en triángulos conectados entre sí. Cada esquina se llama vértice o vértice. Cada vértice actúa como un punto en el espacio y se describe con al menos tres números: las coordenadas x, y, z . Sin embargo, esto no es suficiente para un juego en 3D, por lo que cada vértice tiene significados adicionales: color, dirección del lado frontal (sí, un punto no puede tener un lado frontal ... ¡sigue leyendo!), Brillo, grado de transparencia, etc.


Los vértices siempre tienen un conjunto de valores asociados con los mapas de textura. Estas son fotos de la "ropa" que usa la modelo. Pero como la imagen es plana, el mapa debe contener una vista desde cualquier dirección desde donde podamos ver el modelo. El ejemplo de Quake II ilustra un enfoque simple: imágenes desde el frente, la parte posterior y los lados (brazos). Y los juegos 3D modernos ya funcionan para modelos con numerosos mapas de textura, cada uno de los cuales contiene muchos detalles, sin espacios vacíos entre ellos. Algunos mapas no parecen materiales o propiedades; en cambio, proporcionan información sobre cómo se refleja la luz desde la superficie. Cada vértice tiene un conjunto de coordenadas en el mapa de textura asociado con el modelo, de modo que puede "estirarse" sobre el vértice. Esto significa que cuando mueves el vértice, la textura se moverá con él.

En el mundo tridimensional renderizado, todo lo que ves comienza con un conjunto de vértices y mapas de textura. Se cargan en memorias intermedias conectadas entre sí. El búfer de vértices ( búfer de vértices) contiene texturas y porciones de memoria asignadas para su posterior representación. El búfer de comandos contiene una lista de instrucciones sobre qué hacer con estos recursos.

Todo esto forma el marco necesario que se utilizará para crear la cuadrícula final de píxeles de colores. En algunos juegos, esta es una gran cantidad de datos, porque lleva demasiado tiempo recrear los búferes para cada nuevo marco. Los juegos también almacenan en buffers la información necesaria para formar un mundo entero que un jugador puede ver, o una parte lo suficientemente grande, actualizándose según sea necesario. Por ejemplo, en un juego de carreras como F1 2018, todo se almacenará en una gran colección de buffers. Y en un juego de mundo abierto como Skyrim, los datos se cargarán en buffers y se eliminarán de ellos a medida que la cámara se mueva por el mundo.

Configuración de escena: vértices


Con toda la información visual, el juego comenzará el proceso de visualización. La escena comienza en una determinada posición por defecto, con la disposición base de modelos, fuentes de luz, etc. Esta será la pantalla "cero", el punto de partida para los gráficos. A menudo no se muestra, simplemente es procesado por el sistema. Para ilustrar lo que sucede en la primera etapa del renderizado, utilizaremos la herramienta en línea Real-Time Rendering . Creemos el "juego" más simple: una caja parada en el suelo.


Este objeto contiene 8 vértices, cada uno de los cuales se describe mediante una lista de números. Los vértices forman un modelo que consta de 12 triángulos. Cada triángulo, e incluso el objeto en sí, se llama primitivo . A medida que las primitivas se mueven, giran y escalan, los números pasan por cadenas de operaciones matemáticas y se actualizan.


Tenga en cuenta que los números de puntos del modelo no cambian. Estos números muestran exactamente dónde se encuentra el modelo en el mundo virtual. La consideración de los cálculos matemáticos correspondientes está más allá del alcance del artículo, solo diremos que primero todos los objetos se colocan donde deberían estar. Y luego comienza la coloración.


Tome otro modelo que tenga 10 veces más vértices que el cuadro anterior. En el proceso de pintura más simple, se toma el color de cada vértice y luego se calculan los cambios de color de una superficie a otra. Esto se llama interpolación .


Aumentar el número de vértices en el modelo no solo le permite crear objetos más realistas, sino que también mejora el resultado de la interpolación de color.


En esta etapa de renderizado, el efecto de las fuentes de luz en la escena se puede calcular en detalle. Por ejemplo, cómo los materiales del modelo reflejan el color. Dichos cálculos deben tener en cuenta la posición y dirección de la cámara, así como la posición y dirección de las fuentes de luz.


Para hacer esto, hay varios métodos matemáticos diferentes, algunos simples, otros muy complejos. En la ilustración anterior, vemos que el objeto a la derecha se ve mucho más bonito y realista, pero se requiere más trabajo para dibujarlo.

Es importante tener en cuenta que ahora comparamos objetos con un pequeño número de picos con los juegos más modernos. Desplácese hacia arriba y examine cuidadosamente la imagen de Crysis: esta escena muestra más de un millón de triángulos. Usando el punto de referencia de Unigine Valley como ejemplo, puedes entender cuántos triángulos se usan en los juegos modernos.


Cada objeto en esta imagen consiste en vértices conectados entre sí, que están formados por las primitivas que consisten en triángulos. El punto de referencia se puede ejecutar en modo de estructura alámbrica, en el que los bordes de cada triángulo se indican con líneas blancas.


Como puede ver, cualquier objeto consta de triángulos, y para cada triángulo se calcula la ubicación, dirección y color. Esto tiene en cuenta la ubicación de las fuentes de luz, así como la ubicación y dirección de la cámara. Todos los cambios asociados con los vértices deben transferirse al juego para que tenga toda la información necesaria para dibujar el siguiente cuadro, esto se realiza actualizando el búfer de vértices.

Sorprendentemente, esta no es la parte más difícil de renderizar, con el hardware adecuado, ¡todos los cálculos se realizan en unas pocas milésimas de segundo! Siga adelante.

Dimensión perdida: rasterización


Después de procesar todos los vértices y completar la colocación de todos los objetos en nuestra escena tridimensional, el proceso de renderizado pasa a una etapa muy importante. Hasta este punto, el juego era realmente tridimensional, pero el cuadro final ya no es así: en el curso de una serie de cambios, el mundo visto se transforma del espacio 3D, que consta de miles de puntos conectados, en una imagen bidimensional, que consiste en píxeles de colores. En la mayoría de los juegos, este procedimiento consta de al menos dos fases: espacio de pantalla de proyección (proyección de espacio de pantalla) y rasterización .


Volviendo a nuestra herramienta de renderizado basada en la web, nos mostrará cómo el volumen del mundo virtual se convierte en una imagen plana. La cámara se muestra a la izquierda, las líneas que emanan crean una pirámide truncada de visibilidad (frustum), y todo lo que entra en ella se puede mostrar en el cuadro final. La sección perpendicular de la pirámide se llama la ventana - esto es lo que se mostrará en el monitor. Se utilizan numerosos cálculos matemáticos para proyectar todo el contenido de la pirámide en el área de visualización, teniendo en cuenta la perspectiva de la cámara.

Aunque los gráficos en el área de visualización son bidimensionales, los datos siguen siendo realmente tridimensionales, y luego esta información se utilizará para calcular qué primitivas son visibles para nosotros y cuáles están ocultas. Esto puede ser sorprendentemente difícil de hacer, porque los primitivos pueden proyectar sombras visibles para nosotros, incluso si los primitivos mismos están ocultos para nosotros. Elimina escondidos de nosotros las primitivas llamadas caída (eliminación). Esta operación puede afectar significativamente la velocidad de renderizado de todo el cuadro. Después de que se completa la clasificación en primitivas visibles y ocultas, así como se eliminan los triángulos fuera de los límites de la pirámide de visibilidad, se completa la última etapa de tridimensionalidad y el marco se hace completamente bidimensional mediante rasterización.


La ilustración de arriba muestra un ejemplo muy simple de un cuadro que contiene una primitiva. La cuadrícula de píxeles se superpone a la forma geométrica y los píxeles correspondientes se marcan para el procesamiento posterior. El resultado final no se parece demasiado al triángulo original, porque no estamos utilizando suficientes píxeles. A este respecto, surge el problema del alias (aliasing, líneas escalonadas), que se resuelve de varias maneras. Por lo tanto, un cambio en la resolución del juego (el número total de píxeles en el cuadro) afecta tanto el resultado final: más píxeles no solo mejoran la visualización de los formularios, sino que también reducen el efecto de alias no deseado.

Después de completar esta parte de la representación, pasamos al siguiente gran paso: la coloración final de todos los píxeles en el marco.

Llevar la luz: etapa de píxeles


Hemos llegado a la etapa más difícil de renderizado. Una vez que se redujo a tirar de modelos de ropa (texturas) utilizando información de píxeles (originalmente obtenida de los vértices). Sin embargo, el hecho es que aunque las texturas y el marco en sí son bidimensionales, sin embargo, el mundo virtual en la etapa de procesamiento de vértices se distorsionó, cambió y cambió. Para tener en cuenta todo esto, se utilizan cálculos matemáticos adicionales, sin embargo, los nuevos problemas pueden ser característicos del resultado.


En esta ilustración, se aplica una textura de tablero de ajedrez al plano. Hay una onda visual desagradable, que se ve exacerbada por el alias. Para resolver este problema, utilice versiones más pequeñas de mapas de textura ( mapeos múltiples , mapas MIP), reutilice la información de estas texturas ( filtrado , filtrado) y cálculos matemáticos adicionales. El efecto es notable:


Para cualquier juego, esta fue realmente una etapa difícil, pero hoy ya no lo es, porque debido al amplio uso de otros efectos visuales, como reflejos y sombras, el procesamiento de texturas se ha convertido en una etapa relativamente pequeña del proceso de renderizado. Cuando se juega a altas resoluciones, la carga en las etapas de rasterización y procesamiento de píxeles aumenta, pero esto afecta el procesamiento de vértices relativamente poco. Aunque el color primario debido a las fuentes de luz se realiza en la etapa de vértice, se pueden aplicar efectos de iluminación más sofisticados.


En la ilustración anterior, ya no vemos cambios de color entre diferentes triángulos, lo que nos da la sensación de un objeto liso sin costuras. Aunque en este ejemplo la esfera consta del mismo número de triángulos que la esfera verde en la ilustración anterior, como resultado del procedimiento de coloración de píxeles, nos parece que se utilizan muchos más triángulos.


En muchos juegos, la fase de píxeles debe ejecutarse varias veces. Por ejemplo, para que un espejo o superficie del agua refleje el mundo circundante, primero debe dibujarse este mundo. Cada ejecución se denomina pasada (pasada), y para obtener la imagen final de cada cuadro se pueden usar fácilmente cuatro o más pasadas.

Además, a veces necesita ejecutar la etapa de vértice nuevamente para volver a dibujar el mundo desde otro punto y usar esta imagen en una escena que se muestra al jugador. Para hacer esto, use la representación de un solo búfer (objetivos de representación): use búferes que actúen como el almacenamiento final del marco, pero también pueden actuar como texturas con un paso diferente.

Para evaluar la complejidad de la etapa de píxeles, puede leerAnálisis de cuadros en Doom 2016 . Te sorprenderá la cantidad de operaciones que se necesitan para crear un marco.


Todo el trabajo realizado para crear el marco debe guardarse en el búfer, ya sea el resultado final o intermedio. En general, el juego utiliza sobre la marcha al menos dos buffers para la visualización final: uno para el "trabajo actual", y el segundo buffer está esperando que se acceda a un monitor o está en proceso de visualización. Siempre necesita un búfer de pantalla en el que se guardará el resultado de la representación, y cuando todos los búferes estén llenos, debe continuar y crear un nuevo búfer. Una vez finalizado el trabajo con el marco, se da un comando simple, se intercambian las memorias intermedias de marcos finales, el monitor recibe el último marco renderizado y comienza el proceso de renderización del siguiente marco.


En este cuadro de Assassin's Creed Odyssey , vemos el contenido del búfer de cuadros completo. Este contenido se puede representar en una tabla que contiene solo números. Se envían en forma de señales eléctricas a un monitor o TV, y los píxeles de la pantalla cambian sus valores. Nuestros ojos ven una imagen plana y sólida, pero nuestro cerebro la interpreta como tridimensional. Se oculta tanto trabajo detrás de escena de una sola toma en el juego que vale la pena echar un vistazo a cómo los programadores pueden manejarlo.

Gestión de procesos: API e instrucciones


Para descubrir cómo hacer que el juego ejecute y administre todos los cálculos, vértices, texturas, iluminación, buffers, etc. Esta es una tarea enorme. Afortunadamente, ayúdenos en estas interfaces de programación (interfaz de programación de aplicaciones, API).

Las API de representación reducen la complejidad general al ofrecer estructuras, reglas y bibliotecas de software que permiten instrucciones simplificadas que son independientes del hardware. Tome cualquier juego 3D lanzado para PC en los últimos tres años: fue creado usando una de las tres API populares: Direct3D, OpenGL o Vulkan. Hay otros desarrollos similares, especialmente en el segmento móvil, pero en este artículo hablaremos de los tres mencionados.


A pesar de las diferencias en los nombres de las instrucciones y operaciones (por ejemplo, un bloque de código para procesar píxeles en DirectX se llama sombreador de píxeles, y en Vulkan se llama sombreador de fragmentos), el resultado final no difiere, más precisamente, no debería diferir.

La diferencia se manifestará en qué equipo se utiliza para renderizar. Las instrucciones generadas por la API deben convertirse en comandos compatibles con el hardware que son procesados ​​por los controladores del dispositivo. Y los fabricantes de equipos tienen que gastar muchos recursos y tiempo para que sus conductores realicen esta conversión lo más rápido y correctamente posible.


Por ejemplo, la versión beta temprana de The Talos Principle (2014) era compatible con las tres API mencionadas. Para demostrar cómo pueden diferir los resultados de diferentes combinaciones de controladores e interfaces, ejecutamos el estándar de referencia incorporado al establecer la resolución a 1080p y la configuración de máxima calidad. El procesador Intel Core i7-9700K funcionaba sin overclocking, la tarjeta de video Nvidia Titan X (Pascal), RAM - 32 GB de RAM DDR4.

  • DirectX 9 = un promedio de 188.4 cuadros / s.
  • DirectX 11 = un promedio de 202.3 cuadros / s.
  • OpenGL = promedio 87.9 cuadros / s.
  • Vulkan = un promedio de 189.4 cuadros / s.

No analizaremos los resultados, y ciertamente no dicen que alguna API es "mejor" que la otra (no se olvide, la versión beta del juego fue probada). Solo diremos que la programación para diferentes API está asociada con varias dificultades, y en cualquier momento el rendimiento también será diferente. En general, los desarrolladores de juegos eligen la API con la que tienen más experiencia y optimizan su código para ello. A veces, el término motor se usa para describir el código responsable de la representación, pero estrictamente hablando, el motor es un conjunto completo de herramientas que procesa todos los aspectos del juego, no solo los gráficos.

No es tan fácil crear un programa desde cero que represente un juego en 3D. Por lo tanto, hoy en día se utilizan muchos sistemas con licencia de terceros (por ejemplo, Unreal Engine) Para evaluar su complejidad, abra el motor de código abierto para Quake y vea el archivo gl_draw.c: contiene instrucciones para diferentes operaciones de representación y refleja solo una pequeña parte de todo el motor. Pero Quake se lanzó hace más de 20 años, y todo el juego (incluidos todos los recursos visuales, sonidos, música, etc.) ocupa 55 MB. A modo de comparación, en Far Cry 5, solo los sombreadores ocupan 62 MB.

El tiempo es lo más importante: usar el equipo adecuado


Todo lo anterior puede ser calculado y procesado por el procesador de cualquier sistema informático. Los procesadores modernos de la familia x86-64 admiten todas las operaciones matemáticas necesarias e incluso contienen subsistemas separados para esto. Sin embargo, la tarea de renderizar un solo marco requiere numerosos cálculos repetidos y una paralelización significativa del trabajo. Los procesadores centrales no están adaptados para esto, porque están creados para resolver la gama más amplia posible de tareas. Los procesadores especializados para la informática gráfica se denominan GPU (unidades de procesamiento de gráficos). Se crean para DirectX, OpenGL y Vulkan.

Utilizaremos un punto de referencia que le permite renderizar un marco utilizando un procesador central o un equipo especializado: V-ray NEXTEmpresas del Grupo del Caos. De hecho, realiza el trazado de rayos en lugar de renderizar, pero la mayoría de las operaciones numéricas aquí también dependen del hardware.


Pasemos el punto de referencia en tres modos: solo el procesador central, solo el procesador gráfico y una combinación de ambos procesadores:

  • CPU sola = 53 millones de rayos
  • GPU sola = 251 millones de rayos
  • La combinación de ambos procesadores = 299 millones de rayos.

La unidad de medida puede ignorarse, la esencia es cinco veces la diferencia. Pero aún así, esta prueba no está demasiado relacionada con los juegos, así que pasemos al punto de referencia de la vieja escuela Futuremark 3DMark03 . Ejecutemos una prueba simple de Wings of Fury con un cálculo forzado de todos los sombreadores de vértices (es decir, con un conjunto completo de operaciones para mover y colorear triángulos) usando el procesador central.


El resultado no debería sorprenderte:

  • Procesador central = promedio 77 cuadros / s.
  • GPU = promedio 1,580 cuadros / s.

Cuando el procesador central realiza todos los cálculos con los vértices, se requiere un promedio de 13 ms para procesar y mostrar cada fotograma. Y cuando se usa un procesador de gráficos, esta cifra cae a 0.6 ms, más de 20 veces más rápido.

La diferencia aumenta aún más si ejecuta la prueba de referencia más difícil: la Madre Naturaleza. ¡El procesador central produjo 3,1 cuadros / s insignificantes! Y el procesador gráfico se disparó a 1388 cuadros / s .: casi 450 veces más rápido. Tenga en cuenta: 3DMark03 salió 16 atrás, y en la prueba en el procesador central solo se procesan los vértices, el procesador de gráficos aún toma la etapa de rasterización y píxeles. ¿Imagínese si el punto de referencia fuera moderno y la mayoría de las operaciones se realizaran mediante programación?


Ahora intentemos de nuevo con el punto de referencia de Unigine Valley , los gráficos que procesa son muy similares a los utilizados en juegos como Far Cry 5. También hay un motor de renderizado completo de software además del DirectX 11. Cuando se ejecuta en un procesador de video, obtuvimos un resultado promedio de 196 cuadros / s . ¿Qué pasa con la versión del software? Después de un par de fallas, una poderosa PC de prueba generó un promedio de 0.1 cuadros / s. - casi dos mil veces más lento.

La razón de una gran diferencia radica en los cálculos matemáticos y el formato de datos utilizado en la representación 3D. Cada núcleo de la CPU está equipado con módulos de punto flotante. El i7-9700K contiene 8 núcleos, cada uno con dos de estos módulos. Aunque la arquitectura de los módulos en Titan X es diferente, ambos tipos pueden realizar los mismos cálculos con datos del mismo formato. Esta tarjeta de video tiene más de 3,500 módulos para realizar cálculos comparables, y aunque su frecuencia de reloj es mucho menor que en el procesador central (1.5 GHz y 4.7 GHz), el procesador de video toma la cantidad de módulos.

Aunque la Titan X no es una tarjeta gráfica masiva, incluso un modelo económico superará a cualquier procesador central. Por lo tanto, todos los juegos 3D y API están diseñados para equipos especializados. Puede descargar V-ray , 3DMark o cualquier referencia de Unigine y pruebe su sistema: vea usted mismo qué tan bien están adaptados los procesadores de video para renderizar gráficos en juegos.

Ultimas palabras


Fue una breve digresión en el proceso de creación de un solo cuadro en juegos 3D, desde un punto en el espacio hasta una imagen colorida en un monitor.

De hecho, todo el proceso solo funciona con números. Sin embargo, mucho ha quedado fuera del alcance del artículo. No consideramos cálculos matemáticos específicos de álgebra lineal euclidiana, trigonometría y cálculos diferenciales realizados por sombreadores de vértices y píxeles. Tampoco hablamos sobre cómo se procesan las texturas mediante el muestreo estadístico. Omití efectos visuales tan geniales como bloquear la luz ambiental en el espacio de la pantalla, reducir la interferencia con el trazado de rayos, utilizando el rango dinámico extendido y el suavizado temporal.

Y la próxima vez que lance un juego 3D moderno, esperamos que no solo vea los gráficos con otros ojos, sino que también quiera saber más al respecto.

All Articles