domingo, 20 de junio de 2010

Real Time Radiosity - Intro

Dicen que una vez Sábato (que además de escritor, ensayista y pintor aficionado, es físico) estaba dando una charla de relatividad general a unos ingresantes a ingeniería. Luego de la charla les preguntó, si habian entendido, a lo cual se hizo el silencio... Bueno, dijo, no se hagan problema, vamos a simplificar la teoría original para que se comprenda mejor, y volvió a explicar, esta vez en términos mas simples. Al finalizar la exposición volvió a preguntar si habían entendido y de nuevo el mismo silencio.. Entonces, simplificó aún mas la teoría, y al finalizar y preguntarle a los alumnos si esta vez habían entendido, todos dijeron: si profe, ahora si entendimos. Les dijo: bueno, eso que vimos NO es la relatividad general.

No le hagán caso al título del post, lo que voy a presentar no es un algoritmo de radiosity, y lo real-time es discutible.
Pero si es un algoritmo de iluminación global y que funciona lo suficientemente rápido para usarse en un entorno interactivo. Como el muy largo, lo voy a meter en varios post, en la medida que tenga tiempo.




INTRODUCCION

Para una descripcion detallada del algoritmo de radiosity:
http://en.wikipedia.org/wiki/Radiosity_(3D_computer_graphics)

La radiosidad es la cantidad de energía que sale de una superficie x unidad de tiempo, que se puede expresar con esta ecuación :





Bi es la radiosidad de la superficie i. El primer término esta relacionado con la luz que emite la superficie. El segundo término representa la cantidad de luz que refleja proveniente de cualquier otra superficie y depende de la orientacion relativa de ambas superficies, se expresa con un factor llamado Form Factor o View Factor. Este factor es puramente geométrico y no varía si la escena y fuentes de luz son estáticas, lo que motivó a numerosos algoritmos para pre-calcular la radiosidad (Ver: PRT Engine = Pre-computed Radiance Transfer).

Ecuación del form factor
El Form Factor entre 2 superficies i,j representa la fracción de la energia total que sale de la superfice i y llega a la superfice j.

En la práctica el form factor esta multiplicado por un factor de visiblidad H(i,j), que es 1 si la sup. i es visible desde la sup j o cero si no les.

La implementación estandard de esta ecuación asume que la superficie i es lo suficientemente pequeña para tomarse como un punto y las integrales se aproximan como una sumatoria. Luego se introducen algunas restricciones, usualmente se asume que la energia se mantiene constante dentro de una habitación o caja.
La solución del algoritmo requiere calcular para cada par de superficies i, j (i!=j) el form factor Fi,j. Esto genera un sistema de ecuaciones lineales expresado como una matriz llamada "full matrix radiosity solution".

Usualmente esta matriz se resuelve en forma progresiva, en lo que se llama: Progressive Radiosity Algorithm. En cada interacción se selecciona un patch i, se calculan los form factors Fij para todo j. Luego para cada superfice j se actualiza la cantidad de energia recibida del patch i (usando los Fij previamente calculados) y finalmente se pone en cero la cantidad de energia de la superficie i. Esto se repite para cada patch. Hay varios algoritmos que resuelven esto desde la GPU, utilizando una aproximacion por hemicubos para calcular los Fij. Para ello en cada paso se dibuja la escena desde el pto de vista de cada patch i utilizando una proyeccion sobre el hemicubo. Luego se suma la cantidad de energia que se almacena en alguna estructura auxiliar. Este proceso se repite para cada pach, y al finalizar se puede presentar la escena calculada hasta ese momento. En el primer paso el unico patch que tiene energia es la fuente luminosa. Al dibujar desde cada patch, solo los patch que "pueden" ver la fuente luminosa sumarán energia. En el segundo paso, la fuente luminosa ya habrá vaciado su energía, pero ahora varios patchs tendran energía acumulada, que ahora llegara a otros patch. En cada paso se refina la solución progresivamente.

-------------------------------------

Inspirados por el algoritmo de radiosity queremos implementar una versión (sumamente) simplificada para que se pueda utilizar en tiempos interactivos (entre 3 a 10 fps). El algoritmo está diseñado para aplicaciones usualmente off-line (diseño de interiores, arquitectura, etc) , en las que se requiere pre-visualizar el modelo de iluminación en el momento de diseño como paso previo, antes de obtener un render de calidad fotográfica.
La implementacion stadard parte de dibujar todo desde cada superficie, para poder presentar la primer escena primero hay que terminar de dibujar cada uno de los patch, con lo cual para los tiempos que queremos lograr no parece factible con el hardware actual y la cantidad de patchs que usualmente necesitamos.

-------------------------------------
ALGORITMO:

Paso 1: Fuente de Luz Principal.
Partimos de la fuente luminosa j y para cada superficie i que es alcanzada por j calculamos el Form Factor actualizando luego la cantidad de energia de j que va a ir a parar a i. En este primer paso ya podemos dibujar algo: el resultado corresponde a tomar solo la iluminación directa sin tener en cuenta ningún rebote. Las superfices que están en areas iluminadas tendrán una cierta intensidad de luz y las demás estarán totalmente oscuras.

Paso 2: Rebotes primarios.
En el segundo paso tenemos varios (cientos o miles) de superficies iluminadas, que por ende, se convierten en fuentes luminosas secundarias. Como no podemos repetir el mismo proceso para todas ellas, tenemos que seleccionar solo algunas de ellas, (con algún criterio específico). El proceso es idéntico (más alla del muestreo) al primer paso, y al finalizar tenemos una imagen que tiene en cuenta los rebotes primarios.

Paso 3: Rebotes secundarios.
El paso 2 se podría repetir un cierto numero de veces dependiendo de la cantidad de polígonos, la calidad requerida, la cantidad de fuentes secundarias (o terciarias, etc) que se tomen en cada paso. Teniendo en cuenta que en cada rebote solo una parte de la energia asociada al rayo es reflejada, y la otra es absorbida por la superfice, los rebotes primarios tienen mucho mas efecto que los siguientes, y asi sucesivamente, por lo cual en el rebote secundario solo tomamos un único rayo desde la fuente de luz secundaria: el rayo reflejado (sobre la normal de la superfice).

En síntesis:

En la luz principal se toman algunos de los rayos dentro del cono de luz para generar una pequeña cantidad de luces secundarias. Por su parte en las luces secundarias se toma un UNICO rayo en el centro del cono de luz para generar un UNICA luz terciaria. Y para las luces terciarias no se toma NINGUN otro rayo de luz, de forma que el algoritmo converge rápidamente.

En la próxima van detalles de implementación....

1 comentario: