25 de diciembre de 2009

CGI: parte III

Para el caso de los objetos definidos por ecuaciones (llamadas primitivas), el cómo determinar si un rayo de visión alcanza un objeto es trivial: basta con resolver el sistema de ecuaciones compuesto por la ecuación del rayo, y la ecuación que define el objeto.

Pensad en una recta (el rayo) y una esfera. Se pueden dar 3 casos:
  • la recta y la esfera no se tocan: eso significaría que en el píxel correspondiente a ese rayo no se dibuja la esfera.
  • la recta y la esfera se tocan en un punto.
  • la recta y la esfera se tocan en dos puntos: se escoge el más cercano a la cámara.
(Esto es en el caso de esferas; para poder dibujar objetos distintos, el programa tiene que resolver distintos sistemas de ecuaciones, uno detrás de otro, para cada píxel de la escena.)

Una vez que se sabe el punto del objeto que ha sido alcanzado por el rayo, se calcula el vector normal de ese punto, que es el perpendicular a la superficie del objeto: en el caso de una esfera, las normales apuntan todas hacia afuera (como púas de un erizo).
Por medio de ecuaciones normales y corrientes para cualquiera que haya estudiado Matemáticas con Claudio (qué COU me dió el mamón) se calcula el ángulo del rayo con  vector normal. También se calcula el ángulo que formaría un rayo desde la fuente de luz de la escena, con ese punto. Al final queda una ecuación relativamente sencilla:

I = L*Kespecular*(vluz·vrayo)+L*Kdifuso*(vnormal·vrayo)+Kambiente

Kespecular, Kdifuso y Kambiente son coeficientes de cada objeto: definen su comportamiento ante la luz: su color, vamos. L es la intensidad de la fuente luminosa. La operación · es el producto vectorial, que para 2 vectores devuelve un número entre +1 y -1, dependiendo del ángulo que forman. I es la intensidad de luz devuelta por el objeto.

Ya está. En resumen:
  1. Se lanza un rayo desde la cámara pasando por un píxel de la escena.
  2. Se comprueba si choca con un objeto.
  3. Si no lo hace, el píxel es del color del fondo. Si lo hace, calcular en qué punto intersecta con qué objeto, y calcular la intensidad de luz I de ese punto de ese objeto.
  4. Seguir p'alante con los demás píxeles.

Y por encima, un par de aclaraciones:
  • la ecuación es para, digamos, blanco y negro, si se quiere color, hay que repetirla (cambiando los coeficientes y la intensidad de la fuente luminosa) por cada componente (rojo, verde, y azul).
  • se supone que la luz pasa a la cámara a través de un agujero infinitamente pequeño, es decir una cámara estenopeica (pinhole camera): una cámara oscura sin lente.
  • las sombras están tiradas de calcular, si el rayo de luz que lanzas desde la fuente impacta con un objeto no-transparente antes que con tu objeto, está en sombra.
  • el rayo puede pasar por un objeto semi-transparente, que le da parte de color al píxel, si el índice de refracción del objeto es distinto de 0, el rayo cambia de dirección y se seguiría calculando con qué objetos colisiona, añadiendo el resultado de los cálculos al color total.
  • se puede simular la niebla de una forma muy sencilla: como se sabe a qué distancia (3D) está el punto que estás proyectando en 2D, le añades el color de la niebla multiplicado por esa distancia:;cuando más lejos esté el objeto, más color de niebla tendrá.
  • la atenuación de una fuente luminosa, lo mismo, la intensidad de la fuente se divide por la distancia al punto del objeto a iluminar.
  • el efecto de profundidad de campo (Jota_, esto va por ti) es una guarrada de calcular, ya que se basa en que la luz no pasa por un agujero infinitamente pequeño a la "cámara", sino que pasa por uno grande (definido por la apertura del diafragma). Por lo tanto si el objeto está más o menos lejos de la distancia focal, hay que lanzar varios rayos por cada píxel, cada uno cruzando la "lente" por un lugar ligeramente diferente, y promediarlos.
  • hacer que las sombras no tengan bordes "duros" es un problema parecido: las fuentes luminosas en el mundo real no tienen tamaño 0, definido por un punto, sino un área, de modo que los bordes de las sombras se tienen que calcular lanzando rayos aleatoriamente desde la superficie de la fuente luminosa y promediándolos luego.


Qué bonico me ha salido el blob.

Esto es para el caso de objetos basados en primitivas (conos, esferas, cubos, prismas, superficies de revolución, toroides).  Esta forma de generar escenas se denomina trazado de rayos (ray-tracing).
¿Pero qué pasa con los objetos no definidos por primitivas, como los Na'vi de "Avatar"?

2 comentarios:

Brusete dijo...

Y un pene? cuales son las posibles aplicaciones de esto en el mundo del porno? Respuestas, exijo respuestas!!

Patman dijo...

Pues (aparte de "Watchmen") se ve uno hecho por ordenador en "Irreversible" de Gaspar Noé.