Prólogo
Después del lanzamiento del último juego de la serie Metro, pasé varias horas estudiando su trabajo interno y decidí compartir algo que podría parecer interesante desde un punto de vista tecnológico. No realizaré un análisis detallado ni estudiaré el código desarmado de los sombreadores, pero mostraré las decisiones de alto nivel tomadas por los desarrolladores en el proceso de creación del juego.
Por el momento, los desarrolladores aún no han hablado sobre las técnicas de renderizado utilizadas en el juego. La única fuente oficial de información es el
informe de GDC , que no se puede encontrar en ningún otro lugar en Internet. Y esto es molesto, porque el juego se ejecuta en un motor propietario muy interesante que ha evolucionado desde juegos anteriores en la serie Metro. Este es uno de los primeros juegos en usar
DXR .
Nota: este artículo no es una descripción completa y volveré sobre él si encuentro algo que valga la pena agregar. Quizás me perdí algo, porque algunos aspectos aparecen solo en las siguientes etapas del juego, o simplemente miré los detalles.
Primeros pasos
Me llevó varios días encontrar un entorno capaz de trabajar con este juego. Después de probar varias versiones de RenderDoc y PIX, decidí estudiar los resultados del trazado de rayos con Nvidia NSight. Quería aprender renderizado sin trazado de rayos, pero NSight me permitió explorar también los detalles de esta función, así que decidí dejarla activada. Para el resto de la representación, PIX es un buen ajuste. Se tomaron capturas de pantalla usando ambas aplicaciones.
NSight tiene un inconveniente: no admite guardar la captura en un archivo, por lo que no pude volver a los cuadros que estaba estudiando.
Al comienzo de mi trabajo, también me encontré con otro problema que no tenía nada que ver con las aplicaciones de depuración de marcos: las funciones de trazado de rayos requerían instalar la última actualización de Windows, pero el juego permitió que se incluyeran en las opciones sin instalar la actualización. En este caso, la inclusión de funciones hizo que el juego se bloqueara al inicio. La Experiencia GeForce tampoco dijo nada sobre la necesidad de la versión correcta de Windows para habilitar estas funciones. Este problema debe abordarse en ambos lados.
En aras de la exhaustividad, hice capturas de un juego que se ejecuta con los parámetros máximos posibles, pero sin DLSS.
Análisis de trama
Marco terminadoUn breve análisis de la representación demuestra un conjunto bastante estándar de funciones, con la excepción de la iluminación global realizada por el trazado de rayos (GI trazado de rayos).
Antes de renderizar la imagen, la escala del cuadro anterior se reduce en la cola de cálculo y se calcula el brillo promedio.
La cola gráfica comienza con la representación de partículas de distorsión (gotas en la cámara), que se aplican en la etapa de postprocesamiento. Luego, un rápido paso preliminar de las profundidades crea una parte de las profundidades frente al Gbuffer; parece que solo representa un alivio.
El pase GBuffer llena 4 objetivos de renderizado de acuerdo con el siguiente diagrama, y también completa el llenado de la memoria intermedia de profundidad.
1. Objetivo en formato RGBA8 con albedo y, posiblemente, oclusión ambiental en el canal alfa; En algunas superficies se ve muy oscuro.2. Objetivo en formato RGB10A2 con normales y, posiblemente, una máscara de dispersión subsuperficial en el canal alfa.3. Objetivo en formato RGBA8 con otros parámetros de material, probablemente metalidad y rugosidad en el canal alfa. Curiosamente, los canales RGB en este caso contienen exactamente los mismos datos.4. Objetivo en formato RG16F con vectores de movimiento 2D.Una vez que las profundidades están completamente llenas, se construye un buffer de profundidad lineal y su escala disminuye. Todo esto se hace en la cola de cómputo. En la misma cola, el búfer se llena con algo similar a la iluminación direccional sin usar sombras.
En la cola de gráficos, la GPU traza los rayos de iluminación global, pero hablaré más sobre esto a continuación.
La cola de cómputo calcula la oclusión ambiental, los reflejos y algo similar al reconocimiento de bordes.
En la cola gráfica, se representa un mapa de sombra de cuatro etapas en un mapa de profundidad de 32 bits de tamaño 6k * 6k. Más sobre esto a continuación. Después de completar el mapa de sombras dirigidas, la resolución de la tercera cascada por razones desconocidas disminuye a 768 * 768.
En medio del proceso de representación de sombras, hay un momento curioso: el atlas de impostores se complementa con algunos objetos antes de generar sombras locales a partir de la iluminación (sobre qué impostores se pueden encontrar
aquí ). Tanto los buffers impostores como los buffers de sombra de iluminación local también tienen texturas de 6k * 6k.
Después de completar todas las sombras, comienza el cálculo de la iluminación. Esta parte de la representación es bastante incomprensible, porque hay muchas representaciones que realizan algunas acciones misteriosas y, por lo tanto, requieren un estudio adicional.
La representación de la escena finaliza con objetos iluminados frontalmente (ojos, partículas). Los efectos visuales se procesan en un búfer de media resolución, después de lo cual se componen con objetos opacos utilizando el zoom.
La imagen final se logra mediante la corrección tonal y el cálculo de la floración (disminuye y luego aumenta la resolución del cuadro con la corrección tonal). Finalmente, la interfaz de usuario se representa en un búfer separado y, junto con la composición de floración, se superpone en la parte superior de la escena.
No encontré la parte en la que se realiza el suavizado, así que lo dejaré para más adelante.
Rastreo global de rayos de luz
Alguna información sobre la iluminación global realizada por GI con trazado de rayos. Esta estructura acelerada cubre una gran área del mundo del juego, probablemente varios cientos de metros, mientras que mantiene detalles muy altos en todas partes. Parece que se está transmitiendo de alguna manera. La escena de la estructura de aceleración no coincide con la escena rasterizada, por ejemplo, los edificios en la imagen a continuación no son visibles en la forma rasterizada.
Vista superiorAquí podemos ver cuatro fichas que rodean la posición del jugador. También es evidente la falta de geometría que se está probando en el canal alfa. Los árboles tienen troncos, pero no hay follaje, ni hierba, ni arbustos.
Vista cercanaEn la vista de primer plano, se ven mejor los detalles y la densidad de los objetos. Cada objeto de un color diferente tiene su propia estructura aceleradora del nivel inferior. Solo en esta imagen hay varios cientos de ellos.
Artículos del jugador bajo los piesCuriosamente, los artículos del jugador también son parte de la estructura de aceleración, pero por alguna razón se encuentran debajo de sus pies.
Rotura de la piel?¿Desollado de nuevo?Algunos de los objetos con aspecto desollado se ven rotos en la estructura de aceleración. Uno de los problemas observados es estirar la malla (en las piernas del niño). Otro problema lleva al hecho de que diferentes partes del personaje con desuello están en diferentes posiciones. No hay estiramiento, pero las partes están separadas entre sí. Parece que nada de esto es visible en la iluminación global de trazado de rayos, o al menos no he podido notar esto en el juego.
Una gran cantidad de objetosEn un plano más general, puede ver cuántos objetos diferentes hay en la estructura de aceleración. La mayoría de ellos no contribuirá realmente a los resultados de los cálculos de la iluminación global. También se ve aquí que no hay un esquema LOD. Todos los objetos se agregan con todo detalle. Sería interesante saber si esto tiene algún efecto sobre el trazado de rayos (supongo que sí).
LOD ultra alto, cada escala y conmutador totalmente modeladosOtra captura de pantalla muestra un gran detalle de objetos incluso lejos del jugador. Cada interruptor y cada escala en esta imagen son claramente legibles incluso sin texturas. El lugar donde moví la cámara para tomar esta captura de pantalla se encuentra a decenas de metros del reproductor y eliminar estos detalles no habría empeorado la calidad de la imagen. Quizás actualizar la estructura de aceleración usando LOD sería demasiado costoso, pero existe una alta probabilidad de que esta actualización se pueda realizar de forma asincrónica. Definitivamente vale la pena explorar este punto con más detalle.
Renderizado de sombras direccionales
La parte principal de renderizar sombras es simple y no requiere mención especial, pero aquí hay puntos interesantes.
Mallas para las cuales es improbable la proyección de sombrasEnormes detalles en mapas de sombrasMallas que parecen usar el búfer de índice incorrectoParece que, como las estructuras de aceleración, el renderizado de sombras incluye absolutamente todo. Hay objetos que casi no contribuyen al mapa de sombras, pero aún así se representan. Me pregunto si esto sucede debido a un permiso, o ¿no hay una manera fácil en el motor de excluirlos?
Hay objetos que son difíciles de notar incluso con sombras en el espacio de la pantalla. No toma mucho tiempo renderizarlos, pero sería interesante ver si pueden eliminarse para ahorrar un poco de tiempo.
Al estudiar la malla, parece que algunas de las mallas renderizadas en el mapa de sombras tienen búferes de índice rotos, pero después del sombreador de vértices se ven correctos (los resultados son los mismos en PIX y NSight). Este es el mejor ejemplo que logré encontrar, pero está lejos de ser el único. ¿Tal vez esta es una especie de posición de empaque especial?
Las mallas parecen tener poca pielEl desollado parece estar causando problemas no solo en las estructuras de aceleración. Curiosamente, no conduce a artefactos visibles en la pantalla.
Parte 2
Enmienda menor
En la parte anterior, escribí que el tercer objetivo de renderizado del búfer GBuffer probablemente contenga metalidad, pero parece que en realidad contiene color especular. Al principio no vi ningún color y no entendí por qué los tres canales RGB contienen los mismos datos, pero probablemente fue porque no había reflejos de color en la escena. Para esta arma, el búfer contiene muchos más colores diferentes.
También se me olvidó agregar mi textura favorita, que encontré en el proceso de investigación de la representación del juego. Definitivamente vale la pena mencionarlo porque demuestra la naturaleza caótica del desarrollo del juego cuando no siempre es posible limpiarlo.
"¡Mejorame!"Composición de transparencia y anti-aliasing
Intentando descubrir cómo aumenta la resolución del búfer de transparencia de tamaño medio y cómo el juego realiza antialiasing, noté algo interesante. Necesitaba una escena donde hubiera mucho más contraste para que fuera claramente visible lo que estaba sucediendo. Afortunadamente, logré capturar un cuadro en el que el arma del jugador se mueve ligeramente entre cuadros.
Antes de renderizar transparenciaParece que antes de componer el búfer de transparencia, el búfer ya contiene una imagen completamente renderizada, y dado que no hay bordes afilados en este marco, es lógico suponer que estos son los datos del marco anterior.
Después de componer la transparencia del marco actualAl agregar transparencia al marco actual, podemos notar bordes rotos individuales. Sucedió porque el arma se movió ligeramente a la derecha. Algunas nubes se vuelven transparentes, pero se recortan en el horizonte (que es opaco), por lo que la composición no cambia la parte inferior, sino que ya se representa sobre la malla del arma del cuadro anterior utilizando el búfer de profundidad del cuadro actual.
Después de agregar opacidad al marco actualDespués de varias llamadas de sorteo, se realizan mallas de composición y opacas. Parece que no hay ninguna razón particular para hacer esto en este orden. Es lógico componer el búfer de transparencia en los datos de los objetos opacos del marco actual, pero esto no sucede, y sería interesante saber por qué.
Después de TAADespués de completar el fotograma completo, el paso TAA (suavizado temporal) suaviza los bordes. Ya estaba interesado en esto antes, porque no veía dónde tiene lugar el alisado. Pero me salteé esto porque inmediatamente después de esta llamada de sorteo comienza la disminución de resolución para el pase de floración y pierdo esta llamada de sorteo.
Destello de lente
Por lo general, no quiero analizar los efectos individuales, pero hay muchas formas de implementar el destello de la lente, por lo que tenía curiosidad sobre qué desarrolladores eligieron.
Destello de lente en composición preparadaEn la mayoría de los casos, el destello de la lente apenas se nota, pero este es un efecto hermoso. Es difícil de mostrar en la captura de pantalla, por lo que no pondré mucho esfuerzo en esto.
Destello de lente en buffer de floraciónDespués de buscar, encontré una llamada de sorteo que agrega este efecto, y resultó que era una llamada después de la última etapa de elevar la resolución de floración. En este búfer, el efecto es mucho más notable.
Destello de lente de geometríaSi nos fijamos en la geometría, el destello de la lente es bastante simple. Al menos 6 cuadrángulos están involucrados en la creación del resultado final en la pantalla, pero no hay una serie de cuadrángulos más pequeños que se acerquen a la posición del sol. Podemos concluir que esta es una solución bastante estándar, aunque algunos desarrolladores procesan el destello de la lente directamente en la escena del renderizado, mientras que otros calculan el efecto como postprocesamiento.
Representación del terreno
En todos los juegos de mundo abierto, una de las dificultades más interesantes es renderizar terreno. Decidí que podría parecer interesante estudiar este aspecto, pero, francamente, un poco decepcionado.
A primera vista, un fragmento del relieve parece que se está realizando algún tipo de teselación. La forma en que se deforma el relieve durante el movimiento hace que sea lógico suponer que existe un desplazamiento adicional. Además, en una PC, el juego usa activamente teselación, por lo que sería lógico usarlo en relieve.
Tal vez tenía los parámetros incorrectos establecidos, pero el juego muestra todos los fragmentos del relieve sin teselación. Para cada fragmento del relieve, ella usa esta cuadrícula uniforme de 32 * 32. Tampoco hay LOD.
Al observar un fragmento del relieve después del sombreador de vértices, puede ver que la mayoría de los pares de vértices se fusionaron para formar una cuadrícula casi perfecta de 16 * 16, con la excepción de algunos lugares que requieren más precisión (probablemente debido a la curvatura del relieve). La deformación mencionada anteriormente probablemente surge debido a la lectura de las texturas mip del mapa de elevación del relieve cuando el relieve está lejos de la cámara.
Trucos de seguimiento de rayos
Y ahora sobre lo que todos esperaban.
Streaming de datos
Uno de los aspectos más interesantes de cualquier implementación de DXR en este momento es la forma en que trabaja con los datos. Lo más importante es cómo se cargan los datos en las estructuras de aceleración y cómo se actualizan. Para probar esto, tomé dos capturas y comparé las estructuras de aceleración en NSight.
El jugador está dentro de la nave.En la primera captura, me paré dentro de una nave rota, que es visible en el centro de esta imagen. Solo se cargan los objetos más cercanos, excepto las rocas grandes en el borde del mapa.
El jugador se ha movido a la esquina superior izquierda de esta imagen.En la segunda captura, me alejé del borde del mapa y me acerqué al borde superior izquierdo de la imagen. La nave y todo lo que la rodea todavía está cargada, pero también se han cargado nuevos objetos. Curiosamente, no puedo definir ninguna estructura de mosaico. Los objetos se pueden cargar / eliminar de la estructura de aceleración en función de la distancia y la visibilidad (¿posiblemente limitando el paralelogramo?). Además, el borde superior derecho se ve más detallado, aunque se ha alejado de él. Sería interesante saber más sobre esto.
Alivio y lo que hay debajo
Se pueden mencionar varios aspectos de la implementación de DXR en Metro: Exodus con respecto al terreno.
En primer lugar, es interesante que las estructuras de aceleración no contengan ninguna malla de alivio (con la excepción de casos especiales). Estos monstruos realmente corren en el juego en el suelo, pero a juzgar por los datos en NSight, podrías pensar que están volando. Esto plantea una pregunta interesante para nosotros: ¿la implementación de la iluminación global puede tener en cuenta el terreno (posiblemente usando un mapa de altura y material de relieve) o no?
Al momento siguiente, nunca me habría dado cuenta si el alivio estuviera en su lugar. Al observar el comienzo del nivel en la estructura acelerada en NSight, noté algunas mallas debajo del relieve.
Los artistas a menudo, por varias razones, colocan mallas de depuración debajo del nivel, pero generalmente se eliminan antes de que se lance el juego. En este caso, estas mallas no solo sobrevivieron hasta el lanzamiento, sino que también se convirtieron en parte de la estructura de aceleración.
Además de los mencionados anteriormente, encontré otras mallas dispersas debajo del relieve. Básicamente, no merecen mucha mención, pero este fue muy interesante: este es un personaje que se encuentra justo debajo del punto de partida del nivel. Incluso tiene su propia piscina.
Finalmente, el último elemento curioso de la estructura de aceleración son las mallas unilaterales que miran hacia afuera del nivel. A menos que se consideren bilaterales, hay muy pocas posibilidades de que hagan alguna contribución a la imagen del juego. Incluso si las mallas son de dos lados, están tan lejos del área jugable que probablemente solo estiren la estructura de aceleración. Es interesante ver que no están filtrados.
Esta imagen también muestra uno de los casos especiales de la "malla de relieve" en la esquina inferior derecha, entre el tren y el edificio.Decapitación con desuello
Ya hablé sobre los problemas de desollar mallas, pero a este nivel noté algo más.En primer lugar, este monstruo muestra ambos errores en una imagen, lo cual noté anteriormente. Todavía me pregunto qué los causó.También noté que estas pequeñas criaturas, como los murciélagos, no tienen cabezas en la estructura acelerada.Otro ejemplo. Observe el agujero donde debería estar la cabeza. No he visto un solo caso donde la cabeza fuera visible.El mismo tipo de criaturas en modo rasterización. Tenga en cuenta que la cabeza es claramente visible.Y aquí está la estructura metálica de la cabeza.En conclusión
Eso es todo por hoy. Espero que hayas disfrutado este vistazo al interior de Metro: Exodus.Continuaré explorando la representación del juego, pero no publicaré nuevas partes del artículo a menos que encuentre algunas partes especiales que sean interesantes para las personas, o encuentre algo que valga la pena compartir.