En esta entrada entramos ya a la Iluminación de tres rebotes o más conocida como iluminación global.

shad2-globalillum1

Los sistemas para la iluminación de tres rebotes o más que habitualmente se han utilizado no son sistemas que rendericen las escenas a tiempo real y no se basan en el algoritmo de rasterizado sino que utilizan algoritmos como el Raytracing para generar la escena con una mayor precisión visual pero no son técnicas basadas en la velocidad sino en la fidelidad visual por lo que no se utilizan en el renderizado de escenas a tiempo real pero el Raytracing es importante por el hecho que tiene una enorme influenia en lo que es rasterizado con tres rebotes por el hecho que toma conceptos de este por lo que si me permitís voy a hacer un inciso a como funciona el Raytracing.

El modelo más básico del Raytracing es la del objeto emitiendo directamente su valor de color a la cámara, este es llamado RayCasting y vamos a decir que tiene una complejidad «E» donde E es el valor de emisión de la fuente fuente de luz.

275_Ray Casting - Polygon Rendering and Ray Tracing Methods

La primera hornada de juegos 3D para PC que no utilizaban polígonos como Doom utilizaban el Raycasting.

Doom

¿Pero cuando se convierte el Raycasting en Raytracing? Cuando empezamos a añadir rebotes de luz… ¿Pero de donde sale la fuente de luz primaria? Pues ni más ni menos que de la cámara y cada vez que un rayo toca con un objeto este va rebotando hasta que se llega al limite marcado por el renderizado o cuando se cumplen las siguientes condiciones:

  1. La intensidad/energia del rayo es lo suficientemente baja como para no tener que representarse.
  2. El rayo deja la escena.

Dado que por cada rebote el rayo tiene que interactuar con cada uno de los pixeles de la escena el coste computacional con cada nuevo rebote aumenta considerablemente:

slide_39

El Raytracing solo tiene ventaja visual sobre la Rasterización a partir de la Iluminación Global pero… ¿Se pueden aplicar los mismos conceptos? Para empezar hemos de tener en cuenta que las fuentes de luz en el caso de la Rasterización no tienen como origen el ojo/cámara sino un objeto concreto desde donde parte la fuente de luz y luego tenemos que tener en cuenta que la precisión no es a nivel de pixel sino a nivel de fragmento (2×2 pixeles) y que la iluminación por rasterizado no tiene ne cuenta rayos de luz sino que hay unos tipos de luces estándar que se aplican en OpenGL, Direc3D y otras APIs similares.

light_types

la generación de luces direccionales va muy bien para simular la iluminación especular, la iluminación desde un punto para similar la difusa y el efecto foco de luz va de maravilla para simular la luz ambiental. Las limitaciones del Rasterizado gracias a esto se ven ya con la iluminación indirecta donde una buena parte de la información falta y por tanto el resultado no es el que debería ser.

RayvsRas

El algoritmo del Raytracing calcula la luz por cada pixel de la escena en vez de por cada triangulo y es aquí donde pueden entrar los modelos híbridos donde la escena primero es calculada en 3D pero en vez de ser rasterizada es voxelizada en mayor o menos grado, es decir, que en vez de convertir la escena en un espacio bidimensional la convertimos en un espacio tridimensional compuesto por voxeles (pixeles volumetricos) para así poder almacenar la trayectoría de los rayos de luz que traviesan la escena,  dicha información se guardará en una estructura de datos espacial que puede ser una de las dos siguientes o no… Como ya veremos más adelante.

El proceso de voxelización de la escena desde la GPU sigue el siguiente pipeline:

voxelization

Dicho proceso se le puede llamar «Diferido» por el hecho que no ilumina directamente la escena antes de la voxelización, lo cual sería una perdida de tiempo enorme.En cuanto a la forma de almacenar los datos son las siguientes:

KD-Tree

Es la más precisa de ambas ya que lo que permite es almacenar el comportamiento de la luz de manera más local con los objetos.

kdtree

Dado que el Raytracing trabaja a nivel de pixel lo que permite esto es una precisión del mapa de la iluminación de la escena por lo que el tamaño de los voxeles generados no es uniforme en toda la escena sino según la intensidad y el area ocupada en cada fuente luz.

kDtree2

El problema es que requiere una enorme capacidad de computación trabajar con un KD-Tree es por ello que se esta hablando del uso de un tipo de estructura de datos especial más simple para el renderizado a tiempo real de la luz de tres rebotes.

Octree

El Octree también divide la escena en voxeles pero lo hace de manera uniforme y no según la energia y area ocupada por fuente de luz en el espacio 3D.

octree

La estructura es el de un arbol de 8 nodos, mientras que el KD-Tree era un arbol binario que iba generando ramas no de manera regular aquí las ramas son siempre regulares.

400px-Octree2.svg

 

Cuando hacemos que una fuente de luz atraviese el Octree como si fuese un espacio trimensional no tenemos tanta precisión como un KD-Tree y no es la misma precisión que con el Raytracing donde el calculo se hace a nivel de pixel, es decir… La iluminación de tres rebotes utilizando un Octree no es tan precisa como el Raytracing para iluminación global  (L=E+KL+K2L)  pero si que consigue una mejor calidad de imagen que el Raytracing simple (L=E+KL) aunque dado que las GPUs tienen enormes problemas para trabajar con bases de datos espaciales se esta buscando la forma de aplicar voxelización sin tener que almacenar los datos en una estructura de datos espacial porque su generación consume una cantidad de recursos increible.

svocost2

Fijaos como la construcción del Octree en este caso se come una buena parte del tiempo de renderizado, es por ello que se esta promoviendo el uso de métodos para al renderizado a tiempo real que obvian el uso de los Octrees u otras estructuras de datos espaciales.

No uso de estructura de datos.

Los voxeles no tienen porque almacenarse en un KD-Tree o en un Octree, la forma más simple de voxelizar en OpenGL es almacenar cada uno de los voxeles (que al fin y al cabo no son otra cosa que un cubo) como un Vertex Buffer Object.El VBO en OpenGL (Vertex Buffer en Direct3D) es el hecho de poder almacenar información de vectores en el espacio tridimensional dentro de la cache para vertices de la GPU para ser procesados de manera más rápida, es decir que en vez de generar una estructura de datos compleja para almacenar lo que hacemos es una colección de tiles en un espacio tridimensional uniforme y cada uno de estos tiles se almacena en la memoria interna de la GPU, del shader para ser más concreto.

En DX12 Microsoft ha añadido un elemento llamado Volume Tiled Resources:

volume-tiled-resources

En realidad dado que ya no hay separación para pixel y vertex shaders los que llamamos vertex buffer sirve también como pixel/fragment buffer y viceversa. Es bajo este mismo concepto que Sony hablo de aplicar iluminación global (3 rebotes) en su hardware sin tener que utilizar el Octree.

Axxtgrx

La precisión en la calidad de la iluminación es peor que utilizando el Octree pero la tasa de fotogramas es más alta. Utilizando un Octree para una escena con iluminación global a 1080P30 necesitamos la potencia de una GeForce 680 (3 TFLOPS) lo cual esta muy lejos de los 1.8 TFLOPS de la GPU de PS4, no obstante no tengo duda que los juegos de PS Neo aplicarán esta técnica de iluminación para marcar diferencias respecto a los juegos en la PS4 estándar.

ResultsVoxelsPS4

Existe un amplio margen de mejora y esto no va a ser solo para PS4 y PS «Neo» sino que se va a ver seguramente en Xbox Scorpio y en juegos futuros. La ventaja que tiene la iluminación de tres rebotes es que permite realizar escenas más realistas sin tener que tocar del trabajo humano de los artistas dado que las fuentes de luz aparecen de manera dinámica en cada fotograma y no son simuladas.

Métodos híbridos.

Se conocen como métodos híbridos aquellos basados en combinar Rasterización y Raytracing para la generación de la escena, no es un método que se utilice mucho por la enorme cantidad de calculos que necesita y por el momento solo la serie Wizard de los PowerVR de Imagination ha creado una GPU (y solo tienen un modelo) capaz de combinar ambas técnicas por hardware.

El PowerVR GR6500 es el procesador gráfico de marras como se puede ver tiene una serie de unidades para el Raytracing:

1_PowerVR GR6500 GPU - PowerVR Wizard GPUs

En este caso el cálculo de los rayos de la escena no se hace a través de un algoritmo por software en los shaders sino que lo hace utilizando una unidad especializada para ello que es la RTU. Hay que tener en cuenta que los PowerVR están diseñados utilizando el renderizado en diferido por tiles donde el proceso de composición de la escena es el mismo que en cualquier GPU que utilice dicho método (sobre el renderizado en diferido ya hable en la tercera entrega).

GBufferPipeline

En este caso no es para la iluminación de tres rebotes sino para una iluminación indirecta de mayor precisión gracias al uso del raytracing para calcular la iluminación de la escena:

DeferredRays

rending2

En este caso la complejidad del Raytracing es de L=E+KL pero no se llegaría al Raytracing para la iluminación global (L=E+KL+K2L) pero si la calidad de las imagenes si que es mejor que la iluminación indirecta a través de rasterización.

17_Ray tracing in games_PowerVR Ray Tracing - rasterized rendering-1-label

resize

No obstante en la industria las tecnologías propietarias no tienen futuro alguno por lo que esto ha caído en el olvido y en desuso, la idea no es mala pero he pensado que merecía un espacio en la entrada porque tarde o temprano se me iba a plantear. ¿Pero es posible que veamos métodos híbridos? Es posible pero en este caso sería a través de los shaders y el rendimiento es pésimo en ese aspecto por lo que lo mejor al igual que el rasterizado tiene una serie de algoritmos comunes que se hacen a través de las procesadores de función fija que se aplicaran los necesarios para el raytracing como es el caso de la unidad RTU del GR6500 de Imagination pero el único motivo por el cual no se aplican es porque no hay demanda para el uso de sistemas híbridos por lo que es un pez que se muerde la cola en este caso.

Es más, un hardware capaz de trazar los rayos no solo sería bueno para el Raytracing sino también en la voxelización, por lo que no dudo que en un futuro veamos una unidad de este tipo para trazar de manera automática la trayectoria de la iluminación en el espacio voxelizado, al fin y al cabo el algoritmo es general tanto para la voxelización como para el raytracing, solo es aplicar la siguiente formula en cada uno de los rayos de luz que traviesan la escena:

lightingformula

De aquí a que veamos una unidad así en una GPU pasará un tiempo, no obstante la lógica es que la acabemos viendo inicialmente como una unidad de función fija para luego ir evolucionando de manera programable, de la misma manera que ocurrió con el añadido de las unidades de subdivisión de primitivas (teselación).

Y con esto acabamos la serie de cuatro entradas sobre iluminación.