Renderizado en Unreal Engine
Introducción al renderizado en motores de juego
El renderizado es el proceso de generar una imagen final (fotograma) en la pantalla a partir de una colección de objetos de una escena.
El software usado para renderizar un fotograma recibe el nombre de motor de renderizado, y estos motores suelen categorizarse como:
-
Renderizado sin conexión: diseñado para renderizados de alta calidad que priorizan la calidad sobre el tiempo de procesamiento. Suelen usarse en aplicaciones en las que el tiempo de renderizado no es importante en comparación con la calidad del fotograma renderizado final.
-
Renderizado en tiempo real: diseñado pensando en el rendimiento y en renderizar fotogramas rápidamente. Los objetivos típicos de la tasa de fotogramas en tiempo real son 30 (33 ms), 60 (16 ms) y 120 (8 ms) fotogramas por segundo (FPS), pero la tasa real de fotogramas puede variar con el tiempo en función de diferentes factores. Los proyectos desarrollados con renderizado en tiempo real deben encontrar un equilibrio entre rendimiento y calidad para mantener tasas de fotogramas costantes. Los motores de renderizado en tiempo real suelen usarse para medios interactivos, como videojuegos, simulaciones y visualización arquitectónica.
Unreal Engine es un potente conjunto de herramientas diseñadas para el renderizado en tiempo real que satisface las necesidades de diferentes plataformas, desde dispositivos móviles hasta avanzados ordenadores de sobremesa. Unreal Engine ofrece renderizado sin conexión y en tiempo real de alta calidad. Puedes usarlo para crear cualquier cosa, desde experiencias 2D y 3D interactivas en plataformas móviles, de consola y de sobremesa hasta renderizado de fotogramas finales para producciones de cine y televisión.
A diferencia de otros motores en tiempo real del mercado, Unreal Engine ofrece una gran cantidad de funciones propias diseñadas específicamente para el tiempo real y el rendimiento. El objetivo es reducir la complejidad del desarrollo y obtener resultados más rápidamente, al tiempo que se mantiene un elevado nivel de calidad y rendimiento.
Funciones como el sistema de iluminación global y los reflejos de Lumen, la Nanite Virtualized Geometry y los mapas de sombras virtuales son pasos importantes para alcanzar la meta de eliminar la complejidad del desarrollo con funciones que «actúan» en aplicaciones de consola y escritorio. Las plataformas móviles admiten la iluminación dinámica y los procesos de trabajo de iluminación precalculada que requieren que hagas bake de la iluminación en las texturas.
Introducción al renderizado en Unreal Engine
Los motores de juego llevan a cabo una serie de pasos, que suelen recibir el nombre de proceso de renderizado, para renderizar una imagen (o un fotograma) en la pantalla. Esta sección describe cómo hace esto Unreal Engine usando su ruta de renderizado diferido por defecto, y compara los pasos con la ruta de renderizado diferido de Unity cuando corresponde.
El motor de Unity tiene tres procesos de renderizado: el integrado, el universal y el de alta definición. Cada proceso está diseñado para casos de uso específicos, y suele seleccionarse antes de empezar un nuevo proyecto.
Unreal Engine tiene un proceso de renderizado unificado que escala funciones individuales en función de la plataforma de destino: desde dispositivos portátiles y móviles hasta la actual generación de consolas y PC. Esto significa que puedes elegir una ruta de renderizado y las funciones más adecuadas para tu proyecto, sin la obligación de optar por una ruta concreta.
El proceso de renderizado de Unreal Engine puede usarse con su ruta de renderizado diferida por defecto o configurarse para que se ejecute en una ruta de renderizado directo. Además, puedes habilitar la ruta de renderizado móvil para dispositivos de menor potencia, lo que incluye el Vulkan Mobile Renderer. Si deseas más información sobre las funciones de renderizado compatibles con las rutas de renderizado, lee la documentación de Supported Features by Rendering Path (Funciones compatibles con las rutas de renderizado).
La siguiente imagen muestra una visualización conceptual de los pasos que realiza Unreal Engine en cada fotograma para renderizar una imagen final usando la ruta de renderizado diferido:
El proceso fluye de izquierda a derecha, y los pasos 2-5 se suceden en paralelo.
A continuación tienes más información sobre cada uno de estos pasos en el proceso de renderizado y lo que necesitas para renderizar cada fotograma.
Preparación de la escena y oclusión
Unreal Engine tiene tres subprocesos principales: el del juego (CPU), el de trazado y el de la GPU.
Antes de iniciar el proceso de renderizado, el subproceso de juego (o de la CPU) recopila las transformaciones de todos los objetos de la escena. Esto incluye el procesamiento de todas las animaciones, simulaciones de física e inteligencia artificial (IA) antes de recopilar la transformación final de cada objeto.
A continuación, la información de las transformaciones se pasa al subproceso de trazado en la CPU. El subproceso de trazado ejecuta el proceso de cribado, que compila una lista de objetos visibles en la vista de cámara actual y elimina todos los demás objetos que no son visibles para la cámara. No es necesario trazar estos objetos, y no renderizarlos aumenta el rendimiento.
Este proceso tiene los siguientes pasos (en orden):
- Cribado de distancia: elimina todos los objetos que están más lejos de una distancia específica de la cámara.
- Cribado de tronco: elimina los objetos que no son visibles dentro del tronco (vista) de la cámara.
- Cribado de oclusión: comprueba con precisión el estado de visibilidad de todos los objetos restantes de la escena. Este método es costoso y, por lo tanto, se realiza al final del proceso de oclusión, cuando los objetos visibles restantes se prueban de nuevo para ver si están ocluidos (ocultos) por otros objetos.
La lista final de objetos visibles se pasa al subproceso de la GPU para iniciar el proceso de renderizado.
Equivalente de Unity
Unity realiza el cribado de tronco y el cribado de oclusión durante su proceso de renderizado. Además, puedes realizar el cribado de distancia con tu API CullingGroup. Una combinación de estas técnicas crea la lista final de objetos visibles en la escena.
Renderizado de geometría
En este paso, Unreal Engine recorre la lista de objetos visibles en la escena y los prepara para el siguiente paso, en el que convierte los datos de vértices 3D en datos de píxeles que se muestran en la pantalla.
Sombreadores de vértices
Un sombreador es código que se ejecuta directamente en la GPU y se usa para realizar una serie de cálculos. Son eficientes y la GPU puede ejecutar muchos cálculos de sombreador en paralelo.
El sombreador de vértices lleva a cabo los siguientes pasos:
- Convierte posiciones locales de los vértices en una posición en el mundo: los datos de vértices del objeto se almacenan en el espacio local, pero, cuando el objeto se coloca en el mundo, la información sobre los vértices debe convertirse en coordenadas del espacio en el mundo.
- Gestiona el color y el sombreado de los vértices: el sombreador de vértices gestiona el suavizado de vértices y los datos de colores de vértices en el propio objeto.
- Puedes aplicar desfases adicionales a las posiciones de los vértices: el sombreador de vértices puede aplicar un desfase a la posición de cualquier vértice en la pantalla para lograr efectos específicos. Esto se hace mediante el material del objeto y se denomina desfase de la posición en el mundo.
Pasada de profundidad
Antes de renderizar objetos individuales, Unreal Engine realiza una pasada de profundidad, o pasada Z temprana, para determinar la ubicación de los objetos en relación con los demás. Esto impide que Unreal Engine renderice los mismos píxeles en la pantalla varias veces, lo cual se denomina superposición (de píxeles), y puede tener un impacto significativo en el rendimiento, por lo que el motor intenta evitarlo por todos los medios.
Llamadas de trazado
Tras la pasada de profundidad, la GPU renderiza cada objeto trazando al mismo tiempo todos los polígonos que comparten las mismas propiedades, como mallas y materiales. Esto se conoce como llamada de trazado.
Todos los polígonos de un objeto asignados al mismo material se cuentan como la misma llamada de trazado. Sin embargo, cada material requiere su propia llamada de trazado. Por ejemplo, cada objeto en pantalla requiere como mínimo una llamada de trazado, pero podría tener más en función del número de materiales asignados al objeto.
La Nanite Virtualized Geometry (geometría virtualizada de Nanite) de Unreal Engine renderiza al mismo tiempo todos los polígonos de todos los objetos con un material específico. Las estimaciones de fotogramas ya no están limitadas por recuentos de polígonos, las llamadas de trazado ni el uso de memoria de malla.
Equivalente de Unity
El proceso de renderizado de Unity sigue pasos similares en los que realiza una pasada de profundidad y utiliza llamadas de trazado para dibujar los objetos en la escena.
Rasterización y el búfer de geometría
El proceso de rasterización convierte datos de vértices 3D en datos de píxeles 2D que se muestran en la pantalla. Este proceso comienza después de que el sombreador de vértices termine de procesar todos los datos.
El búfer de geometría (GBuffer) de Unreal Engine incluye una serie de imágenes que almacenan información sobre la geometría de la escena. Estas imágenes suelen incluir información sobre la iluminación del color base, la normal del mundo, el metalizado, la rugosidad y la información especular en la escena. Estas imágenes en el GBuffer se componen para formar la imagen final que ves en la pantalla.
El proceso de conversión de estas imágenes compuestas ocurre en cada fotograma que se renderiza y cada llamada de trazado en la que los datos de vértices se convierten en datos de píxeles y se dibujan las partes correctas de las imágenes en el GBuffer.
Equivalente de Unity
La ruta de renderizado diferido de Unity también utiliza un GBuffer para almacenar información importante sobre la escena. En el caso de Unity, el GBuffer almacena información similar sobre la escena (a la que se referencia con diferentes nombres): albedo, información especular, normal y del emisor/de la iluminación de los objetos.
Renderizado de texturas
Unreal Engine renderiza texturas mediante la transmisión de texturas para optimizar la carga de texturas en la escena. El sistema de transmisión de texturas utiliza mapas MIP de textura. Se trata de una secuencia precalculada de imágenes de la misma textura en diferentes resoluciones. Puedes tomarlo como niveles de detalle (LOD) para texturas en lugar de mallas. El motor crea automáticamente estos mapas MIP en los que cada imagen tiene la mitad de resolución que la anterior.
Unreal Engine transmite el mapa MIP de la textura durante el juego en función de la distancia a la cámara. Esto se hace automáticamente para optimizar el ancho de banda y el consumo de memoria, así como para reducir el ruido lejos de la cámara.
El tamaño de las texturas debe ser una potencia de 2 para recibir mapas MIP. Los tamaños de textura comunes incluyen 3840 × 2160 píxeles (4K) y 1920 × 1080 píxeles (HD). Ten en cuenta que no es necesario que las texturas tengan una relación específica: una textura de 1920 × 480 píxeles también recibirá mapas MIP.
Equivalente de Unity
El sistema Mipmap Streaming de Unity utiliza mapas MIP de textura para transmitir sus texturas en tiempo de ejecución. Al igual que en Unreal Engine, este sistema transmite automáticamente el mapa MIP de textura adecuado en función de la distancia y el ángulo con respecto a la cámara.
Sombreadores de píxeles y materiales
Una vez que los objetos se han renderizado completamente en el GBuffer, Unreal Engine comienza a sombrear cada objeto en la pantalla, para lo cual utiliza las propiedades del material de cada objeto con el sombreador de píxeles.
Un sombreador de píxeles realiza una serie de cálculos para modificar el color de un píxel en la pantalla. Los sombreadores de píxeles se ejecutan en la GPU y son extremadamente eficientes. Controlan el sistema de materiales de Unreal Engine y se utilizan para calcular la iluminación, la niebla, los reflejos y los efectos de posprocesamiento.
El sistema de materiales utiliza plantillas de sombreador de lenguaje de sombreador de alto nivel (HLSL) junto con el editor de materiales para crear los materiales finales que se aplican a los objetos en la pantalla. Estos materiales pueden utilizar parámetros, como texturas, para definir el aspecto de cada objeto.
Equivalente de Unity
Unity viene con varios sombreadores prediseñados (equivalentes a los materiales en Unreal Engine) junto con su grafo de sombreador para crear sombreadores para tu proyecto. El editor de materiales de Unreal Engine es el equivalente al grafo de sombreador de Unity.
Reflejos
Después de sombrear todos los objetos de la escena, Unreal Engine comienza a renderizar los reflejos de los objetos en función de sus propiedades de material.
Unreal Engine utiliza cuatro sistemas para renderizar reflejos en la escena. Estos sistemas se ejecutan en el siguiente orden:
- Capturas de reflejos: precalculadas y almacenadas en un mapa de cubos estático en una ubicación específica.
- Reflejos en plano: captura los reflejos desde y en un plano.
- Reflejos en espacio de pantalla (SSR): utiliza la información disponible en pantalla para dibujar reflejos precisos de los objetos en tiempo real.
- Reflejos de Lumen: resuelve los reflejos de toda la gama de valores de rugosidad de la escena. Estos reflejos incluyen compatibilidad con la luz cenital, materiales de capa transparente, traslucidez e incluso materiales de agua de una sola capa.
Unreal Engine integra los tres métodos: da prioridad a los reflejos en espacio de pantalla, vuelve a los reflejos en plano y, por último, vuelve a las capturas de reflejos. El resultado final del reflejo se combina con las imágenes de rugosidad, especulares y metálicas en el GBuffer.
Si estás usando la iluminación global de Lumen, los reflejos de Lumen se utilizarán automáticamente. Sin embargo, también puedes usar reflejos de Lumen sin iluminación global de Lumen, en cuyo caso Unreal Engine utilizará iluminación con bake con reflejos de Lumen.
Equivalente de Unity
Las sondas de reflejo de Unity ofrecen una funcionalidad similar y se utilizan para precalcular los datos de reflexión de tu escena.
Iluminación estática y sombras
Después de renderizar los reflejos, Unreal Engine renderiza la iluminación estática y las sombras de todos los objetos de la escena.
Unreal Engine utiliza su sistema de iluminación global de Lightmass para precalcular la información de iluminación de la escena. La información de iluminación y sombras se almacena en una textura de UV de mapa de luz, que se mezcla con el color base del objeto al renderizar el objeto en la escena.
Este sistema es muy rápido pero requiere más memoria y debe calcularse previamente cada vez que hay un cambio en la escena.
El sistema de iluminación global de Lightmass es una buena opción para proyectos dirigidos a dispositivos móviles y de baja potencia.
Equivalente de Unity
Los sistemas Progressive Lightmapper y Enlighten Baked Global Illumination de Unity ofrecen una funcionalidad similar al precalcular la iluminación de la escena.
Iluminación dinámica y sombras
Después de renderizar la iluminación estática, Unreal Engine renderiza la iluminación dinámica y las sombras (en tiempo real) con Lumen, su sistema de iluminación global dinámica.
Lumen es un sistema de iluminación global dinámica y reflejos diseñado para consolas de nueva generación y PC de gama alta. El sistema utiliza varios métodos de trazado de rayos para resolver la iluminación global y los reflejos a escala.
Lumen proporciona rebotes difusos infinitos y funciona de manera uniforme con la geometría virtualizada de Nanite. Además, el sistema funciona en conjunto con los mapas de sombras virtuales para crear sombras suaves de alta resolución en tiempo real.
Lumen proporciona reflejos de Lumen que resuelven los reflejos de toda la gama de valores de rugosidad de la escena. Estos reflejos incluyen compatibilidad con la luz cenital, materiales de capa transparente, traslucidez e incluso materiales de agua de una sola capa.
Lumen reemplaza los reflejos en espacio de pantalla cuando se usa en la escena.
Equivalente de Unity
Unity utiliza Enlighten Realtime Global Illumination para proporcionar iluminación dinámica en la escena. Este sistema proporciona iluminación global en tiempo real mediante la información de visibilidad precalculada junto con mapas de luz para calcular el rebote de luz indirecta en tiempo de ejecución.
Esto se diferencia de Lumen, ya que Lumen no requiere ningún dato precalculado para proporcionar rebotes de luz indirecta.
Niebla y transparencia
Después de renderizar la iluminación dinámica y las sombras, Unreal Engine renderiza los efectos de niebla y transparencia.
Unreal Engine renderiza los efectos de niebla con su sistema de niebla de altura exponencial, que renderiza la densidad de la niebla en función de la altura y la distancia desde la cámara. Además, el sistema puede generar niebla volumétrica.
Los objetos transparentes utilizan un material traslúcido y se renderizan en esta etapa del proceso. Al utilizar la ruta de renderizado diferido, Unreal Engine utiliza la información disponible en el GBuffer para renderizar la transparencia. También puedes configurar el material para utilizar la ruta de renderizado directo para producir un efecto de transparencia más preciso.
Equivalente de Unity
Unity admite niebla lineal, exponencial y exponencial al cuadrado en la escena.
Efectos de posprocesamiento
Una vez renderizadas la niebla y la transparencia, Unreal Engine puede aplicar más efectos sobre la imagen. Estos efectos se denominan efectos de posprocesamiento porque se aplican después de procesar la imagen final. Los efectos se basan en el sombreador de píxeles y utilizan la información disponible en el GBuffer.
Algunos efectos de posprocesamiento comunes incluyen el bloom de iluminación, la profundidad de campo, los haces de luz, el mapeado de tonos y el desenfoque de movimiento.
Como parte de este paso de posprocesamiento, Unreal Engine puede aplicar la superresolución temporal (TSR). TSR es un escalador temporal independiente de la plataforma que Unreal Engine utiliza para renderizar bonitas imágenes 4K. Las imágenes se obtienen a una fracción del coste al amortizar algunos de los costosos cálculos de renderizado en muchos fotogramas.
En la cadena de renderizado, la superresolución temporal se produce después de la profundidad de campo y todo lo que sigue se amplía, como el desenfoque de movimiento, el bloom, etc.
Una vez que estos efectos se aplican al GBuffer, Unreal Engine renderiza la imagen final en la pantalla.
Los pasos descritos anteriormente generan un solo fotograma en la pantalla. Estos pasos suelen repetirse entre 30 y 60 veces por segundo, en función de la tasa de fotogramas objetivo del juego.
Equivalente de Unity
Unity viene con soluciones de posprocesamiento en función del proceso de renderizado elegido. Muchos de los efectos disponibles son similares a los de Unreal Engine.
Además, Unity 6 también viene con Spatial-Temporal Post-processing (STP), un escalador nativo basado en software que utiliza técnicas de aumento de muestreado espacial y temporal para producir una imagen con antialiasing de alta calidad.
Presentación de las funciones de renderizado en Unreal Engine
Ahora que comprendes los pasos que sigue Unreal Engine para renderizar un fotograma en la pantalla, estás listo para obtener más información sobre las funciones de renderizado específicas que vienen con el motor.
Más información sobre las funciones de renderizado de Unreal Engine en la documentación Lighting the Environment (Iluminación del entorno).